【问题标题】:Checking a lot of URLs to see if they return 200. What's the cleverest way?检查很多 URL 看它们是否返回 200。最聪明的方法是什么?
【发布时间】:2011-04-21 08:00:01
【问题描述】:

我需要检查很多(约 1000 万)个 URL 以查看它们是否存在(返回 200)。我已经编写了以下代码来针对每个 URL 执行此操作,但是执行所有 URL 大约需要很长时间。

def is_200(url):             
    try:
        parsed = urlparse(url)
        conn = httplib.HTTPConnection(parsed.netloc)
        conn.request("HEAD", parsed.path)
        res = conn.getresponse()
        return res.status == 200
    except KeyboardInterrupt, e:
        raise e
    except:
        return False

这些 URL 分布在大约十几个主机上,因此我似乎应该能够利用这一点来处理我的请求并减少连接开销。你会如何建造这个?我对任何编程/脚本语言持开放态度。

【问题讨论】:

  • 也许 node.js 在这里会有所帮助,因为它执行异步 I/O,其扩展性比阻塞线程更好。此外,如果可用,您可以为此使用一组机器。

标签: python http curl head


【解决方案1】:

看看urllib3。它支持每个主机的连接重用。 此外,使用多个进程/线程或异步 I/O 将是一个好主意。

【讨论】:

  • 感谢您的链接。 urllib3 看起来不错。
【解决方案2】:

所有这些都在 Python 3.x 版本中。

我将创建检查 200 的工作线程。我将举一个例子。线程池(放入threadpool.py):

# http://code.activestate.com/recipes/577187-python-thread-pool/

from queue import Queue
from threading import Thread

class Worker(Thread):
    def __init__(self, tasks):
        Thread.__init__(self)
        self.tasks = tasks
        self.daemon = True
        self.start()

    def run(self):
        while True:
            func, args, kargs = self.tasks.get()
            try: func(*args, **kargs)
            except Exception as exception: print(exception)
            self.tasks.task_done()

class ThreadPool:
    def __init__(self, num_threads):
        self.tasks = Queue(num_threads)
        for _ in range(num_threads): Worker(self.tasks)

    def add_task(self, func, *args, **kargs):
        self.tasks.put((func, args, kargs))

    def wait_completion(self):
        self.tasks.join()

现在,如果urllist 包含您的网址,那么您的主文件应该是这样的:

numconns = 40
workers = threadpool.ThreadPool(numconns)
results = [None] * len(urllist)

def check200(url, index):
    results[index] = is_200(url)

for index, url in enumerate(urllist):
    try:
        workers.add_task(check200, url, index)

    except KeyboardInterrupt:
        print("Shutting down application, hang on...")
        workers.wait_completion()

        break

请注意,此程序可根据此处发布的其他建议进行扩展,这仅取决于 is_200()

【讨论】:

  • 感谢线程池的实现。不幸的是,我在这个系统上仅限于 python 2.5,这让我最初无法回答你的问题,但是如果你将一个导入更改为from Queue import Queue 并在@987654327 中使用self.setDaemon(True),那么代码在 2.5 上也可以正常工作@构造函数。
猜你喜欢
  • 1970-01-01
  • 2012-05-26
  • 2012-09-03
  • 2011-05-25
  • 2021-09-22
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
相关资源
最近更新 更多