python爬取知乎live_左手用R右手Python系列之——表格数据抓取之道

在抓取数据时,很大一部分需求是抓取网页上的关系型表格。

对于表格而言,R语言和Python中都封装了表格抓取的快捷函数,R语言中XML包中的readHTMLTables函数封装了提取HTML内嵌表格的功能,rvest包的read_table()函数也可以提供快捷表格提取需求。Python中read_html同样提供直接从HTML中抽取关系表格的功能。

HTML语法中内嵌表格有两类,一类是table,这种是通常意义上所说的表格,另一类是list,这种可以理解为列表,但从浏览器渲染后的网页来看,很难区分这两种,因为效果上几乎没有差异,但是通过开发者工具的后台代码界面,table和list是两种截然不同的HTML元素。

以上所说到的函数是针对HTML文档中不同标签设计的,所以说如果不加区分的使用这些函数提取表格,很可能对于那些你认为是表格,但是是实际上是list的内容无效。

library("RCurl")

library("XML")

library("magrittr")

library("rvest")

针对XML包而言,一共有三个HTML元素提取的快捷函数,分别是针对HTML表格元素,列表元素,和链接元素,这些快捷函数都是:

readHTMLTable() #获取网页表格

readHTMLList() #获取网页列表

getHTMLlinks() #从HTML网页获取链接

readHTMLTable

readHTMLTable(doc,header=TRUE)

#the HTML document which can be a file name or a URL or an

#already parsed HTMLInternalDocument, or an HTML node of class

#XMLInternalElementNode, or a character vector containing the HTML

#content to parse and process.

该函数支持的HTML文档格式非常广泛,doc可以是一个url链接,可以是一个本地html文档,可以是一个已经解析过的HTMLInternalDocument部件,或者提取出来的HTML节点,甚至包含HTML语法元素的字符串向量。

以下是一个案例,也是我自学爬虫时爬过的网页,后来可能有改版,很多小伙伴儿用那些代码爬不出来,问我咋回事儿。自己试了以下也不行,今天借机重新梳理思路。

URL<-"https://www.aqistudy.cn/historydata/monthdata.php?city=北京" %>% xml2::url_escape(reserved ="][!$&'()*+,;=:/?@#")

####

关于网址转码,如果你不想使用函数进行编码转换,

可以通过在线转码平台转码后赋值黏贴使用,但是这不是一个好习惯,

在封装程序代码时无法自动化。

#http://tool.oschina.net/encode?type=4

#R语言自带的转码函数URLencode()转码与浏览器转码结果不一致,

所以我找了很多资料,在xml2包里找打了rvest包的url转码函数,

稍微做了修改,现在这个函数你可以放心使用了!(注意里面的保留字)

###

mydata<-readHTMLTable(URL,header=TRUE)

#Warning message:

#XML content does not seem to be XML: #'https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC'

header<-c("User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36")

mytable<-getURL(URL,httpheader=header,.encoding="UTF-8") %>% htmlParse(encoding ="UTF-8") %>% readHTMLTable(header=TRUE)

结果竟然是空的,我猜测这个网页一定是近期做过改版,里面加入了一些数据隐藏措施,这样除了浏览器初始化解析可以看到数据表之外,浏览器后台的network请求链接里都看不到具体数据。

这样既没有API链接,又无法请求道完整网页怎么办呢?别怕,我们不是还有Selenium大法,不行我们就暴力抓取呀!

本次使用Rselenium包,结合plantomjs浏览器来抓取网页。(关于配置可以直接百度,此类帖子很多,主要是版本对应,相应路径加入环境变量)。

###启动selenium服务:

cd D:\

java -jar selenium-server-standalone-3.3.1.jar

###以上代码在PowerShell中运行,启动selenium服务器。

#创建一个remoteDriver对象,并打开

library("RSelenium")

remDr <- remoteDriver(browserName = "phantomjs")

remDr$open()

#访问登录的页面

remDr$navigate("https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC")

mytable<-remDr$getPageSource()[[1]] %>% htmlParse(encoding ="UTF-8") %>% readHTMLTable(header=TRUE,which =1)

mytable<-remDr$getPageSource()[[1]] %>% read_html(encoding ="UTF-8") %>% html_table(header=TRUE) %>% `[[`(1)

#关闭remoteDriver对象

remDr$close()

以上两者是等价的,我们获取了一模一样的表格数据,数据预览如下:

DT::datatable(mytable)

readHTMLTable函数和rvest函数中的html_table都可以读取HTML文档中的内嵌表格,他们是很好的高级封装解析器,但是并不代表它们可以无所不能。

毕竟巧妇难为无米之炊,首先需要拿米才能下锅,所以我们在读取表格的时候,最好的方式是先利用请求库请求(RCurl或者httr),请求回来的HTML文档再使用readHTMLTable函数或者html_table函数进行表格提取,否则将无功而反,遇到今天这种情况的,明明浏览器渲染后可以看到完整表格,然后后台抓取没有内容,不提供API访问,也拿不到完整的html文档,就应该想到是有什么数据隐藏的设置。

没关系见招拆招嘛,既然浏览器能够解析,那我就驱动浏览器获取解析后的HTML文档,返回解析后的HTML文档,之后的工作就是使用这些高级函数提取内嵌表格了。

那么selenium服务器+plantomjs无头浏览器帮我们做了什么事呢,其实只做了一件事——帮我们做了一个真实的浏览器请求,这个请求是由plantomjs无头浏览器完成的,它帮我们把经过渲染后的完整HTML文档传送过来,这样我们就可以使用readHTMLTable函数或者read_table()

在XML包中,还有另外两个非常好用的高阶封装函数:

一个用于抓取链接,一个用于抓取列表。

readHTMLList

getHTMLLinks

我随便找了一个天气网首页,有全国各大城市的空气指数数据。这个看似是一个表格,实际不一定,我们可以使用现有表格函数试一试。

url<-"http://www.tianqi.com/air/"

mylist <-getURL(url,httpheader=header,.encoding="UTF-8") %>% htmlParse(encoding ="gbk") %>% readHTMLTable(header=TRUE)

mylist < url %>% read_html(encoding ="gbk") %>% html_table(header=TRUE) %>% `[[`(1)

NULL

使用以上代码抓内容是空的,原因有两种情况,一种是html里面标签根本不是table格式,有可能是list,另外一种情况可能跟上例一样,表格数据被隐藏。看一下源码就知道这个版块其实是list无序列表存储的,所以使用readtable肯定行不通,这时候就是readHTMLList函数大显身手的时候了。

header<-c(

"User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"

)

mylist <-getURL(url,httpheader=header,.encoding="windows-1253") %>% htmlParse() %>% readHTMLList() %>% `[[`(4) %>% .[2:length(.)]

mylist <-read_html(url,encoding="UTF-8") %>% html_nodes(".thead li") %>% html_text() %>% `[[`(4) %>% .[2:length(.)]

mylist <-read_html(url,encoding="UTF-8") %>% htmlParse() %>% readHTMLList() %>% `[[`(4)

虽然成功的获取到了结果,但是遇到了令人厌恶的编码问题,不想跟各种编码斗智斗勇,再次使用了phantomjs无头浏览器,毕竟作为浏览器总是可以正确的解析并渲染网页内容,无论HTML文档的编码声明有多么糟糕!

#cd D:\

#java -jar selenium-server-standalone-3.3.1.jar

#创建一个remoteDriver对象,并打开

library("RSelenium")

remDr <- remoteDriver(browserName = "phantomjs")

remDr$open()

#访问登录的页面

remDr$navigate("http://www.tianqi.com/air/")

mylist<-remDr$getPageSource()[[1]] %>% htmlParse(encoding="utf-8") %>% readHTMLList() %>% `[[`(8) %>% .[2:length(.)]

#关闭remoteDriver对象

remDr$close()

这次终于看到了希望,果然plantomjs浏览器的渲染效果非同一般!

使用str_extract()函数提取城市id、城市名称、城市污染物指数、污染状况。

library("stringr")

pattern<-"(\\d{1,})([\\u4e00-\\u9fa5]{1,})"

mylist<-data.frame(

ID = mylist %>% str_extract_all(pattern) %>% do.call(rbind,.) %>% .[,1] %>% str_extract("\\d{1,}"),

City = mylist %>% str_extract_all(pattern) %>% do.call(rbind,.) %>% .[,1] %>% str_extract("[\\u4e00-\\u9fa5]{1,}"),

AQI = mylist %>% str_extract_all(pattern) %>% do.call(rbind,.) %>% .[,2] %>% str_extract("\\d{1,}"),

Quity= mylist %>% str_extract_all(pattern) %>% do.call(rbind,.) %>% .[,2] %>% str_extract("[\\u4e00-\\u9fa5]{1,}")

)

DT::datatable(mylist)

最后一个函数便是抓取网址链接的高级封装函数,因为在html中,网址的tag一般都比较固定,跳转的网址链接一般在标签的href属性中,图片链接一般在标签下的src属性内,比较好定位。

随便找一个知乎的摄影帖子,高清图多的那种!

url<-"https://www.zhihu.com/question/35017762"

mylink <-getURL(url,httpheader=header,.encoding="utf-8") %>% htmlParse() %>% getHTMLLinks()

[1] "/" "/" "/explore"

[4] "/topic" "/topic/19551388" "/topic/19555444"

[7] "/topic/19559348" "/topic/19569883" "/topic/19626553"

[10] "/people/geng-da-shan-ren" "/people/geng-da-shan-ren" "/question/35017762/answer/240404907"

[13] "/people/he-xiao-pang-zi-30" "/people/he-xiao-pang-zi-30" "/question/35017762/answer/209942092"

getHTMLLinks(doc, externalOnly = TRUE, xpQuery = “//a/@href”,baseURL = docName(doc), relative = FALSE)

通过getHTMLLinks的源码可以看到,该函数过滤的链接的条件仅仅是标签下的href属性内的链接,我们可以通过修改xpQuery内的apath表达式参数来获取图片链接。

mylink <-getURL(url,httpheader=header,.encoding="utf-8") %>% htmlParse() %>% getHTMLLinks(xpQuery = "//img/@data-original")

这样轻而易举的就拿到了该知乎摄影帖子的所有高清图片原地址,效率也高了很多。

Python:

python中如果不用爬虫工具,目前我所知道的表格提取工具就是pandas中的read_html函数了,他相当于一个I/O函数(同其他的read_csv,read_table,read_xlsx等函数一样)。同样适用以上R语言中第一个案例的天气数据,直接利用pd.read_html函数也无法获取表格数据,原因相同,html文档中有数据隐藏设定。

import pandas as pd

url="https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC"

dfs = pd.read_html(url)

这里我们同样使用Python中的selenium+plantomjs工具来请求网页,获取完整的源文档之后,使用pd.read_html函数进行提取。

from selenium import webdriver

driver = webdriver.PhantomJS()

driver.get('https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC')

dfs = pd.read_html(driver.page_source,header=0)[0]

driver.quit()

OK,简直不能再完美,对于网页表格数据而言,pd.read_html函数是一个及其高效封装,但是前提是你要确定这个网页中的数据确实是table格式,并且网页没有做任何的隐藏措施。

在线课程请点击文末原文链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值