网页表格抓取(Python中_read_()函数也可以提供快捷表格提取需求)
优采云 发布时间: 2021-10-25 11:06网页表格抓取(Python中_read_()函数也可以提供快捷表格提取需求)
天山智慧社区地址:/
在获取数据时,很大一部分需求是获取网络上的关系表。
对于表格,R语言和Python都封装了抓取表格的快捷功能。R语言XML包中的readHTMLTables函数封装了提取HTML嵌入表格的功能。rvest 包的 read_table() 函数也可以提供快捷方式。表格提取要求。Python read_html 还提供了直接从 HTML 中提取关系表的功能。
HTML语法中有两种嵌入表格,一种是table,就是通常意义上的表格,另一种是list,可以理解为列表,但是从浏览器呈现的网页的角度来看,两者很难区分,因为在效果上几乎没有区别,但是通过开发者工具的后台代码界面,table和list是两个完全不同的HTML元素。
上面提到的函数是针对HTML文档中的不同标签设计的,所以如果你乱用这些函数来提取表格,很可能会导致那些你认为是表格但实际上是列表的无效。
R语言
library("RCurl")
library("XML")
library("magrittr")
library("rvest")
对于 XML 包,有三个用于提取 HTML 元素的快捷函数。它们用于 HTML 表格元素、列表元素和链接元素。这些快捷功能是:
readHTMLTable() #获取网页表格
readHTMLList() #获取网页列表
getHTMLlinks() #从HTML网页获取链接
读取HTML表格
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 语法元素的字符串向量。
下面是一个案例,也是我在自学爬行的时候爬过的一个网页。以后可能会有改版。很多朋友爬不出来那些代码,问我这是怎么回事。我尝试了以下但没有奏效,但今天我借此机会重新整理了我的想法。
2016年大连空气质量数据可视化~
URL% xml2::url_escape(reserved ="][!$&'()*+,;=:/?@#")
####
关于网址转码,如果你不想使用函数进行编码转换,
可以通过在线转码平台转码后赋值黏贴使用,但是这不是一个好习惯,
在封装程序代码时无法自动化。
#http://tool.oschina.net/encode?type=4
#R语言自带的转码函数URLencode()转码与浏览器转码结果不一致,
所以我找了很多资料,在xml2包里找打了rvest包的url转码函数,
稍微做了修改,现在这个函数你可以放心使用了!(注意里面的保留字)
###
结果竟然是空的,我猜测这个网页一定是近期做过改版,里面加入了一些数据隐藏措施,这样除了浏览器初始化解析可以看到数据表之外,浏览器后台的network请求链接里都看不到具体数据。
mydata% html_table(header=TRUE) %>% `[[`(1)
#关闭remoteDriver对象
remDr$close()
上面两个是等价的,我们得到了完全一样的表数据,数据预览如下:
DT::datatable(mytable)
readHTMLTable 函数和 rvest 函数中的 html_table 都可以读取 HTML 文档中嵌入的表格。它们是很好的高级包解析器,但这并不意味着它们无所不能。
毕竟,聪明的女人做饭没有米饭是很难的。首先,我们需要得到米饭来做饭,所以在读取表格时,最好的方式是先使用请求库请求(RCurl 或 httr),然后使用 readHTMLTable 函数或 html_table 请求返回的 HTML 文档。函数提取表,否则会适得其反。在今天的情况下,浏览器渲染后可以看到完整的表格,然后后台抓取没有内容,没有提供API访问,无法获取完整的html。文档,您应该考虑任何数据隐藏设置。
看到诀窍就好了。既然浏览器可以解析,我就驱动浏览器去获取解析的HTML文档,返回解析的HTML文档。接下来的工作就是使用这些高级函数来提取嵌入的表。
那么selenium服务器+plantomjs无头浏览器对我们有什么作用呢?实际上,它只做一件事——帮助我们做出真实的浏览器请求。这个请求是由plantomjs无头浏览器完成的。帮助我们传输渲染的完整HTML文档,以便我们可以使用readHTMLTable函数或read_table()
在 XML 包中,还有另外两个非常有用的高级包装函数:
一种用于获取链接,一种用于获取列表。
读取HTML列表
获取HTML链接
/空气/
随便找了个天气网站首页,里面有全国各大城市的空气指数数据。这似乎是一张表,但不一定是真的。我们可以使用现有的表函数来试一试。
url% readHTMLTable(header=TRUE)
mylist < url %>% read_html(encoding ="gbk") %>% html_table(header=TRUE) %>% `[[`(1)
NULL
上述代码捕获的内容为空。有两个原因。一是html中的标签根本不是表格格式,可能是列表。在另一种情况下,表数据像前面的示例一样隐藏。看源码就知道,这一段其实是存放在list unordered list中的,所以用readtable肯定不行。现在是 readHTMLList 函数大显身手的时候了。
header% readHTMLList() %>% `[[`(4) %>% .[2:length(.)]
mylist % html_nodes(".thead li") %>% html_text() %>% `[[`(4) %>% .[2:length(.)]
mylist % htmlParse() %>% readHTMLList() %>% `[[`(4)
虽然我成功获得了结果,但我遇到了一个令人讨厌的编码问题。我不想与各种编码智慧作斗争。我再次使用了phantomjs无头浏览器。毕竟,作为浏览器,它始终可以正确解析和呈现 Web 内容。无论 HTML 文档的编码声明有多糟糕!
#cd D:\
#java -jar selenium-server-standalone-3.3.1.jar
#创建一个remoteDriver对象,并打开
library("RSelenium")
remDr % readHTMLList() %>% `[[`(8) %>% .[2:length(.)]
#关闭remoteDriver对象
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属性中,图片链接一般在href属性中的标签。
最好在标签下的 src 属性中定位。
随便找个知乎的照片贴,高清图多的那种!
url% 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 % 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()
好吧,它不可能是完美的。对于网页表格数据,pd.read_html函数是一个非常高效的包,但前提是你要保证这个网页中的数据确实是表格格式,并且网页没有做任何隐藏的措施.
更多课程请点击R语言可视化在业务场景中的应用:
往期案例资料请移步我的GitHub:
/ljtyduyu/DataWarehouse/tree/master/File