为了账号安全,请及时绑定邮箱和手机立即绑定

python - 使用 BeautifulSoup 更有效地抓取网页

python - 使用 BeautifulSoup 更有效地抓取网页

Cats萌萌 2023-07-05 11:10:16
我正在编写一个脚本来抓取维基百科页面,其中包含这些名称的名称列表。具体来说,我正在抓取一个维基百科页面,其中包含每个爵士钢琴家的姓名列表(至少根据维基百科)。我想要做的是将本页上所有钢琴家的名字附加到一个列表中。以下是维基百科页面的链接:https ://en.wikipedia.org/wiki/List_of_jazz_pianists我设法用 Beautiful Soup v4 找到了一个解决方案,但它看起来很笨重。让我描述一下这个解决方案以及为什么我会实现它。(为了简洁起见,我不会在这篇文章中包含 HTML 文件)import requestsimport bs4result = requests.get("https://en.wikipedia.org/wiki/List_of_jazz_pianists")soup = bs4.BeautifulSoup(result.text, "html.parser")bigList = soup.findAll('div', {'class' : 'div-col columns column-width'})bigList 是每个 div class = div-col columns column-width 的列表,因为这些 div 包含艺术家的实际姓名。artistList = []index = 0for nameTag in bigList[5].contents[1].contents:    if index % 2 == 0:        artistList.append(nameTag.contents[0].contents[0])            index += 1    print(artistList)这需要一些解释。如果您查看 Wikipedia 页面的 HTML 文件,将会有所帮助。bigList[5]给出 'F' 的所有姓氏,因为 F 是字母表中的第 6 个字符. bigList[5].contents给出一个包含 3 个元素的列表:一个换行转义字符、F 的整个<li>列表,最后是另一个换行转义字符. 因此访问F 的 bigList[5].contents[1]整个列表。给出每个元素的列表,以换行转义字符分隔。所以我的想法是,我将迭代此列表中的每个元素,仅采用偶数索引元素,因为奇数索引元素都是换行符转义字符。<li>bigList[5].contents[1].contents<li>nameTag.contents给出一个由两个元素组成的列表,钢琴家的超链接和姓名,以及他们的出生日期 - 死亡日期. 所以我选择该列表的第一个元素。最后,nameTag.contents[0].contents给出一个仅包含一个元素(钢琴家的名字)的列表,因此我拉出该列表的唯一元素,以便将其作为字符串而不是嵌套列表附加到artistList。正如您所看到的,对于看起来应该更简单的事情来说,这是一个极其复杂的过程。鉴于我对 bs4 和使用 python 进行网页抓取总体来说是新手,我觉得有一个更好的解决方案。此外,我最终想从该页面上链接的每个钢琴家的页面收集数据。我的解决方案不是很稳健或高效,我知道这会给我推进这个项目带来问题。有更好的方法来做我想做的事情吗?我真的很感谢您的帮助,对于帖子的长度以及任何其他不适当或非惯用的错误,我深表歉意 - 我是堆栈溢出的新手。谢谢!
查看完整描述

2 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

您的解决方案可能有点过于依赖页面的格式,尽管抓取维基百科总是很困难,因为带有数据的元素没有用标识符或类来标记它们保存的数据,所以您只能依赖于结构无论如何,表格保持不变。


您找到了正确的数据,但真正使艺术家链接与众不同的是它们是元素<a>内的div-col <div>元素。


BS4 的一个更简单的解决方案(考虑到您既需要艺术家姓名又需要他们页面的链接):


from urllib import request

from bs4 import BeautifulSoup


with request.urlopen("https://en.wikipedia.org/wiki/List_of_jazz_pianists") as response:

    bs = BeautifulSoup(response, "html.parser")

    for div_col in bs.find_all('div', {'class': 'div-col'}):

        for artist_tag in div_col.find_all('a'):

            print(f'{artist_tag.text}, {artist_tag.attrs["href"]}')

请注意,这不使用第三方requests,而是标准urllib。


结果:


Irving Aaronson, /wiki/Irving_Aaronson

Anders Aarum, /wiki/Anders_Aarum

...

Bojan Zulfikarpašić, /wiki/Bojan_Zulfikarpa%C5%A1i%C4%87

Axel Zwingenberger, /wiki/Axel_Zwingenberger

如果您注重效率(或更确切地说是简洁),那么这句话可能就是您喜欢的:


result = [(a.text, a.attrs['href'])

          for d in bs.find_all('div', {'class': 'div-col'})

          for a in d.find_all('a')]

result将是艺术家姓名和链接的元组列表,即[('Irving Aaronson', '/wiki/Irving_Aaronson'), ('Anders Aarum', '/wiki/Anders_Aarum'), ..]


查看完整回答
反对 回复 2023-07-05
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

找到后bigList,您可以使用此行替换其余行:

[row['title'] for row in bigList[5].find_all('a')]

要理解此代码,请查看bigList[5]bigList[5].find_all('a')` 的输出,然后也尝试该行。

您可以类似地使用href代替title来查找网址。


查看完整回答
反对 回复 2023-07-05
  • 2 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信