爬虫过程中 DOM 对象的处理

2021-04-03 10:28:24 +08:00
 badacook
在练习过程中 尝试对一个页面 table 信息进行收集,pandas 也可读取页面全部 table,但是想使用爬虫中 DOM 的 xpath 语法,对 DOM 节点元素进行筛选,也算是第一次练习,在获得 相应的 table 元素后,没有思路了,在 DOM 元素数组,string 、与 XML 或者 pandas 数据表之间 卡主了,想请教一下 下一步 如何优雅的处理,还望大家不吝赐教

实例如下:
import requests
from lxml import etree

url = 'http://baostock.com/baostock/index.php/Python_API%E6%96%87%E6%A1%A3'
headers = {
"User-Agent" : "Mozilla\/5.0 (Windows NT 10.0; WOW64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/78.0.3904.108 Safari\/537.36"}
text = requests.post(url, headers=headers)
dom = etree.HTML(text.text) #将 web 页面文本信息解析为 HTML 文档
print(dom)
#通过 xpath 语法筛选 DO 文档中感兴趣的元素 此处返回该 id 下子节点 caption 属性为"返回数据说明"的 table 元素数组
tables = dom.xpath('//*[@id="mw-content-text"]/table[@caption="返回数据说明"]')
#下面开始 tables 数组处理 table 数组
for table in tables:
print(type(table))
print(etree.tostring(table))
3372 次点击
所在节点    Python
20 条回复
demo06
2021-04-03 15:03:46 +08:00
就我所了解,你这个 tables 还是个 element 对象,你调用的 entree.tostring 方法只是获取了 tables 的对象索引值,如果需要获取 tables 下的子 element 的内容可以用 xpth('.//a[class="className"]/text()'),如果获取节点属性值可以用 xpath('.//a/@attrName/text()')来获取,注意获取子标签下的其他标签时不能有 /table 不然会出错具体什么原因我给忘了,昨天才看完😂,随后我翻翻,还有就是 /text()是获取当前标签下的直属文本内容,//text()是获取当前标签下所有的文本内容,这块刚看完,不知道我理解的对不对
demo06
2021-04-03 15:10:08 +08:00
另外 xpth 最后获取的内容是个集合,如果只有一个值可以后缀[0]取集合第一个下标的值,如果你 xpath 写的不太准确的最后获取的值有多个的话,下标写几就是取第几个值
milukun
2021-04-03 15:40:37 +08:00
首先,这个 xpath 就是不对的
//*[@id="mw-content-text"]/table[@caption="返回数据说明"]
你可以在 F12 里面直接 crtl+F 查找里面直接输入 xpath 看看能不能查找得到,这里是支持 xpath 的
milukun
2021-04-03 15:40:50 +08:00
badacook
2021-04-03 16:04:08 +08:00
@milukun 因为 有多个 caption="返回数据说明" d table,分别是 id="mw-content-text"元素的子元素,且互为不间断的兄弟元素,我有 F12 查看 其中一个元素 xpath 检索 //*[@id="mw-content-text"]/table[26]/caption,我只是在这个基础上改成查找 包含 caption 属性,且值为"返回数据说明" 的 table 元素
badacook
2021-04-03 16:08:15 +08:00
@demo06 非常感谢 能不能分享一下 python 处理 dom 文档对象的文章,没找到切合的实例
misaka19000
2021-04-03 16:41:31 +08:00
https://cuiqingcai.com/5545.html

我每次写爬虫都照着这个写 xpath 的语法
badacook
2021-04-03 16:48:20 +08:00
@misaka19000 我感觉 我 xpath 没写错,我有参照 W3C xpath 语法来写,就是取到了 DOM 对象,如何还原表单,后续的处理,我看 pandas 的 read_html 其中带 attrs 参数,参数为字典格式,可获取特定属性的 table,我使用 attrs = {"caption":"返回数据说明"} 不带这个参数能获取所有 table,带了反而报错
demo06
2021-04-03 17:49:11 +08:00
@badacook 我看的是爬虫的这块视频,主要解析 html,刚好有讲 xpath,https://b23.tv/cplcyn
你可以去 B 站看一下,不知道能不能满足你的需求
badacook
2021-04-03 20:21:33 +08:00
发现了自己的一个大错误,caption 作为 table 的标题,并不是 table 的属性,而是最近的子元素,那针对 caption 的 table 筛选,何种方法最便捷呢
vngghgfjnff
2021-04-03 21:36:10 +08:00
等答案
demo06
2021-04-04 12:57:07 +08:00
你贴个 HTML 吧
badacook
2021-04-04 14:38:01 +08:00
@demo06 http://baostock.com/baostock/index.php/Python_API%E6%96%87%E6%A1%A3
比如这个页面 我想取出 所有的 caption 为返回数据说明的 table,结合 pandas 处理 DataFrame 的能力
我上面 实例 里面的 text = requests.post(url, headers=headers) 就是获取 HTML 页面的 text.text
你也可以直接 打开这个页面 http://baostock.com/baostock/index.php/Python_API%E6%96%87%E6%A1%A3
使用 F12 查看源码
demo06
2021-04-05 13:04:15 +08:00
@badacook tables=tree.xpath('//table[@class="wikitable"]/caption[contains(text(),"返回数据说明")]/..')
for table in tables:
print(etree.tostring(table, method='html', with_tail=False))
demo06
2021-04-05 13:04:40 +08:00
@badacook 这样改就 OK 了
demo06
2021-04-05 13:08:21 +08:00
@badacook 总结一下,用 xpath 获取 caption 包含 返回数据说明的子标签然后用 /.. 再获取他的父标签(我看了一下页面里面所有 table 的 class 都是 wikitable,用这种方法获取比较准确),然后 toString 后,获得的就是标准 table 表格
demo06
2021-04-05 16:11:12 +08:00
page = requests.post(url, headers=headers).text
tree = etree.HTML(page)
tables=tree.xpath('//table[@class="wikitable"]/caption[contains(text(),"返回数据说明")]/..')
for table in tables:
content=etree.tostring(table)
# result.decode('utf-8')
with open('./table.html','ab+') as fp:
fp.write(content)
print(content)
badacook
2021-04-05 19:25:56 +08:00
@demo06 非常感谢大神 xpath 语法真的很赞,这个语法我要好好研究一下,本来还觉得学了解 xpath,自惭形秽啊
demo06
2021-04-05 22:34:12 +08:00
@badacook 能帮到你就好,我也就刚好看过这块内容😂
zpfhbyx
2021-04-06 10:57:04 +08:00
上 pyquery 吧。比这个省事。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/767744

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX