python read table_左手用R右手Python系列之——表格数据抓取之道

2023-10-25 06:10

本文主要是介绍python read table_左手用R右手Python系列之——表格数据抓取之道,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原标题:左手用R右手Python系列之——表格数据抓取之道

杜雨,EasyCharts团队成员,R语言中文社区专栏作者,兴趣方向为:Excel商务图表,R语言数据可视化,地理信息数据可视化。个人公众号:数据小魔方(微信ID:datamofang) ,“数据小魔方”创始人。

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

对于表格而言,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语法元素的字符串向量。

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

大连市2016年空气质量数据可视化~

a30ffc946a38e9ea371a0a8bb907348f.png

URL% xml2::url_escape(reserved ="][!$&'()*+,;=:/?@#")

####

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

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

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

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

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

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

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

###mydata% 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

remDr$navigate("https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC") mytable% htmlParse(encoding ="UTF-8") %>% readHTMLTable(header=TRUE,which =1)mytable% read_html(encoding ="UTF-8") %>% html_table(header=TRUE) %>% `[[`(1)

#关闭remoteDriver对象

remDr$close()

94b2c441fea724613005e60d9958c951.png

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

DT::datatable(mytable)

779e46c341c519074817af271f6d9d57.png

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

http://www.tianqi.com/air/

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

69db8676aa9cb13b7e125a7b089af949.png

url

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

NULL

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

802c73a3e75466b8f193b47231849088.png

header

"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 % htmlParse() %>% 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对象,并打开

library("RSelenium")remDr

remDr$navigate("http://www.tianqi.com/air/") mylist% htmlParse(encoding="utf-8") %>% readHTMLList() %>% `[[`(8) %>% .[2:length(.)]

#关闭remoteDriver对象

remDr$close()

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

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

library("stringr")pattern

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)

5f68c24fdbe0e6650fd0a13133e95340.png

0e5de50e45dad3521889d940c92ca5b6.png

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

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

f9d6a0e676f6bb76770106af72af4815.png

url

mylink % 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 % htmlParse() %>% getHTMLLinks(xpQuery = "//img/@data-original")

0bb1dc964a21a77c86ed6a3f2427ccb2.png

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

Python:

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

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

dfs = pd.read_html(url)

2d2c16e8ed9a86b0444689d7f932995c.png

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

from selenium import webdriverdriver = 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()

170fdae0ea2d73dbfb929acbdda623c8.png

1b5b9512c7fba7900dc9709b416ba5a3.png

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

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

往期案例数据请移步本人GitHub:

https://github.com/ljtyduyu/DataWarehouse/tree/master/File

R语言爬虫实战案例分享:网易云课堂 、知乎live、 今日头条、B站视频

分享内容:本次课程所有内容及案例均来自于本人平时学习练习过程中的心得和笔记总结,希望借此机会,将自己的爬虫学习历程与大家分享,并为R语言的爬虫生态改善以及工具的推广,贡献一份微薄之力,也是自己爬虫学习的阶段性总结。

责任编辑:

这篇关于python read table_左手用R右手Python系列之——表格数据抓取之道的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/280539

相关文章

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

Python自动化批量重命名与整理文件系统

《Python自动化批量重命名与整理文件系统》这篇文章主要为大家详细介绍了如何使用Python实现一个强大的文件批量重命名与整理工具,帮助开发者自动化这一繁琐过程,有需要的小伙伴可以了解下... 目录简介环境准备项目功能概述代码详细解析1. 导入必要的库2. 配置参数设置3. 创建日志系统4. 安全文件名处

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

Python包管理工具pip的升级指南

《Python包管理工具pip的升级指南》本文全面探讨Python包管理工具pip的升级策略,从基础升级方法到高级技巧,涵盖不同操作系统环境下的最佳实践,我们将深入分析pip的工作原理,介绍多种升级方... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核