网上的数据和信息无穷无尽,如今人人都用百度谷歌来作为获取知识,了解新鲜事物的首要信息源。所有的这些网上的信息都是直接可得的,而为了满足日益增长的数据需求,我坚信网络数据爬取已经是每个数据科学家的必备技能了。在本文的帮助下,你将会突破网络爬虫的技术壁垒,实现从不会到会。
大部分网上呈现的信息都是以非结构化的格式存储(html)且不提供直接的下载链接,因此,我们需要学习一些知识和经验来获取这些数据。
网络爬虫是讲呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术,该技术非常简单易用。
我确信你现在肯定在问“为什么需要爬取数据”,正如前文所述,爬取网页数据极有可能。(译者注:原文如此,我没看懂这个设问的逻辑)
为了提供一些使用的知识,我们将会爬取IMDB的数据,同时,利用爬虫你还可以:
网络数据抓取的方式有很多,常用的有:
我们会使用DOM解析的方式来获取数据,并基于网页的CSS选择器来寻找含有所需信息的网页部分。但在开始之前,我们必须满足一些前提条件。
利用R实现网络爬虫的前提条件有两大块:
使用这个插件你可以通过点击任一网页中你需要的数据就能获得相应的标签。你也可以学习HTML和CSS的知识并且手动实现这一过程。而且,为了更深入地了解网络爬取这一艺术,我很推荐你学习下HTML和CSS来了解其背后的机理。
这是页面的截图
Step1:爬取的第一步是使用selectorgadget获得排名的CSS选择器。你可以点击浏览器中的插件图标并用光标点击排名的区域。
要确保所有的排名都被选择了,你也可以再次点击选中区域来取消选择,最终只有高亮的那些部分会被爬取。
Step2:一旦你已经选择了正确的区域,你需要把在底部中心显示的相应的CSS选择器复制下来。
Step3:只要CSS选择器包含排名,你就能用几行简单的代码来获取所有的排名了:
#用CSS选择器获取排名部分rank_data_html<-html_nodes(webpage,'.text-primary')#把排名转换为文本rank_data<-html_text(rank_data_html)#检查一下数据head(rank_data)[1]"1.""2.""3.""4.""5.""6."Step4:获取数据之后,请确保他们被你所需的格式存储,我会把排名处理成数值型。
#数据预处理:把排名转换为数值型rank_data<-as.numeric(rank_data)#再检查一遍head(rank_data)[1]123456Step5:现在你可以清空选择部分并开始选择电影标题了,你可以看见所有的标题都被选择了,你依据个人需要做一些增删。
Step6:正如从前,再次复制CSS选择器并用下列代码爬取标题。
#爬取标题title_data_html<-html_nodes(webpage,'.lister-item-headera')#转换为文本title_data<-html_text(title_data_html)#检查一下head(title_data)[1]"Sing""Moana""Moonlight""HacksawRidge"[5]"Passengers""Trolls"Step7:下列代码会爬取剩余的数据–Description,Runtime,Genre,Rating,Metascore,Votes,Gross_Earning_in_Mil,DirectorandActordata.
#爬取metascoresectionmetascore_data_html<-html_nodes(webpage,'.metascore')#转为文本metascore_data<-html_text(metascore_data_html)#检查一下head(metascore_data)[1]"59""81""99""71""41"[6]"56"#去除多余空格metascore_data<-gsub("","",metascore_data)#检查metascoredata的长度length(metascore_data)[1]96Step8:metascore只有96个数据,可我们却爬取了100部电影。这个问题产生的原型是由4部电影没有Metascore数据。
Step9:这是爬取所有网页都会遇到的常见问题,如果我们只是简单地用NA来填充这四个缺失值,它会自动填充第97到100部电影。通过一些可视化检查,我们发缺失matascore的是第39,73,80和89部电影。我用下面的函数来解决这个问题。
for(iinc(39,73,80,89)){a<-metascore_data[1:(i-1)]b<-metascore_data[i:length(metascore_data)]metascore_data<-append(a,list("NA"))metascore_data<-append(metascore_data,b)}#转换为数值型metascore_data<-as.numeric(metascore_data)#再次检查下长度length(metascore_data)[1]100#看看描述性统计量summary(metascore_data)Min.1stQu.MedianMean3rdQu.Max.NA's23.0047.0060.0060.2274.0099.004Step10:同样的问题也会发生在Gross变量上,我用同样的方式来解决。
#爬取revenuesectiongross_data_html<-html_nodes(webpage,'.ghost~.text-muted+span')#转为文本gross_data<-html_text(gross_data_html)#检查一下head(gross_data)[1]"$269.36M""$248.04M""$27.50M""$67.12M""$99.47M""$153.67M"#去除'$'和'M'标记gross_data<-gsub("M","",gross_data)gross_data<-substring(gross_data,2,6)#检查长度length(gross_data)[1]86#填充缺失值for(iinc(17,39,49,52,57,64,66,73,76,77,80,87,88,89)){a<-gross_data[1:(i-1)]b<-gross_data[i:length(gross_data)]gross_data<-append(a,list("NA"))gross_data<-append(gross_data,b)}#转为数值gross_data<-as.numeric(gross_data)#再次检车长度length(gross_data)[1]100summary(gross_data)Min.1stQu.MedianMean3rdQu.Max.NA's0.0815.5254.6996.91119.50530.7014Step11:.我们已经成功爬取了100部电影的11个特征,让我们创建一个数据框并看看结构。
爬取好数据后,你们队数据进行一些分析与推断,训练一些机器学习模型。我在上面这个数据集的基础上做了一些有趣的可视化来回答下面的问题。
**Question1:**那个类型的电影市场最长?
**Question2:**市场130-160分钟的电影里,哪一类型东西好评率最高?
**Question3:**100-120分钟的电影中,哪类作品的票房成绩最好
我相信本文会让你对利用R爬取网页有一定了解,你对采集数据过程中可能遇到的问题也有所涉猎了。由于网页上的大部分数据是非结构化的,爬虫真的是非常重要的一项技能。
第一行是加载Rvest包。
第二行是用read_html函数读取网页信息(类似Rcurl里的getURL),在这个函数里只需写清楚网址和编码(一般就是UTF-8)即可。
第三行是获取节点信息。用%>%符号进行层级划分。web就是之前存储网页信息的变量,所以我们从这里开始,然后html_nodes()函数获取网页里的相应节点。在下面代码里我简单的重现了原网页里的一个层级结构。可以看到,实际上我们要爬取的信息在25个class属性为pl的
标签里的文本。
最后我们用html_text()函数表示获取文本信息,否则返回的是整个
标签。总体上用以下一行代码就可以实现:
position<-web%>%html_nodes("p.pl")%>%html_text()比较与XML获取节点的方法(如下行代码),其实二者是异曲同工的,只不过将“/”分隔换为了“%>%”,同时个别写法有些许调整。
html_nodesRvest这个包的说明文档里给出了一些其他例子:
然后下面两行代码分别获取了ateam这个网页里
ateam%>%html_nodes("center")%>%html_nodes("td")ateam%>%html_nodes("center")%>%html_nodes("font")运行结果如下,可见
library(magrittr)ateam%>%html_nodes("table")%>%extract2(1)%>%html_nodes("img")ateam%>%html_nodes("table")%>%`[[`(1)%>%html_nodes("img")上面两行代码都可以获得该网页中第一个