如何为Wikipedia页面构建基本的Web爬网程序以收集链接?

时间:2018-07-20 15:02:46

标签: python-3.x web-crawler

我一直在为初学者观看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

我该如何解决?

1 个答案:

答案 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__)

```