我一直在为初学者观看python上的bucky roberts视频,我正在尝试使用视频中的类似代码为Wikipedia页面构建一个基本的网络爬虫。
import requests
from bs4 import BeautifulSoup
def main_page_spider(max_pages):
page_list={1: "Contents",
2:"Overview",
3:"Outlines",
4:"Lists",
5:"Portals",
6:"Glossaries",
7:"Categories",
8:"Indices",
9:"Reference",
10:"Culture",
11:"Geography",
12:"Health",
13:"History",
14:"Mathematics",
15:"Nature",
16:"People",
17:"Philosophy",
18:"Religion",
19:"Society",
20:"Technology"}
for page in range(1,max_pages+1):
if page == 1:
url = "https://en.wikipedia.org/wiki/Portal:Contents"
else:
url = "https://en.wikipedia.org/wiki/Portal:Contents/" + str(page_list[page])
source_code = requests.get(url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text, "html.parser")
divs = soup.find('div', {'class': "mw-body-content", 'id': "bodyContent"})
for link in divs.findAll('a'):
href = "https://en.wikipedia.org" + str(link.get("href"))
get_link_data(href)
print(href)
def get_link_data(link_url):
source_code = requests.get(link_url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text, "html.parser")
divs = soup.find('div',{'class': "mw-body-content", 'id': "bodyContent"})
for link in divs.findAll('a'):
link_href_data = link.get("href")
print(link_href_data)
main_page_spider(3)
问题是当我注释掉get_link_data()
的函数调用时,程序运行正常,并且从定义的页面数中获取了所有链接。
但是,当我取消注释时,程序会收集一些链接,并给我类似
socket.gaierror,urllib3.exceptions.NewConnectionError,urllib3.exceptions.MaxRetryError,requests.exceptions.ConnectionError
我该如何解决?
答案 0 :(得分:1)
每当您报废时,都应该引入延迟,以免淹没网站的资源或您自己的资源。如您所描述的那样,使用注释掉get_link_data
行运行脚本会产生2763行输出。这就是您将尽快抓取的2763个URL。这通常会引发错误,可能是由于网站限制您或您自己的网络,或者是DNS服务器被阻塞。
在每次致电get_link_data
之前添加一个延迟-我建议至少等待一秒钟。这将需要一段时间,但请记住-您正在从免费的资源中收集数据。不要滥用它。
您还应该对选择的链接有更多的选择。在2763个URL输出中,只有2291个唯一URL-您将抓取两次的近五百页。跟踪已处理的URL,不要再次请求它们。
您可以进一步优化-大约100个URL包含片段(#
之后的部分)。像这样进行抓取时,通常应该忽略片段-它们通常仅将浏览器定向到焦点所在的位置。如果您从每个网址中删除#
及其后的所有内容,则会留下2189个唯一的页面。
您要使用的某些链接也格式不正确。它们看起来像这样:
https://en.wikipedia.org//en.wikipedia.org/w/index.php?title=Portal:Contents/Outlines/Society_and_social_sciences&action=edit
您可能需要修复这些问题-并可能会完全跳过“编辑”链接。
最后,即使您做了所有这些事情,您也可能会遇到一些例外。互联网是一个混乱的地方:)因此,您将需要包括错误处理。遵循以下原则:
for link in divs.findAll('a'):
href = "https://en.wikipedia.org" + str(link.get("href"))
time.sleep(1)
try:
get_link_data(href)
except Exception as e:
print("Failed to get url {}\nError: {}".format(href, e.__class__.__name__)
```