爬虫相关,关于 XPath 的疑问

2022-09-14 18:38:09 +08:00
 MrVito

http://eid.csrc.gov.cn/fund/disclose/instance_html_view.do?instanceid=11733222 http://eid.csrc.gov.cn/fund/disclose/instance_html_view.do?instanceid=11733213

在上面这两个链接中我想获取对应的基金名称,我在浏览器里面获取到的 full XPath 如下

/html/body/table/tbody/tr/td[2]/table/tbody/tr[1]/td[1]/div/table[1]/tbody/tr[2]/td/div/div/table/tbody/tr[1]/td[2]/p

但是第二个链接中我能顺利获取到值,第一个获取到的内容为空

为了给大佬省事,对应的代码如下

from ast import main
from fake_useragent import UserAgent
from lxml import etree
import requests

ua = UserAgent()
headers = {"user-agent": ua.random}
url1 = "http://eid.csrc.gov.cn/fund/disclose/instance_html_view.do?instanceid=11733222"
url2 = "http://eid.csrc.gov.cn/fund/disclose/instance_html_view.do?instanceid=11733213"


def get_fund_name(url: str):
    x = requests.get(url, headers = headers)
    selector = etree.HTML(x.content)
    fund_name = selector.xpath('/html/body/table/tbody/tr/td[2]/table/tbody/tr[1]/td[1]/div/table[1]/tbody/tr[2]/td/div/div/table/tbody/tr[1]/td[2]/p/text()')
    return fund_name

print(get_fund_name(url1))
print(get_fund_name(url2))

output 如下

[]
['长信利盈灵活配置混合型证券投资基金']

我仔细对比了这两个网页,实在是找不到原因……

3399 次点击
所在节点    Python
34 条回复
dongtingyue
2022-09-14 18:47:23 +08:00
有些 dom 是 js 渲染的
MrVito
2022-09-14 18:49:34 +08:00
@dongtingyue 你可以看下这个网页,应该是纯静态的
Stoney
2022-09-14 18:58:47 +08:00
@MrVito get 里面加个 wait 设置等待时间?有时候是没来得及加载出来吧
humbass
2022-09-14 19:03:54 +08:00
2202 年的爬虫应该用 JS 来实现更强大;比如 Puppeteer
tankren
2022-09-14 19:04:17 +08:00
用 try+except 抛个异常看看,为啥要用绝对路径啊,不是不推荐吗
MrVito
2022-09-14 19:21:55 +08:00
@tankren 相对路径我也取不到……所以就用绝对路径了
MrVito
2022-09-14 19:23:32 +08:00
@Stoney 加了一个 timeout = 10 ,也还是不对……
MrVito
2022-09-14 19:24:18 +08:00
@tankren 也没有抛异常出来……
MrVito
2022-09-14 19:24:38 +08:00
@humbass 对 js 不熟……
zengxs
2022-09-14 19:26:19 +08:00
试试这个

//*[contains(text(), '基金名称')]/../../td[2]/p/text()
MrVito
2022-09-14 19:27:47 +08:00
@zengxs 卧槽,你这个确实可以,这个思路好像也是对的。但是我还是想不明白我那种为啥不行……
zengxs
2022-09-14 19:29:20 +08:00
@MrVito 因为两个页面的 html 内容不一样,你需要找到二者之间相同的特征才行
MrVito
2022-09-14 19:31:56 +08:00
@zengxs 问题是我用的 full xpath ,从浏览器提取出来的这两个页面的都是相同的呀?
zengxs
2022-09-14 19:35:28 +08:00
@MrVito 那可能是这个页面的 html 不规范,导致浏览器和 lxml 解析出来的 dom 不一样
humbass
2022-09-14 20:24:26 +08:00
网页是 JS 写的,爬虫当然是 JS 来写解析 DOM 结构也是天然的! Python 是过去式了;

```
const jsdom = require('jsdom')
const axios = require('axios')
;(async () => {
const url =
'http://eid.csrc.gov.cn/xbrl/REPORT/HTML/2022/FC190100/CN_50470000_009421_FC190100_20220039/CN_50470000_009421_FC190100_20220039.html'
const response = await axios.get(url)
const result = new jsdom.JSDOM(response.data)
const table = result.window.document.querySelector('#tabItem0')
const title = table.querySelectorAll('p')[1].textContent
console.log('title:', title)
})()

``
zjuster
2022-09-14 20:44:36 +08:00
如果 Xpath 写的绝对路径太多了,可能要比较一下两个页面(虽然链接一致),但在 Dom 结构可能不一致的情况。
写的宽泛一点试试看。
wxf666
2022-09-14 20:49:09 +08:00
@humbass 问一下,看起来都是调包,Python 是有啥明显的坑吗?
humbass
2022-09-14 21:14:13 +08:00
@wxf666 也不是说 Python 有坑,而是网页解析这玩意本身就是 JS 的领域。
zengxs
2022-09-14 21:31:48 +08:00
@humbass 这个是和底层的 html parser 有关,和语言关系不大,jsdom 用的 html parser 和浏览器的也不一样
wxf666
2022-09-14 21:32:15 +08:00
@humbass js 本身也没有啥特别的语言特性,是用于描述 DOM 的吧

你是想说,无头浏览器能方便地,执行一些自己的 js 代码?

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

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

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

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

© 2021 V2EX