获取指向包含某些文本的标签的xpath

时间:2019-07-31 18:53:13

标签: python xpath beautifulsoup

我正在尝试查找网页上某些文本的xpath。如果您要去https://www.york.ac.uk/teaching/cws/wws/webpage1.html并尝试获取xpath的“ EXERCISE”,它将看起来像“ html body html table tbody tr td div h4”。如果转到该页面,请右键单击“ EXERCISE”并对其进行检查,您可以在代码底部(chrome)中看到该路径。

我尝试了许多方法。没有一个能获得理想的结果。这是我得到的最接近的东西:

soup = BS(page, 'html.parser')
tags = [{"name":tag.name,"text":tag.text,"attributes":tag.attributes} for tag in soup.find_all()]
s = ''
for t in tags:
    if "EXERCISE" in t['text']:
        s = s + t['name'] + " "
print(s)

一开始我需要获取“ html body html table tbody tr td div h4”,但最终在页面更复杂的情况下,我还需要获取标签属性

谢谢!

3 个答案:

答案 0 :(得分:0)

如果您知道所需的标签将始终具有“ EXERCISE”的确切文本(无引号,或其他不同的大小写,空格等),那么您可以使用.find在确切的文字上。虽然您也可以使用正则表达式,以防万一您想检查空格的变化,而不要检查空白。

从那里,您可以利用.parents来获取对象祖先的列表,这意味着包含该对象的元素,包含该元素的元素等等,直到文档的顶部。然后只需提取标签名称,将列表反向,然后将所有内容结合在一起即可。

thetag = soup.find(string="EXERCISE")
parent_tags = [ p.name for p in list(thetag.parents) ]
print('/'.join(parent_tags[::-1]))

输出:

  

[document] / html / body / hmtl / table / tr / td / div / h4

如果您一开始不希望使用“ [document]”,则可以采用多种方式将其取出,例如,使用以下几行代替最后两行:

parent_tags = [ p.name for p in list(thetag.parents)[:-1] ]
print('/' + '/'.join(parent_tags[::-1]))

输出:

  

/ html / body / hmtl / table / tr / td / div / h4

答案 1 :(得分:0)

CSS选择器:contains(EXERCISE):not(:has(:contains(EXERCISE)))将选择包含字符串“ EXERCISE”的最里面的标签。

然后,我们使用方法find_parents()查找该标签的所有父标签并打印其名称:

import requests
from bs4 import BeautifulSoup

url = 'https://www.york.ac.uk/teaching/cws/wws/webpage1.html'

soup = BeautifulSoup(requests.get(url).text, 'html.parser')

t = soup.select_one(':contains(EXERCISE):not(:has(:contains(EXERCISE)))')
# you can use also this:
# t = soup.find(text="EXERCISE").find_parent()    

#lets print the path
tag_names = [t.name, *[t.name for t in t.find_parents()]]
print(' > '.join(tag_names[::-1]))

打印:

[document] > hmtl > body > table > tr > td > div > p > p > p > p > h4

答案 2 :(得分:0)

使用lxml:

url = 'https://www.york.ac.uk/teaching/cws/wws/webpage1.html'

import requests
from lxml import etree
parser = etree.HTMLParser()
page  = requests.get(url,headers={"User-Agent":"Mozilla/5.0"})

root = etree.fromstring(page.content,parser)

tree = etree.ElementTree(root)
e = root.xpath('.//*[text()="EXERCISE"]')
print(tree.getpath(e[0]))

输出:

  

/ html / body / hmtl / table / tr / td / div [2] / h4