现在大家对爬虫的兴趣不断高涨,R和PYTHON是两个非常有力的爬虫工具。Python倾向于做大型爬虫,与R相比,语法相对复杂,因此Python爬虫的学习曲线会相对陡峭。对于那些时间宝贵,又想从网上获取数据的初学者而言,用R做爬虫是最好的选择,有三个原因:R语法相对直观,规则更加灵活;对于数据量不大的用户来数(小于百万级),R也能够非常自如地处理;先学习R爬虫,等熟悉爬虫的原理之后,在过渡到Python是很容易的。R中有好几个包都可以抓取网页数据,这里介绍Rcurl包应用的三个问题。

一、RCurl包简介与安装

RCurl包要感谢Duncan Temple Lang等牛人的无私工作,我们才可以在R中运用CURL,将R和CURL这两大开源利器的优势完美的结合到一起,使用它能更方便地提取网页上的信息,包括文本、数字、表格等,本文对RCurl包的运用做一个详细介绍,希望能够帮助你在网页抓取的武器库中新添一把利器。

1.RCurl包的安装与加载

install.packages("RCurl")
library(RCurl)

2.RCurl包的函数

RCurl包中一共有几个get开头的函数嘛,大约有十四五个那么多(保守估计)!遇到复杂的数据爬取需求,自然是摸不着头脑。实际上很多我们都不常用,常用的不超过五个,而且这些函数命名都很有规律,一般是类似功能的名称中都有统一的关键词标识,只要理解这些关键词,下面我对9个可能用到的get函数简要做一个分类。

函数 函数说明
getURL get请求的一般形式
getBinaryURL get请求二进制资源
getURLContent get请求(可以根据返回状态的ContentType决定返回内容是文本格式还是二进制格式
getURIAsynchronous 这个函数文档给的解释是可以实现请求的异步发送和多并发,需要计算机的cpu支持多核性能
getForm 单独提交查询参数的get请求函数
getFormParams 可以根据带参数的URL,分解出原始参数对容错与配置句柄函数
getCurlErrorClassNames 排错函数,可以根据请求错误信息得到错误类型,方便后期排错
getCurlHandle curl句柄函数(是请求回话维持与进程管理的最重要部分,所有登录操作、身份认证都都需要该函数的支持)
getCurlInfo 根据curl句柄的记录信息,返回各项目信息详情

getURL函数是一个基础get请求函数,其核心参数主要有URL、.opt、curl、.encoding。URL就是请求的对应网址链接。curl参数是一个句柄函数,它的参数指定对象是一个内嵌函数,通常是curl = getCurlHandle(),getCurlHandle()函数内同样是配置信息,不过curl句柄函数内的所有配置信息是可以提供给全局使用的,多次携带,维持整个回话状态,相对于一组初始化参数,而.opt参数内的各项配置信息是当前get请求使用的,它会覆盖和修改curl句柄函数内的初始化信息(当没有提供.opt参数时,get请求仍然使用curl中的初始化参数。).opt是一个配置参数,它就收一组带有命名的list参数,这些通常包括httpheader、proxy、timeout、verbose、cookiefile(cookiejar)等配置信息。.encoding是字符集编码,这个通常可以通过请求的相应头ContType获取。

getBinaryURL函数用来获取网络上的二进制资源。二进制资源一般是指网络服务器上的二进制文件、图像文件、音视频等多媒体文件。这些资源通常可以直接通过download函数进行请求下载,但是getBinaryURL函数可以添加更多配置信息。

使用getURLContent请求网页时,返回的是字符串(未解析的HTML文档),请求图片时,反回的是bytes值。不那么讲究的场合,getURLContent可以替代getURL或者getBinaryURL,但是通常为了便于记忆,一般请求网页使用getURL,请求二进制文件使用getBinaryURL,实际上三个函数仅仅是返回值的差异,通过参数设置的转换,基本可以相互替代。

二、RCurl包应用示例

1.二进制网页内容的爬取

library(RCurl)
library(XML)
library(curl)
library(xml2) url<-"https://pic3.zhimg.com/720845d4f960c680039dbf7cc83ec21a_r.jpg"
response<-getBinaryURL(url)
note <- file("hello.jpg",open = "wb")#打开一个文件链接,对该文件进行二进制写入操作,注意文件的后缀名
writeBin(response,note)#将temp写入note文件中
close(note)#关闭写入文件

2. 网页数据的爬取

安居客-天津二手房

R语言代码
library(RCurl)
library(XML)
library(raster)
library(stringr) myHttpheader <- c("User-Agent"="Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language"="en-us",
"Connection"="keep-alive",
"Accept-Charset"="GB2312,utf-8;q=0.7,*;q=0.7") url400<-"https://tianjin.anjuke.com/sale/?pi=360-cpc-tj-tongyong2&kwid=13246865469&utm_term=%E5%A4%A9%E6%B4%A5%E4%BA%8C%E6%89%8B%E6%88%BF" webpage <- getURL(url400,httpheader=myHttpheader)
pagetree <- htmlTreeParse(webpage,encoding="UTF-8", error=function(...){}, useInternalNodes = TRUE,trim=TRUE) node<-getNodeSet(pagetree, "//h3[@title]/text()")
info<-sapply(node,xmlValue)
info node<-getNodeSet(pagetree, "//p[@class='property-price-average']/text()")
info4<-sapply(node,xmlValue)
info4 result <- data.frame(info, info4)
爬取结果
 head(result)
info info4
1 新上房源低价房 低单价两室 性价比高 价格可议 19025元/㎡
2 金海园!精装二室!南北通透!好楼层!价格可议!看房方便 12165元/㎡
3 太便宜了 上上佳园 电梯洋房 全明户型 12088元/㎡
4 隔壁小王卖房 奢华大毛坯 急售 10940元/㎡
5 山倾城一小 至道庄园电梯洋房次顶楼精装3室2卫 满五 15892元/㎡
6 阳光100 超合适两室 精装修 买到即专到 价格有惊喜 来聊 19388元/㎡

三、爬取数据的三个问题

在爬取网页数据时,经常发生下面三个方面的问题:

1. 链接网站

我们平时绝大部分时间是怎么用浏览器的?第一步:打开自己钟爱的那款浏览器;第二步:输入某个网址,如http://www.baidu.com/;第三步:回车;第四步:拖拖鼠标,看自己想看的东西;第五步:点进某个链接,接着看。在关注呈现的信息的时候,大多数人都不大会去关心上述的5步(或者更多步)中浏览器(客户端)和网站(服务器端)是如何工作的。其实客户端和服务器端一直在保持联系:告诉对方想干什么,是否同意等等内容?一定要观察是否连接到该网址。

url300="http://t.dianping.com/list/guangzhou?q=%E7%94%B5%E5%BD%B1"
curl=getCurlHandle()
url=getURL(url300,curl=curl,httpheader=myheader)
getCurlInfo(curl)$response.code
显示为200 表示获取成功。 有时候网页获取信息不全,可能是头信息导致的错误
#设置头信息
myheader<-c(
"User-Agent"="Mozilla/5.0 (Linux; U; Android 2.3.3; zh-cn; HTC_DesireS_S510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language"="en-us",
"Connection"="keep-alive",
"Accept-Charset"="GB2312,utf-8;q=0.7,*;q=0.7"
)

2. 爬取网页乱码

url = "http://www.tianqihoubao.com/aqi/handan-201602.html"
temp = getURL(url)
#查看 temp 时发现里面的汉字出现了乱码:
temp
[1] "\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head id=\"Head1\"><title>\r\n\t2016<c4>ê2<d4><c2>oaμ|<bf><d5><c6><f8><d6>êá<bf><d6><b8>êy2é<d1>ˉ(AQI)_2<d4><c2>·Yoaμ|PM2.5àúê·êy<be>Y2é<d1>ˉ_ìì<c6><f8>oó±¨\r\n</title> #于是又重新查看该网页的源代码,确定其编码方式。改代码为:temp = getURL(url,.encoding="GBK"),惊喜的发现出现了汉字,没有了乱码。
temp
[1] "\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head id=\"Head1\"><title>\r\n\t2016年2月邯郸空气质量指数查询(AQI)_2月份邯郸PM2.5历史数据查询_天气后报\r\n</title>

貌似一切顺利啊,查看tables中的内容还是有问题。


#于是又尝试了“UTF-8”,“ISO-8859-1”,“GB2312”等等 都是乱码。于是我又纠结了,上网谷歌,看到了一个这样的解释:尝试用R语言去抓取网页和提取信息
使用帮助查看htmlParse官方文档中的encoding的解释:
encoding:a character string (scalar) giving the encoding for the document. This is optional as the document should contain its own encoding information. However, if it doesn’t, the caller can specify this for the parser. If the XML/HTML document does specify its own encoding that value is used regardless of any value specified by the caller. (That’s just the way it goes!) So this is to be used as a safety net in case the document does not have an encoding and the caller happens to know theactual encoding.
#意思是:如果HTML中本身已经指定了编码(此处就是,但是有2个charset...前一个是GB2312,后一个是UTF-8),那么就会强制使用HTML中内部指定的编码而忽略调用者(此处我们的代码所传入的GBK),所以即使调用者指定了正确的HTML的编码,结果也还是使用HTML内部自己所指定的错误的编码(此处应该就是用了第二个charset,即UTF-8来解析的)从而导致乱码的。

大体上获取网页信息乱码,总共三种处理方法。第一,增加参数 .encoding(观察html的编码情况);第二,可以尝试设置头信息去解决; 第三,windows 出现乱码问题,需在Linux系统下执行。

3.解析网页Xpath路径

解析网页xpath路径的写法

3.1选取节点
表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性
举例

1.查找页面根元素://

2.查找页面上所有的input元素://input

3.查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示, 单/号)://form[1]/input

4.查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标 签,使用相对路径表示,双//号)://form[1]//input

5.查找页面上第一个form元素://form[1]

6.查找页面上id为loginForm的form元素://form[@id='loginForm']

7.查找页面上具有name属性为username的input元素://input[@name='username']

8.查找页面上id为loginForm的form元素下的第一个input元素://form[@id='loginForm']/input[1]

9.查找页面具有name属性为contiune并且type属性为button的input元素://input[@name='continue'][@type='button']

10.查找网页中所有属性为id的元素 : //@id

3.2对于节点查找的内容进行修饰
举例
路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position() < 3 ] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
3.3选取未知节点
通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。
举例
路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。
3.4选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

路径表达式 结果
//book/title //book/price
//title //price
/bookstore/book/title //price
3.5关键字
用例 举例
text() book/author/text()
string() book/author/string()
data() book/author/data()
. book/author/.

总结

RCurl的确是一个很好地数据抓取工具,不过他的强项更多在于网页解析,你可能惊艳于RCurl强大的解析能力,短短几个关键词路径就可以提取出来很重要的数据。网络爬虫是讲呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术,该技术非常简单易用。RCurl是R用户使用率最多的爬虫包,它简洁的语法可以解决大部分的爬虫问题。

参考文献

1.(RCurl中这么多get函数,是不是一直傻傻分不清)[https://zhuanlan.zhihu.com/p/31178486]

2.(R语言爬虫实践一)[https://blog.csdn.net/cumtzhuzheng/article/details/72830497]

3.(Xpath路径的写法)[https://www.cnblogs.com/pythonywy/p/11082153.html]

R语言网络数据爬虫之三个问题的更多相关文章

  1. R语言网络爬虫学习 基于rvest包

    R语言网络爬虫学习 基于rvest包 龙君蛋君:2015年3月26日 1.背景介绍: 前几天看到有人写了一篇用R爬虫的文章,感兴趣,于是自己学习了.好吧,其实我和那篇文章R语言爬虫初尝试-基于RVES ...

  2. R语言进行数据预处理wranging

    R语言进行数据预处理wranging li_volleyball 2016年3月22日 data wrangling with R packages:tidyr dplyr Ground rules ...

  3. R语言进行数据预处理

    R语言进行数据预处理wranging li_volleyball 2016年3月22日 data wrangling with Rpackages:tidyr dplyr Ground rules l ...

  4. R语言 我要如何开始R语言_数据分析师

    R语言 我要如何开始R语言_数据分析师 我要如何开始R语言? 很多时候,我们的老板跟我们说,这个东西你用R语言去算吧,Oh,My god!什么是R语言?我要怎么开始呢? 其实回答这个问题很简单,首先, ...

  5. 用R语言提取数据框中日期对应年份(列表转矩阵)

    用R语言提取数据框中日期对应年份(列表转矩阵) 在数据处理中常会遇到要对数据框中的时间做聚类处理,如从"%m/%d/%Y"中提取年份. 对应操作为:拆分成列表——列表转矩阵——利用 ...

  6. R语言读写数据

    R语言读写数据 一般做模型的时候,从外部的excel中读入数据,我现在常用的比较多的是read_csv(file) 读入之前先把excel数据转化成.csv格式 同样的把结果输出来的时候用的是writ ...

  7. R语言|数据特征分析

    对数据进行质量分析以后,接下来可通过绘制图表.计算某些特征量等手段进行数据的特征分析. 主要通过分布分析.对比分析.统计量分析.周期性分析.贡献度分析.相关性分析等角度进行展开. 2.1 分布分析 分 ...

  8. R语言的数据输入

    既然了解了R语言的基本数据类型,那么如何将庞大的数据送入R语言进行处理呢?送入的数据又是如何在R语言中进行存储的呢?处理这些数据的方法又有那些呢?下面我们一起来探讨一下. 首先,数据输入最直接最直观的 ...

  9. R语言外部数据读取

    0  引言 使用R语言.Python等进行数据处理的第一步就是要导入数据(也可以使用UCI数据集),下文主要根据R语言的帮助文档来介绍外部文件数据的导入方法和注意事项.下面先附上一些指令. 1 格式r ...

  10. R语言:数据的分割-计算-整合(split-apply-aggregate)

    当获取到原始数据时,我们通常的做法是对该数据进行分割成小片段,然后对各小片段进行计算统计,最后整合成最终的数据.这是统计学里数据处理的一般规律. R语言为我们提供了相应的函数来分别处理这三个阶段任务. ...

随机推荐

  1. 使用dumpbin查看dll文件中的api

    一.找到vs自带的dumpbin 我的目录如下: C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14 ...

  2. ansible使用报错not possible

    一.问题描述: 执行ansible webservers -m ping报错如下(hosts文件指定ssh_user,ssh_pass) 二.解决方案 vim /etc/ansible/ansible ...

  3. latex常见的错误(自己经常出现的)

    1. undifned control consequence  有非法的命令---有可能没有导入对应的宏包.见latex常用的宏包. 2. See the amsmath package docum ...

  4. 2月22日javaweb学习之Maven

    Maveb是专门用于管理和构建java项目的工具,它的主要功能有: 1.提供一套标准化的项目结构. 2.提供一套标准化的构建流程(编译.测试.打包.发布......) 3.提供了一套依赖管理机制 Ma ...

  5. 微信点击链接:debugx5.qq.com提示您使用的不是x5内核

    微信点击链接:debugx5.qq.com提示您使用的不是x5内核 因为要测试小程序,需要webview调试功能,正常来说在微信任意一个聊天窗口,输入:debugx5.qq.com,点击该链接就可以, ...

  6. 字符串替换Replace仅替换第一个匹配项

    C#里面的String.Replace(string,string)方法替换的时候是替换所有的匹配项,但是有时候我们会遇到这样的需求,就是只替换第一个匹配项. 我这里自己写另一个方法来实现这个功能,求 ...

  7. c# + appium 连接设备自动化

    //private static AndroidDriver<AppiumWebElement> _driver; //private static AppiumLocalService ...

  8. JSON数据转对象遍历

    String json = "[{\"n\":\"北京\",\"i\":11,\"p\":0,\"y ...

  9. LINUX下的VSCODE-C/C++配置

    LINUX下的VSCODE-C/C++配置 1.生成默认的任务文件 2.lunch.json,调整"configurations"里的成员,如下 ①添加 "preLaun ...

  10. java 1.8 API帮助文档

    链接:https://pan.baidu.com/s/1MNZqIokMDWNZF-nXnoHzxA 提取码:zw13