Python web-scraping 中可能存在 bottle-neck 个问题

Possible bottle-neck issue in web-scraping with Python

首先,我为模糊的标题道歉,但问题是我不确定是什么导致了错误。

我正在使用 Python 从网站推断一些数据。 我创建的代码在当时传递一个 link 时完美运行,但在尝试从我拥有的 8000 页中收集数据时不知何故中断(它实际上中断了方式)。我需要做的过程是这样的:

  1. 从一页(8000 links)中收集所有 links
  2. 从每个 link 推断另一个 link 包含在 iframe
  3. 从 2.link 中抓取日期

第 1 点很简单,而且效果很好。 第 2 点和第 3 点工作了一段时间,然后出现了一些错误。每次都在不同的点,它永远不会相同。经过一些测试后,我决定尝试一种不同的方法和 运行 我的代码,直到 1 中所有 link 的第 2 点,尝试首先收集所有 link。在这一点上,我发现,很可能,我在这个阶段遇到了错误。 代码是这样工作的:在 for 循环中,我将 url 列表中的每一项传递给下面的函数。它应该在 Disqus 网站上搜索 link。应该只有一个 link 并且总是有一个 link。因为使用 lxml 这样的库,无法在 iframe 内部进行扫描,所以我使用了 selenium 和 ChromeDriver。

def get_url(webpage_url):
    chrome_driver_path= '/Applications/chromedriver' 
    driver = webdriver.Chrome(chrome_driver_path) 
    driver.get(webpage_url)
    iframes=driver.find_elements_by_tag_name("iframe")
    list_urls=[]
    urls=[]

    # collects all the urls of all the iframe tags
    for iframe in iframes:
        driver.switch_to_frame(iframe)
        time.sleep(3)
        list_urls.append(driver.current_url)
        driver.switch_to_default_content()
    driver.quit()

    for item in list_urls:
        if item.startswith('http://disqus'):
            urls.append(item)

    if len(urls)>1:
        print "too many urls collected in iframes"
    else:
        url=urls[0]

    return url

一开始没有time.sleep,大概工作了30link秒。然后我放了一个 time.sleep(2) ,它到达了大约 60。现在使用 time.sleep(3) 它可以工作大约 130 links。当然,这不是解决办法。我现在得到的错误,它总是相同的(url=urls[0] 中的索引超出范围),但每次都有不同的 link。如果我用单个 link 检查我的代码,它会在它中断的地方运行,所以它实际上可以在那里找到 url。当然,有时会在之前停止的地方传递一个 link 并且它可以正常工作。 我怀疑我得到这个可能是因为 time-out,但当然我不确定。

那么,我怎样才能理解这里的问题是什么?

如果问题是它发出了太多请求(即使睡眠),我该如何处理?

谢谢。

根据您对问题的描述,当您在给定时间内发出过多请求时,主机可能会限制您的客户端。这是针对 DoS 攻击和行为不端的机器人的常见保护措施 - 就像您的一样。

这里的干净解决方案是检查站点是否有 robots.txt 文件,如果有则解析它并遵守规则 - 否则,在两个请求之间设置足够长的等待时间,这样你就不会被踢。

您还可能会遇到很多其他问题 - 404、丢失网络连接等 - 甚至 selenium.webdriver as documented here:

的加载时间问题

Dependent on several factors, including the OS/Browser combination, WebDriver may or may not wait for the page to load. In some circumstances, WebDriver may return control before the page has finished, or even started, loading. To ensure robustness, you need to wait for the element(s) to exist in the page using Explicit and Implicit Waits.

wrt/ 你的 IndexError,你盲目地假设你会得到至少一个 url (这意味着至少一个 iframe),由于上述任何原因(和一个其他人也很少)。首先,您要确保正确处理所有极端情况,然后修复您的代码,这样您就不会假设您 do 至少有一个 url:

url = None
if len(urls) > 1:
    print "too many urls collected in iframes"
elif len(urls) == 0:
    url = urls[0]
else:
    print "no url found"

另外如果你只想要第一个http://disqus url就可以找到,不需要全部收集,然后过滤掉,然后return第一个:

def get_url(webpage_url):
    chrome_driver_path= '/Applications/chromedriver' 
    driver = webdriver.Chrome(chrome_driver_path) 
    driver.get(webpage_url)
    iframes=driver.find_elements_by_tag_name("iframe")
    # collects all the urls of all the iframe tags
    for iframe in iframes:
        driver.switch_to_frame(iframe)
        time.sleep(3)
        if driver.current_url.startswith('http;//disqus'):
            return driver.current_url 
        driver.switch_to_default_content()
    driver.quit()
    return None # nothing found