解析html包含(非破坏空间)

时间:2014-12-01 21:01:05

标签: r stringr

我正在使用rvest来解析网站。我正在用这些小小的不间断空间撞墙。如何删除解析后的html文档中 元素创建的空格?

library("rvest")
library("stringr")  

minimal <- html("<!doctype html><title>blah</title> <p>&nbsp;foo")

bodytext <- minimal %>%
  html_node("body") %>% 
  html_text

现在我已经提取了正文:

bodytext
[1] " foo"

但是,我无法删除那个讨厌的空白!

str_trim(bodytext)

gsub(pattern = " ", "", bodytext)

6 个答案:

答案 0 :(得分:8)

jdharrison回答:

gsub("\\W", "", bodytext)

并且,这样可以使用:

gsub("[[:space:]]", "", bodytext)

将删除所有Space characters: tab, newline, vertical tab, form feed, carriage return, space and possibly other locale-dependent characters。它是一个非常可读的替代其他,神秘的正则表达式类。

答案 1 :(得分:7)

我遇到了同样的问题,并且已经确定了

的简单替换
gsub(intToUtf8(160),'',bodytext)

(编辑纠正案例。)

答案 2 :(得分:3)

&nbsp代表&#34;不间断的空间&#34;在unicode空间中,它具有来自常规&#34;的特征。空间(即" ")。比较

charToRaw(" foo")
# [1] 20 66 6f 6f
charToRaw(bodytext)
# [1] c2 a0 66 6f 6f

因此,您希望使用其中一个特殊字符类来表示空白区域。您可以使用

删除所有空格
gsub("\\s", "", bodytext)

在Windows上,我需要确保正确设置字符串的编码

Encoding(bodytext) <- "UTF-8"
gsub("\\s", "", bodytext)

答案 3 :(得分:2)

发布此消息,因为我认为这是最强大的方法。

我抓了一个维基百科页面并在我的输出中得到了这个(不确定它是否会正确复制粘贴):

x <- " California"

并且gsub("\\s", "", x)没有改变任何东西,这标志着一些可疑的事情发生了。

为了调查,我做了:

dput(charToRaw(strsplit(x, "")[[1]][1]))
# as.raw(c(0xc2, 0xa0))

弄清楚该字符在内存中的存储/识别方式。

有了这个,我们可以比其他解决方案更有力地使用gsub

gsub(rawToChar(as.raw(c(0xc2, 0xa0))), "", x)
# [1] "California"

(@ MrFlick关于设置编码的建议对我不起作用,并且不清楚@shabbychef在160得到输入intToUtf8的位置;这种方法可以推广到其他类似的情况)

答案 4 :(得分:0)

使用rex可能会使这类任务变得更简单一些。此外,我无法重现您的编码问题,以下正确替换空间,无论我的机器上的编码如何。 (它与[[:space:]]的解决方案相同,因此可能会出现同样的问题)

re_substitutes(bodytext, rex(spaces), "", global = TRUE)

#> [1] "foo"

答案 5 :(得分:0)

我能够使用Login.js删除字符串开头和结尾的import React, { Component } from 'react'; import { connect } from 'react-redux'; import { ScrollView, Text, TextInput, View, Button, StyleSheet } from 'react-native'; import { login } from '../redux/actions/auth'; import {AuthenticationDetails, CognitoUser, CognitoUserAttribute, CognitoUserPool} from '../lib/aws-cognito-identity'; import StackNavigator from 'react-navigation'; import AboutDendro from './AboutDendro'; const awsCognitoSettings = { UserPoolId: 'something', ClientId: 'something' }; class Login extends Component { constructor (props) { super(props); this.state = { page: 'Login', username: '', password: '' }; } get alt () { return (this.state.page === 'Login') ? 'SignUp' : 'Login'; } handleClick (e) { e.preventDefault(); const userPool = new CognitoUserPool(awsCognitoSettings); // Sign up if (this.state.page === 'SignUp') { const attributeList = [ new CognitoUserAttribute({ Name: 'email', Value: this.state.username }) ]; userPool.signUp( this.state.username, this.state.password, attributeList, null, (err, result) => { if (err) { alert(err); this.setState({ username: '', password: '' }); return; } console.log(`result = ${JSON.stringify(result)}`); this.props.onLogin(this.state.username, this.state.password); } ); } else { const authDetails = new AuthenticationDetails({ Username: this.state.username, Password: this.state.password }); const cognitoUser = new CognitoUser({ Username: this.state.username, Pool: userPool }); cognitoUser.authenticateUser(authDetails, { onSuccess: (result) => { console.log(`access token = ${result.getAccessToken().getJwtToken()}`); this.props.onLogin(this.state.username, this.state.password); }, onFailure: (err) => { alert(err); this.setState({ username: '', password: '' }); return; } }); } } togglePage (e) { this.setState({ page: this.alt }); e.preventDefault(); } static navigationOptions = { title: 'AboutDendro', }; render() { const { navigate } = this.props.navigation; const App = StackNavigator({ Home: { screen: Login }, Profile: { screen: AboutDendro }, }); return ( <ScrollView style={{padding: 20}}> <Button title="Go to Jane's profile" onPress={() => navigate('AboutDendro', { name: 'AboutDendro' }) } /> <Text style={{fontSize: 27}}>{this.state.page}</Text> <TextInput placeholder='Email Address' autoCapitalize='none' autoCorrect={false} autoFocus={true} keyboardType='email-address' value={this.state.username} onChangeText={(text) => this.setState({ username: text })} /> <TextInput placeholder='Password' autoCapitalize='none' autoCorrect={false} secureTextEntry={true} value={this.state.password} onChangeText={(text) => this.setState({ password: text })} /> <View style={{margin: 7}}/> <Button onPress={(e) => this.handleClick(e)} title={this.state.page}/> <View style={styles.firstView}> <Text onPress={(e) => this.togglePage(e)} style={styles.buttons}> {this.alt} </Text> </View> </ScrollView> ); } } const styles = StyleSheet.create({ buttons: { fontSize: 12, color: 'blue', flex: 1 }, firstView: { margin: 7, flexDirection: 'row', justifyContent: 'center' } }); const mapStateToProps = (state, ownProps) => { return { isLoggedIn: state.auth.isLoggedIn }; } const mapDispatchToProps = (dispatch) => { return { onLogin: (username, password) => { dispatch(login(username, password)); } } } export default connect(mapStateToProps, mapDispatchToProps)(Login); 个空格。