首页 > 解决方案 > 如何使用 Python/Beautiful Soup 提取两个不同标签之间的文本?

问题描述

我正在尝试使用 Python/Beautiful Soup 将链接标题提取到 HTML 页面上的两个粗体标签之间。

我试图提取的 HTML 片段如下:

<B>Heading Title 1:</B>&nbsp;<a href="link1">Title1</a>&nbsp;
<a href="link2">Title2</a>&nbsp;

&nbsp;

<B>Heading Title 2:</B>&nbsp;<a href="link3">Title3</a>&nbsp;
<a href="link4">Title4</a>&nbsp;
<a href="link5">Title5</a>&nbsp;

...

我特别希望将 Title1 和 Title2(由分隔符分隔)连接到类似列表的对象中的一个条目,同样适用于 Title 3、Title 4 和 Title 5,等等。(我预见到的一个问题是每个标题标题之间的标题数量不一样。)

我尝试了各种方法,包括:

import requests, bs4, csv

res = requests.get('WEBSITE.html')

soup = BeautifulSoup(res.text, 'html.parser')

soupy4 = soup.select('a')

with open('output.csv', 'w') as f:
    writer = csv.writer(f, delimiter=',', lineterminator='\n')
    for line in soupy4:
        if 'common_element_link' in line['href']:
            categories.append(line.next_element)
            writer.writerow([categories])

但是,虽然这会将所有标题写入文件,但它是通过直接附加每个附加标题来实现的,如下所示:

['Title1']
['Title1', 'Title2']
['Title1', 'Title2', 'Title3']
['Title1', 'Title2', 'Title3', 'Title4']
...

理想情况下,我希望此代码执行以下操作:

['Title1', 'Title2']
['Title3', 'Title4', 'Title5']
...

一般来说,我在 python 列表和编程方面是一个新手,我不知道如何继续。我将不胜感激任何人对此可能有的任何反馈。

谢谢!

标签: pythonbeautifulsoup

解决方案


您可以使用itertools.groupby组合标题之间的所有链接文本:

import itertools, re
from bs4 import BeautifulSoup as soup
d = [[i.name, i] for i in soup(content, 'html.parser').find_all(re.compile('b|a'))]
new_d = [[a, list(b)] for a, b in itertools.groupby(d, key=lambda x:x[0] == 'b')]
final_result = [[c.text for _, c in b] for a, b in new_d if not a]

输出:

[['Title1', 'Title2'], ['Title3', 'Title4', 'Title5']]

原始find_all调用用作“扁平化器”并创建具有目标标记名称和内容的列表列表。itertools.groupby有一个根据标签名称是否用于粗体内容进行分组的键。因此,可以进行最后一次传递new_d,忽略b组,并从链接中提取文本。


推荐阅读