2

我需要检查很多(约 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 分布在大约十几个主机上,所以我似乎应该能够利用它来处理我的请求并减少连接开销。你会如何建造这个?我对任何编程/脚本语言持开放态度。

4

2 回答 2

2

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

于 2011-04-21T08:03:39.193 回答
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().

于 2011-04-21T08:15:26.037 回答