我正在尝试使用Python / Beautiful Soup在HTML页面上的两个加粗标签之间提取链接标题。
我要提取的内容的HTML代码段如下:
<B>Heading Title 1:</B> <a href="link1">Title1</a>
<a href="link2">Title2</a>
<B>Heading Title 2:</B> <a href="link3">Title3</a>
<a href="link4">Title4</a>
<a href="link5">Title5</a>
...
我特别希望将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列表和一般程序设计,我是一个新手,对如何进行操作一无所知。任何人可能对此都有任何反馈,我将不胜感激。
谢谢!
答案 0 :(得分:3)
您可以将nth-of-type
,:not
伪类与同级~
组合器一起使用。由于a
标签都是兄弟姐妹,因此,在所示的html中,我相信我使用类型为nth的b
标签将a
标签分成多个块。我使用:not
从当前版本中删除以后的a
个兄弟姐妹。
from bs4 import BeautifulSoup as bs
html = '''
<B>Heading Title 1:</B> <a href="link1">Title1</a>
<a href="link2">Title2</a>
<B>Heading Title 2:</B> <a href="link3">Title3</a>
<a href="link4">Title4</a>
<a href="link5">Title5</a>
'''
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)
输出:
答案 1 :(得分: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
组,并从链接中提取文本。
答案 2 :(得分:2)
您的问题是您遍历所有'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标签,而不要按照所有链接的顺序随意进行
p.s。您也可以使find()具有吸引力,尽管不建议这样做 通过使用recursive = True选项
将字符串添加在一起:str3 = str1 + str2
llist=[]
for z in zrange(10)
llist.append('bob'+str(z))
每个列表项都有一个索引
print llist[1]
阅读列表,字符串,词典