【问题标题】:Python - Speeding up Web Scraping using multiprocessingPython - 使用多处理加速 Web Scraping
【发布时间】:2022-01-27 13:39:30
【问题描述】:

我有以下功能来抓取网页。

def parse(link: str, list_of_samples: list, index: int) -> None:
    # Some code to scrape the webpage (link is given)
    # The code will generate a list of strings, say sample
    list_of_samples[index] = sample

我有另一个脚本,它为列表中存在的所有 URL 调用上述脚本

def call_that_guy(URLs: list) -> list:
    samples = [None for i in range(len(URLs))]
    for i in range(len(URLs)):
        parse(URLs[i], samples, i)
    return samples

调用上述函数的其他函数

def caller() -> None:
    URLs = [url_1, url_2, url_3, ..., url_n]
    # n will not exceed 12
    samples = call_thay_guy(URLs)
    print(samples)

# Prints the list of samples, but is taking too much time

我注意到的一件事是解析函数需要大约 10 秒来解析单个网页(我使用的是 Selenium)。因此,解析列表中存在的所有 URL 大约需要 2 分钟。我想加快速度,可能使用多线程。

我尝试执行以下操作。

import threading

def call_that_guy(URLs: list) -> list:
    threads = [None for i in range(len(URLs))]
    samples = [None for i in range(len(URLs))]
    for i in range(len(URLs)):
        threads[i] = threading.Thread(target = parse, args = (URLs[i], samples, i))
        threads[i].start()
    return samples

但是,当我打印返回值时,它的所有内容都是None。

我想要实现什么:

我想异步抓取 URL 列表并填充示例列表。填充列表后,我还有一些其他语句要执行(它们应该仅在填充样本后执行,否则它们会导致异常)。我想更快地抓取 URL 列表(允许异步),而不是一个接一个地抓取它们。

(我可以用图片更清楚地解释一些事情)

【问题讨论】:

    标签: python-3.x multithreading selenium


    【解决方案1】:

    为什么不使用concurrent.futures 模块?

    这是一个使用concurrent.futures的非常简单但超级快速的代码:

    import concurrent.futures
    
    
    def scrape_url(url):
        print(f'Scraping {url}...')
        scraped_content = '<html>scraped content!</html>'
        return scraped_content
    
    urls = ['https://www.google.com', 'https://www.facebook.com', 'https://www.youtube.com']
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        results = executor.map(scrape_url, urls)
    
    print(list(results))
    # Expected output:
    # ['<html>scraped content!</html>', '<html>scraped content!</html>', '<html>scraped content!</html>']
    

    如果你想学习线程,我推荐观看这个简短的教程:https://www.youtube.com/watch?v=IEEhzQoKtQU

    还要注意,这不是多处理,这是多线程,两者不一样。想了解更多区别,可以看这篇文章:https://realpython.com/python-concurrency/

    希望这能解决您的问题。

    【讨论】:

    • 嗨,我也想保留返回值的顺序。正式地,对于您的示例,我想要 google.com 的内容,然后是 facebook.com 的内容,依此类推。它会保留顺序吗?
    • 嘿,是的,它绝对保持与urls 列表相同的顺序。如果回答正确,请采纳。谢谢。
    猜你喜欢
    • 2018-07-15
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 2022-06-21
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多