【问题标题】:Way too slow to scrape loop-inside-loop with Python BeautifulSoup/urllib2用 Python BeautifulSoup/urllib2 刮循环内循环太慢了
【发布时间】:2014-10-12 02:54:37
【问题描述】:

我想抓取网站的大部分内容。比如说,一般的 url 结构如下:

https://ExampleSite.com/XXXXX,其中 X 可以是任何数字或大写字母。 即https://ExampleSite.com/32E4Zhttps://ExampleSite.com/AA44P

字符总数为 36,包括数字和字母。由于有 5 个随机插槽,因此总 url 组合变成了可怕的 36^5 = 60,466,176。在这些链接中,只有一小部分(20%)实际上有一个有效页面,基于“examplesite.com”前面的 url 的其他组合返回无效链接,我没有抓取任何东西(但我想我仍然需要检查该 URL 组合是否有效并包含“特定标题”?)。

这是我正在运行的 Python/BeautifulSoup 代码,我的目标是通过这些 url 组合并提取与“特定标题”匹配的有效链接:

import urllib2
import re
import csv
from bs4 import BeautifulSoup
import threading

def get_Siteinfo(varURLpart1, varURLpart2, varURLpart3, varURLpart4, varURLpart5):

    for loop1 in range(0, varURLpart1): 
        for loop2 in range(0, varURLpart2):
            for loop3 in range(0, varURLpart3):
                for loop4 in range(0, varURLpart4):
                    for loop5 in range(0, varURLpart5):

                        URLchar = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 
                            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
                            "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] # len(URLchar) = 36

                        url1 = "https://ExampleSite.com/"
                        urlComplete  = url1 + str(URLchar[loop1]) + str(URLchar[loop2]) + \
                            str(URLchar[loop3]) + str(URLchar[loop4]) + str(URLchar[loop5])

                        page = urllib2.urlopen(urlComplete)
                        soup_SomeSiteURL = BeautifulSoup(page, "lxml")
                        page.close()

                        Subhead = soup_SomeSiteURL.find("span", class_="subhead")
                        if Subhead: # If-statement solution; if "subhead" class is found
                            SubheadString = Subhead.get_text(strip=True) # then extract the string
                            if SubheadString == "Specific heading":
                                saveFile = open('SomeSiteValidURLs.csv', 'a')
                                saveFile.write(str(urlComplete)+'\n')
                                saveFile.close()

                        loop5 += 1
                    loop4 += 1
                loop3 += 1
            loop2 += 1
        loop1 += 1

get_Siteinfo(36, 36, 36, 36, 36)

我的问题是处理速度慢,而且要经过许多无效链接的负担。我发现每个 url 需要大约 1 秒的时间才能完成,计算出 60,466,176 种组合将需要大约 2 年的时间在我的计算机上一直运行。这显然是不适用的。所以我的问题是:

  • 我在循环内的循环上做错了吗?
  • 有什么方法可以避免快速或完全通过无效链接的需要?
  • 正则表达式有帮助吗?
  • 我的下一步是实现多线程。不过,我已经在其他程序中尝试过,虽然它有效,但它只将处理时间减少了一半,因此仍然需要一整年不间断地运行程序。
  • 或者我可以加快进程的任何其他提示?

【问题讨论】:

    标签: performance python-2.7 web-scraping beautifulsoup urllib2


    【解决方案1】:

    这是一个 I/O 绑定任务。这意味着您的计算机速度并不重要,因为花费最多时间(按数量级)的是 I/O(等待 http 请求)。您可能无法做太多事情来更快地恢复请求。多线程会有所帮助,但正如您所说,只有 2 到 4 倍左右。

    最好的办法是查看是否可以在不尝试所有网址的情况下找到有效网址的列表。也许你可以在网站的其他地方找到这个?如果没有,可以联系网站管理员吗?

    除此之外,这与尝试所有可能的密码以侵入某人的帐户并没有太大区别...

    如果您真的必须尝试所有这些,那么一种选择可能是通过 VPS 托管公司创建大量虚拟服务器。根据他们如何限制特定域的流量,如果您有 12 台服务器正在运行,您可能会将其减少到一个月或更短的时间。此外,这样您就不必拥有自己的机器来做这件事。

    【讨论】:

    • 感谢您的建议,我会进一步调查。我想到了一个可能的“解决方案”。例如,与其在一个 python 脚本中执行所有循环,不如说我可以创建 12 个脚本,涵盖所有 60,466,176 种组合而没有重叠。然后不停地运行这 12 个脚本一个月,然后将 csv 文件合并为一个。你认为它可行并且会加速约 12 倍吗?
    • 不,这不会比多线程更有优势,因为您的连接一次可以处理的 http 流量是有限的。另外,请小心,因为如果 ExampleSite 收到您的大量请求,他们可能会禁止您的 IP。
    猜你喜欢
    • 2016-01-01
    • 1970-01-01
    • 2021-07-24
    • 2020-09-09
    • 1970-01-01
    • 2013-03-03
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多