Próbuje przyspieszyć i usprawnić kod crawlera korzystającego z ThreadPoolExecutor:

 
import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

Powyższy kod (nie mój) działa dobrze, ale brakuje mi tu dwóch rzeczy:

  • żeby pojedynczy worker zwracał kody błędów jeśli z jakichś powodów nie uda mu się ściągnąć strony.
  • funkcja która organizuje pracę żeby na podstawie ew. błędów wrzucała workera (któremu się nie powiodło ściągnięcie danych) na koniec (puli) listy zadań do wykonania. Oczywiście musi być jakiś limit prób N, np. N=3.

Jakieś podpowiedzi?

( kod z: http://masnun.com/2016/03/29/python-a-quick-introduction-to-the-concurrent-futures-module.html )