Python用urllib2抓取数据并行请求

时间:2014-02-18 17:25:58

标签: python urllib2

我想废弃一个网站。有大约8000件商品要废弃。我有问题,如果要求1件物品需要1秒钟,那么这些物品需要大约8000秒,这意味着它需要大约134分钟和2.5小时。任何人都可以帮助解决如何完成它并同时执行多个请求。我正在使用python urllib2来请求内容。

2 个答案:

答案 0 :(得分:4)

  1. 使用更好的HTTP客户端。 Urllib2使用Connection: close发出请求,因此必须协商新的TCP连接。使用requests,您可以重用该TCP连接。

    s = requests.Session()
    r = s.get("http://example.org")
    
  2. 并行提出请求。由于这是I / O绑定,因此可以使用GIL并且可以使用线程。您可以运行一些简单的线程来下载一批URL,然后等待所有这些URL完成。但也许像"平行地图"会更好地适应这种情况 - 我用简单的例子找到了这个答案:

    https://stackoverflow.com/a/3332884/196206

    如果您在线程之间共享任何内容,请确保它是线程安全的 - 请求会话对象似乎是线程安全的:https://stackoverflow.com/a/20457621/196206

  3. 更新 - 一个小例子:

    #!/usr/bin/env python
    
    import lxml.html
    import requests
    import multiprocessing.dummy
    import threading
    
    first_url = "http://api.stackexchange.com/2.2/questions?pagesize=10&order=desc&sort=activity&site=stackoverflow"
    
    rs = requests.session()
    
    r = rs.get(first_url)
    links = [item["link"] for item in r.json()["items"]]
    lock = threading.Lock()
    
    def f(data):
        n, link = data
        r = rs.get(link)
        doc = lxml.html.document_fromstring(r.content)
        names = [el.text for el in doc.xpath("//div[@class='user-details']/a")]
        with lock:
            print("%s. %s" % (n+1, link))
            print(", ".join(names))
            print("---")
        # you can also return value, they will be returned
        # from pool.map() in order corresponding to the links
        return (link, names)
    
    pool = multiprocessing.dummy.Pool(5)
    names_list = pool.map(f, enumerate(links))
    print(names_list)
    

答案 1 :(得分:0)

您应该考虑使用Scrapy而不是直接使用lxml和urllib。 Scrapy是“一种快速的高级屏幕抓取和网络爬行框架,用于抓取网站并从网页中提取结构化数据。”它建立在Twisted之上,因此它本身可以异步,因此它非常非常快。

我无法向您提供有关您的抓取速度有多快的任何具体数字,但想象您的请求是并行而非串行发生的。您仍然需要使用xpath或Beautiful Soup编写代码来提取所需的信息,但是您不必计算页面的提取。