如何使用Python/Beautiful Soup在两个不同的标记之间提取文本?

2024-10-06 10:24:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用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列表和编程基本上是一个新手,对如何继续下去感到困惑。我会很感激任何人可能对此有任何和所有的反馈。你知道吗

谢谢你!你知道吗


Tags: csv标题列表titlehtmllinewriterhref
3条回答

可以使用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组,并从链接中提取文本。你知道吗

你的问题是你在没有任何模式算法的情况下循环所有的“a”标签,是不是每3个链接你就想连接一次?你可以在里面放一个for循环:

for line in alllinks:
    maintitle=''
    for i in xrange(3):
       maintitle+=line.text
    mainlist.append(maintitle)

查找父块,然后遍历嵌套的子块

sp=sp.find('div',id='whatever')
a=sp.select('a')  (this is recursive, finds all a tags in that div)
for tag in a:
    title=a.text.strip()
    url=a['href']

我建议你寻找父html标签到你的'链接'你想一起组,而不是这样做一个简单的顺序,所有的链接

另外,您也可以将find()设为递归,但不建议这样做 通过使用recursive=True选项

将字符串相加:str3=str1+str2

llist=[]
for z in zrange(10)
   llist.append('bob'+str(z))

每个列表项都有一个索引

print llist[1]

阅读清单、字串、字典

可以将nth-of-type:not伪类与一般同级~组合器一起使用。由于a标记都是同级标记,我相信,在显示的html中,我使用类型为nth的b标记将a标记拆分为块。我使用:not从当前文件中删除后面的a同级文件。你知道吗

from bs4 import BeautifulSoup as bs

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;
'''
soup = bs(html, 'lxml')
items = soup.select('b:has(~a)')
length = len(items)
if length == 1:
    row = [item.text for item in soup.select('b ~ a')]
    print(row)
elif length > 1:
    for i in range(1, length + 1):
        row = [item.text for item in soup.select('b:nth-of-type(' + str(i) + ') ~ a:not(b:nth-of-type(' + str(i + 1) + ') ~ a)')]
        print(row)

输出:

enter image description here

相关问题 更多 >