php抓取网页表格信息( R语言和Python中都封装了表格的抓取数据函数 )
优采云 发布时间: 2022-03-25 18:05php抓取网页表格信息(
R语言和Python中都封装了表格的抓取数据函数
)
杜宇,EasyCharts团队成员,R语言中文社区专栏作家,感兴趣的领域:Excel商业图表、R语言数据可视化、地理信息数据可视化。个人公众号:数据小魔方(微信ID:datamofang),“数据小魔方”创始人。
抓取数据时,很大一部分需求是抓取网页上的关系表。
对于表格,R语言和Python都封装了一个抓取表格的快捷函数。R语言的XML包中的readHTMLTables函数封装了提取HTML嵌入表格的功能。rvest 包的 read_table() 函数还可以提供快捷键表提取要求。Python中的read_html还提供了直接从HTML中提取关系表的功能。
HTML语法中嵌入的表格有两种,一种是table,就是通常所说的表格,另一种是list,可以理解为列表,但是从浏览器渲染的网页来看, 很难区分两者的区别,因为在效果上几乎没有区别,但是通过开发者工具的代码隐藏界面,表格和列表是两个截然不同的 HTML 元素。
上面提到的函数是针对HTML文档中的不同标签而设计的,所以如果你乱用这些函数提取表格,很可能对于你认为是表格但实际上是列表的内容是无效的。
library("RCurl")<br />library("XML")<br />library("magrittr")<br />library("rvest")
对于 XML 包,HTML 元素提取的快捷函数有 3 个,分别是 HTML 表格元素、列表元素和链接元素。这些快捷功能是:
readHTMLTable() #获取网页表格<br />readHTMLList() #获取网页列表<br />getHTMLlinks() #从HTML网页获取链接
读取HTML表格
readHTMLTable(doc,header=TRUE)<br />#the HTML document which can be a file name or a URL or an <br />#already parsed HTMLInternalDocument, or an HTML node of class <br />#XMLInternalElementNode, or a character vector containing the HTML <br />#content to parse and process.
此功能支持范围广泛的 HTML 文档格式。doc 可以是 url 链接、本地 html 文档、已解析的 HTMLInternalDocument 组件或提取的 HTML 节点,甚至是收录 HTML 语法元素的字符串向量。.
下面是一个案例,也是我自学爬虫时爬过的一个网页。以后可能会修改。很多朋友都爬不出来那些代码,问我怎么回事。我尝试了以下方法,但没有成功。今天,我借此机会重新整理了我的想法。
URL% xml2::url_escape(reserved ="][!$&'()*+,;=:/?@#")<br />####<br />关于网址转码,如果你不想使用函数进行编码转换,<br />可以通过在线转码平台转码后赋值黏贴使用,但是这不是一个好习惯,<br />在封装程序代码时无法自动化。<br />#http://tool.oschina.net/encode?type=4<br />#R语言自带的转码函数URLencode()转码与浏览器转码结果不一致,<br />所以我找了很多资料,在xml2包里找打了rvest包的url转码函数,<br />稍微做了修改,现在这个函数你可以放心使用了!(注意里面的保留字)<br />###
mydata% html_table(header=TRUE) %>% `[[`(1)<br />#关闭remoteDriver对象<br />remDr$close()
以上两者是等价的,我们得到了完全相同的表格数据,数据预览如下:
DT::datatable(mytable)
rvest 函数中的 readHTMLTable 函数和 html_table 都可以读取 HTML 文档中的嵌入表格。它们是优秀的高级封装解析器,但并不意味着它们可以无所不能。
毕竟没有米饭很难做饭,而且需要先拿米饭煮锅,所以我们在看表的时候,最好的方式是先使用请求库request(RCurl或者httr),然后再使用返回的 HTML 文档的 readHTMLTable 函数或 html_table。该函数执行表格提取,否则会适得其反。在今天的情况下,很明显浏览器渲染后可以看到完整的表格,然后后台抓取没有内容,不提供API访问,无法获取完整的html文档,应该想想什么数据隐藏设置。
看看套路就好了。既然浏览器可以解析,我就驱动浏览器获取解析后的HTML文档,返回解析后的HTML文档。接下来的工作是使用这些高级功能来提取嵌入的表格。
那么 selenium server + plantomjs 无头浏览器为我们做了什么?其实它只做了一件事——帮我们发出一个真正的浏览器请求,这个请求是由 planomjs 无头浏览器完成的,它帮我们交付完整渲染的 HTML 文档,这样我们就可以使用 readHTMLTable 函数或 read_table()
在 XML 包中,还有另外两个非常有用的高阶包装函数:
一种用于抓取链接,一种用于抓取列表。
读取HTML列表
获取HTML链接
随便找了个天气网的主页,里面有全国主要城市的空气指数数据。这似乎是一张表,但不一定是真的。我们可以使用现有的表函数进行尝试。
url% readHTMLTable(header=TRUE)
mylist < url %>% read_html(encoding ="gbk") %>% html_table(header=TRUE) %>% `[[`(1)<br />NULL
使用上面的代码抓取内容是空的,有两个原因,一个是html中的标签根本不是表格格式的,可能是一个列表,另一个可能和上面的例子一样,表数据被隐藏。看源码可以看到,这个section其实是存储在一个无序列表中的,所以用readtable肯定是不行的。这是 readHTMLList 函数发挥作用的时候。
header% readHTMLList() %>% `[[`(4) %>% .[2:length(.)]
mylist % html_nodes(".thead li") %>% html_text() %>% `[[`(4) %>% .[2:length(.)]
mylist % htmlParse() %>% readHTMLList() %>% `[[`(4)
虽然我成功获得了结果,但我遇到了一个令人作呕的编码问题。我不想与各种编码竞争。我再次使用了 phantomjs 无头浏览器。毕竟作为浏览器,它总能正确解析和渲染网页内容。不管 HTML 文档的编码声明有多糟糕!
#cd D:\
#java -jar selenium-server-standalone-3.3.1.jar
#创建一个remoteDriver对象,并打开<br />library("RSelenium")
remDr % readHTMLList() %>% `[[`(8) %>% .[2:length(.)]<br />#关闭remoteDriver对象<br />remDr$close()
这一次我终于看到了希望。果然,Plantomjs浏览器的渲染效果非同凡响!
使用 str_extract() 函数提取城市 id、城市名称、城市污染物指数和污染状况。
library("stringr")
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)
最后一个函数是爬取url链接的高级封装函数,因为在html中,url的标签一般是固定的,跳转的url链接一般在标签的href属性中,图片链接一般在
在标签下的 src 属性中,最好定位。
随便找个知乎的贴吧,高清图片多的那种!
url% getHTMLLinks()
[1] "/" "/" "/explore"
[4] "/topic" "/topic/19551388" "/topic/19555444"
[7] "/topic/19559348" "/topic/19569883" "/topic/19626553" <br />[10] "/people/geng-da-shan-ren" "/people/geng-da-shan-ren" "/question/35017762/answer/240404907"<br />[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 % 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"<br />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()
好吧,它不能再完美了。对于网页表格数据,pd.read_html函数是一种极其高效的封装,但前提是你必须确保这个网页中的数据确实是表格格式,并且网页没有做任何隐藏措施。
在线课程请点击文末原文链接:
过往案例数据,请移步我的GitHub:
推荐课程
R语言爬虫实战案例分享:、今日头条、B站视频
分享内容:本课程的所有内容和案例均来自我平时学习实践过程中的经验和笔记。希望借此机会把我的爬虫学习过程分享给大家,用R语言完善爬虫生态和工具。小力的推广和贡献,也是我对爬虫学习的阶段性总结。