问题:我有以下XML摘要:
...snip...
<p class="p_cat_heading">DEFINITION</p>
<p class="p_numberedbullet"><span class="calibre10">This</span>, <span class="calibre10">these</span>. </p>
<p class="p_cat_heading">PRONUNCIATION </p>
..snip...
我需要搜索XML的总体,找到具有文本DEFINITION
的标题,然后打印关联的定义。定义的格式不一致,可以更改属性/元素,因此捕获所有内容的唯一可靠方法是读取直到带有属性p_cat_heading
的下一个元素。
现在,我正在使用以下代码查找所有标题:
for heading in root.findall(".//*[@class='p_cat_heading']"):
if heading.text == "DEFINITION":
<WE FOUND THE CORRECT HEADER - TAKE ACTION HERE>
我尝试过的东西:
- 使用LXML的getNext方法。这将获得下一个具有" p_cat_heading"属性的兄弟姐妹,这不是我想要的。
- plostrongibling-lxml应该支持这一点,但它抛出了"在前缀映射中找不到sivebly"
我的解决方案:
我还没有完成它,但是由于我的XML很短,所以我只会获得所有元素的列表,直到具有定义属性的元素,然后迭代直到带有p_cat_heading属性的下一个元素。这个解决方案是可怕而丑陋的,但我似乎找不到一个干净的选择。
我要寻找的是:
在我们的情况下,打印定义的一种更加柔软的方式。解决方案可以使用XPATH或其他替代方案。Python本地解决方案更喜欢,但任何事情都会做。
有几种方法可以做到这一点,但是依靠xpath来完成大部分工作,此表达式
//*[@class='p_cat_heading'][contains(text(),'DEFINITION')]/following-sibling::*[1]
应该工作。
使用LXML:
from lxml import html
data = [your snippet above]
exp = "//*[@class='p_cat_heading'][contains(text(),'DEFINITION')]/following-sibling::*[1]"
tree = html.fromstring(data)
target = tree.xpath(exp)
for i in target:
print(i.text_content())
输出:
这个,这些。
您可以将Flifutifure与CSS选择器一起用于此任务。选择器.p_cat_heading:contains("DEFINITION") ~ .p_cat_heading
将选择所有元素的所有元素,该元素在 p_cat_heading
之前列出了元素,其中包含字符串"定义"的类p_cat_heading
:
data = '''
<p class="p_cat_heading">THIS YOU DONT WANT</p>
<p class="p_numberedbullet"><span class="calibre10">This</span>, <span class="calibre10">these</span>. </p>
<p class="p_cat_heading">DEFINITION</p>
<p class="p_numberedbullet"><span class="calibre10">This</span>, <span class="calibre10">these</span>. </p>
<p class="p_cat_heading">PRONUNCIATION </p>'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(data, 'lxml')
for heading in soup.select('.p_cat_heading:contains("DEFINITION") ~ .p_cat_heading'):
print(heading.text)
打印:
PRONUNCIATION
进一步阅读
CSS选择器指南
编辑:
在定义之后选择直接兄弟姐妹:
data = '''
<p class="p_cat_heading">THIS YOU DONT WANT</p>
<p class="p_numberedbullet"><span class="calibre10">This</span>, <span class="calibre10">these</span>. </p>
<p class="p_cat_heading">DEFINITION</p>
<p class="p_numberedbullet"><span class="calibre10">This is after DEFINITION</span>, <span class="calibre10">these</span>. </p>
<p class="p_cat_heading">PRONUNCIATION </p>
<p class="p_numberedbullet"><span class="calibre10">This is after PRONUNCIATION</span>, <span class="calibre10">these</span>. </p>'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(data, 'lxml')
s = soup.select_one('.p_cat_heading:contains("DEFINITION") + :not(.p_cat_heading)')
print(s.text)
打印:
This is after DEFINITION, these.