【问题标题】:using dask for scraping via requests使用 dask 通过请求进行抓取
【发布时间】:2018-05-15 16:21:54
【问题描述】:

我喜欢 dask 的简单性,并且很想用它来刮擦当地的超市。我的 multiprocessing.cpu_count() 是 4,但是这段代码只实现了 2 倍的加速。为什么?

from bs4 import BeautifulSoup
import dask, requests, time
import pandas as pd

base_url = 'https://www.lider.cl/supermercado/category/Despensa/?No={}&isNavRequest=Yes&Nrpp=40&page={}'

def scrape(id):
    page = id+1; start = 40*page
    bs = BeautifulSoup(requests.get(base_url.format(start,page)).text,'lxml')
    prods = [prod.text for prod in bs.find_all('span',attrs={'class':'product-description js-ellipsis'})]
    prods = [prod.text for prod in prods]
    brands = [b.text for b in bs.find_all('span',attrs={'class':'product-name'})]

    sdf = pd.DataFrame({'product': prods, 'brand': brands})
    return sdf

data = [dask.delayed(scrape)(id) for id in range(10)]
df = dask.delayed(pd.concat)(data)
df = df.compute()

【问题讨论】:

    标签: python-requests screen-scraping dask dask-delayed


    【解决方案1】:

    首先,2 倍加速 - 万岁!

    你会想从阅读http://dask.pydata.org/en/latest/setup/single-machine.html开始

    简而言之,以下三点在这里可能很重要:

    • 你只有一个网络,所有数据都必须通过它,所以这可能是一个瓶颈
    • 默认情况下,您使用线程进行并行化,但 python GIL 限制并发执行(参见上面的链接)
    • concat 操作发生在单个任务中,因此无法并行化,并且某些数据类型可能占总时间的很大一部分。您还可以使用.compute() 将所有最终数据绘制到客户的流程中。

    【讨论】:

    • 谢谢马丁,非常有见地的评论。特别是“你有一个网络”打开了我的大脑。我将继续在 Amazon Batch 上实现这一点。
    【解决方案2】:

    multiprocessingmultithreading 之间存在显着差异。 See my answer here 对差异的简要评论。在您的情况下,这只会获得 2 倍的加速,而不是 10 倍 - 50 倍以上的加速。

    基本上,通过添加更多内核,您的问题不会像通过添加线程那样扩展(因为它受 I/O 限制......而不是处理器限制)。

    将 Dask 配置为在 multithreaded 模式下运行,而不是在 multiprocessing 模式下运行。我不确定如何在 dask 中执行此操作,但 this documentation 可能会有所帮助

    【讨论】:

      猜你喜欢
      • 2019-03-12
      • 2023-03-23
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      • 2021-12-27
      相关资源
      最近更新 更多