爬虫相关,关于 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 如下

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

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

3153 次点击
所在节点    Python
34 条回复
humbass
2022-09-14 21:37:09 +08:00
@wxf666 OP 主贴出来的需求,也用不到无头浏览器,简单的访问就可以了,
@zengxs 对比 python 的 xpath 和 document.querySelector 这样的语法,肯定是后者方便啊。
wxf666
2022-09-14 21:48:47 +08:00
@humbass xpath 不是 Python 的,只是 lxml 库的一个功能。这个库好像不支持 css 风格的查询

换成 BeautifulSoup 库就支持了:xxx.select('#tabItem0')

另外,我还是觉得 xpath 更方便描述 xml html
zengxs
2022-09-14 22:07:56 +08:00
@humbass 呃,xpath 和 css selector 只是两种不同的 html 查询方式而已,和语言无关,python 也可以 css selector 查询,js 也可以 xpath 查询

至于哪个更方便这个也不好说,css selector 语法简单是牺牲了很多功能换来的
bavtoex
2022-09-15 00:16:35 +08:00
@wxf666 +1,美丽汤的 xxx.select('#tabItem0') 很灵活
webcape233
2022-09-15 02:05:22 +08:00
这简单查询观察下写正则可能更快
mscststs
2022-09-15 02:47:57 +08:00
看到 tbody 就要注意了,浏览器会自动在 table 里面自动填充一级 tbody ,这就是为什么你取 Xpath 是一样的,实际上你右键查看源码,就能看出来,第一个链接的 html 没有在源码里面手写 tbody ,而第二个写了。
ADMlN
2022-09-15 05:02:37 +08:00
xpath 改成'/html/body/table/tbody',第一个为空,第二个有值
brucmao
2022-09-15 09:16:19 +08:00
//p[contains(text(),'基金名称')]/../following-sibling::td/p

页面复制的经常不准确,可以试试 xpath 轴
https://developer.mozilla.org/en-US/docs/Web/XPath

另外可以用浏览器插件 SelectorsHub 辅助
JieGaLee
2022-09-15 09:32:27 +08:00
遇到 tbody 就要去源码里确认一下是不是真的有 tbody 。
hidie
2022-09-15 10:00:33 +08:00
不要写 tbody
fbichijing
2022-09-15 17:03:12 +08:00
一个有 tbody 一个没有,所以找不到。
这么深层数的筛选器加上那么多的位置 index ,简直是独木桥中的独木桥啊。
ijustdo
2022-09-15 18:15:09 +08:00
//div[@id="con_one_1"][1]/descendant::table/descendant::tr[1]/td[2]/p/text()
chunhai
2022-09-19 19:36:35 +08:00
我一般都用正则来取
chunhai
2022-09-19 19:40:23 +08:00
@chunhai
```
<td align="left" colspan="2"><p>基金名称<\/p><\/td>\s*<td align="left" width="60%" colspan="3">\s*<p>(.*)<\/p>
```

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

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

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

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

© 2021 V2EX