gpt4 book ai didi

python - 使用 BeautifulSoup 进行多处理来改进 Wikipedia 抓取

转载 作者:太空宇宙 更新时间:2023-11-03 20:10:04 26 4
gpt4 key购买 nike

我正在使用 BeautifulSoup 从一堆维基百科页面中抓取一些基本信息。程序运行,但速度很慢(650 页大约需要 20 分钟)。我正在尝试使用多处理来加快速度,但它没有按预期工作。它要么似乎被阻止而不执行任何操作,要么只抓取每个页面名称的第一个字母。

我使用的抓取代码是:

#dict where key is person's name and value is proper wikipedia url formatting
all_wikis = { 'Adam Ferrara': 'Adam_Ferrara',
'Adam Hartle': 'Adam_Hartle',
'Adam Ray': 'Adam_Ray_(comedian)',
'Adam Sandler': 'Adam_Sandler',
'Adele Givens': 'Adele_Givens'}
bios = {}
def scrape(dictionary):
for key in dictionary:
#search each page
page = requests.get(("https://en.wikipedia.org/wiki/" + str(key)))
data = page.text
soup = BeautifulSoup(data, "html.parser")
#get data
try:
bday = soup.find('span', attrs={'class' : 'bday'}).text
except:
bday = 'Birthday Unknown'
try:
birthplace = soup.find('div', attrs={'class' : 'birthplace'}).text
except:
birthplace = 'Birthplace Unknown'
try:
death_date = (soup.find('span', attrs={'style' : "display:none"}).text
.replace("(", "")
.replace(")", ""))
living_status = 'Deceased'
except:
living_status = 'Alive'
try:
summary = wikipedia.summary(dictionary[key].replace("_", " "))
except:
summary = "No Summary"
bios[key] = {}
bios[key]['birthday'] = bday
bios[key]['home_town'] = birthplace
bios[key]['summary'] = summary
bios[key]['living_status'] = living_status
bios[key]['passed_away'] = death_date

我尝试使用下面的代码将处理添加到脚本的末尾,但它不起作用或仅提取每个页面的第一个字母(例如,如果我正在搜索的页面是 Bruce Lee ,它会调出字母 B 的维基百科页面,然后抛出一堆错误)。

from multiprocessing import Pool, cpu_count

if __name__ == '__main__':
pool = Pool(cpu_count())
results = pool.map(func=scrape, iterable=all_wiki)
pool.close()
pool.join()

是否有更好的方法来构建我的脚本以允许多重处理?

最佳答案

这里有几个问题:

  • dictionaryall_wikis 字典中的每个字符串键。然后,当您使用 for key indictionary: 迭代此字符串时,将访问字符串中的每个字符。您的第一个请求是 https://en.wikipedia.org/wiki/A,这不是所需的结果。
  • 即使 dictionary 是一个名称,
  • str(key) 也没有真正的帮助。我们需要使用 all_wikis[name] 查找正确的 URL。顺便说一句,避免使用诸如字典之类的通用变量。
  • 由于您正在进行多处理,因此需要共享诸如 bios 之类的数据才能进行操作。最简单的方法是仅使用 map 函数的返回值,它是所有工作函数返回值的聚合。
  • 您的抓取存在逻辑问题。 wikipedia.summary 未定义。在不确定您确切想要的结果的情况下,它报告亚当·桑德勒已死亡。我将把这个问题作为练习留给读者,因为这个问题主要是关于多处理的。
  • 我不确定这里的多处理是否与多线程一样理想。由于您的进程在 99% 的情况下都会被阻止发出请求,因此我敢打赌,您可以使用比您拥有的核心数量多得多的线程(或进程)来提高效率。当您执行 CPU 密集型工作时,多处理更适合,但这里的情况并非如此;实际上,Python 进程本身花费的时间很少。我建议通过增加超出核心数量的进程(或线程,如果您为此进行重构)来测试代码,直到您不再看到改进。

这里有一些代码可以帮助您入门。我坚持按照您的示例进行多重处理,并且没有调整网络抓取逻辑。

import requests
from bs4 import BeautifulSoup
from multiprocessing import Pool, cpu_count

all_wikis = {'Adam Ferrara': 'Adam_Ferrara',
'Adam Hartle': 'Adam_Hartle',
'Adam Ray': 'Adam_Ray_(comedian)',
'Adam Sandler': 'Adam_Sandler',
'Adele Givens': 'Adele_Givens'}

def scrape(name):
data = requests.get("https://en.wikipedia.org/wiki/" + all_wikis[name]).text
soup = BeautifulSoup(data, "html.parser")
bio = {}

try:
bio['birthday'] = soup.find('span', attrs={'class': 'bday'}).text
except:
bio['birthday'] = 'Birthday Unknown'

try:
bio['home_town'] = soup.find('div', attrs={'class': 'birthplace'}).text
except:
bio['home_town'] = 'Birthplace Unknown'

try:
bio['passed_away'] = (soup.find('span', attrs={'style': "display:none"}).text
.replace("(", "")
.replace(")", ""))
bio['living_status'] = 'Deceased'
except:
bio['living_status'] = 'Alive'

bio['summary'] = "No Summary"
return name, bio


if __name__ == '__main__':
pool = Pool(cpu_count())
bios = dict(pool.map(func=scrape, iterable=all_wikis))
pool.close()
pool.join()
print(bios)

关于python - 使用 BeautifulSoup 进行多处理来改进 Wikipedia 抓取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58761498/

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