gpt4 book ai didi

python - 带有 Xpath/BeautifulSoup 的 h3/h2 标签之间的 HTML

转载 作者:可可西里 更新时间:2023-11-01 13:06:53 25 4
gpt4 key购买 nike

我正在为一个项目使用 Scrapy,我得到以下 html:

<h3><span class="my_class">First title</span></h3>
<ul>
<li>Text for the first title... li #1</li>
</ul>
<ul>
<li>Text for the first title... li #2</li>
</ul>
<h3><span class="my_class">Second title</span></h3>
<ul>
<li>Text for the second title... li #1</li>
</ul>
<ul>
<li>Text for the second title... li #2</li>
</ul>

现在,当我使用 response.xpath(".//ul/li/text()").extract() 它确实有效,它给我 ["Text for第一个标题... li #1", "第一个标题的文本... li #2", "第二个标题的文本... li #1", "第二个标题的文本... li # 2"] 但这部分是我想要的。

我想要两个列表,一个用于First title,另一个用于Second title。这样的结果将是:

first_title = ["Text for the first title... li #1", "Text for the first title... li #2"]
second_title = ["Text for the second title... li #1", "Text for the second title... li #2"]

我仍然不知道如何实现这一点。我目前正在使用 Scrapy 来获取 HTML;使用 xpath 和纯 Python 的解决方案对我来说是理想的。但不知何故,我相信 BeautifulSoup 对这类任务很有用。

您知道如何在 Python 中执行此操作吗?

最佳答案

您可以在 Scrapy 中使用 XPath 和 CSS 选择器。

这是一个示例解决方案(在 ipython session 中;我只将第二个 block 中的 #1 和 #2 更改为 #3 和 #4 以使其更明显):

In [1]: import scrapy

In [2]: selector = scrapy.Selector(text="""<h3><span class="my_class">First title</span></h3>
...: <ul>
...: <li>Text for the first title... li #1</li>
...: <li>Text for the first title... li #2</li>
...: </ul>
...: <h3><span class="my_class">Second title</span></h3>
...: <ul>
...: <li>Text for the second title... li #3</li>
...: <li>Text for the second title... li #4</li>
...: </ul>""")

In [3]: for title_list in selector.css('h3 + ul'):
...: print title_list.xpath('./li/text()').extract()
...:
[u'Text for the first title... li #1', u'Text for the first title... li #2']
[u'Text for the second title... li #3', u'Text for the second title... li #4']

In [4]: for title_list in selector.css('h3 + ul'):
print title_list.css('li::text').extract()
...:
[u'Text for the first title... li #1', u'Text for the first title... li #2']
[u'Text for the second title... li #3', u'Text for the second title... li #4']

In [5]:

编辑,在评论中OP的问题之后:

Every <li> tag is enclosed in its own <ul> (...) Is there any way to extend that to make it look for all the ul tags below the h3 tag?

如果h3ul都是 sibling ,一种方法选择ul在下一个 h3 之前的 s就是数preceding h3 siblings

考虑这个输入 HTML 片段:

<h3><span class="my_class">First title</span></h3>
<ul><li>Text for the first title... li #1</li></ul>
<ul><li>Text for the first title... li #2</li></ul>

<h3><span class="my_class">Second title</span></h3>
<ul><li>Text for the second title... li #3</li></ul>
<ul><li>Text for the second title... li #4</li></ul>

第一个<ul><li>行有 1 个前缀 h3 sibling ,第三个<ul><li>行前面有 2 个 h3 sibling 。

所以对于每个 h3 , 你想关注 ul正好有h3个数的 sibling 到目前为止你已经看到了。

首先:

following-sibling::ul[count(preceding-sibling::h3)=1]

然后,

following-sibling::ul[count(preceding-sibling::h3)=2]

等等。

这是在 enumerate() 的帮助下实现的想法在 h3选择(记住 XPath positions start at 1,而不是 0):

In [1]: import scrapy

In [2]: selector = scrapy.Selector(text="""
<h3><span class="my_class">First title</span></h3>
<ul><li>Text for the first title... li #1</li></ul>
<ul><li>Text for the first title... li #2</li></ul>

<h3><span class="my_class">Second title</span></h3>
<ul><li>Text for the second title... li #3</li></ul>
<ul><li>Text for the second title... li #4</li></ul>
""")

In [3]: for cnt, title in enumerate(selector.css('h3'), start=1):
...: print title.xpath('following-sibling::ul[count(preceding-sibling::h3)=%d]/li/text()' % cnt).extract()
...:
[u'Text for the first title... li #1', u'Text for the first title... li #2']
[u'Text for the second title... li #3', u'Text for the second title... li #4']

关于python - 带有 Xpath/BeautifulSoup 的 h3/h2 标签之间的 HTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31779226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com