【问题标题】:Optimize scraping through list of urls and write to csv通过 url 列表优化抓取并写入 csv
【发布时间】:2019-10-14 18:30:36
【问题描述】:

使用 20k+ url 的 csv,我想抓取并找到 html 元素“super-attribute-select”。如果找到,将 url 写入 A 列,将产品编号 (sku) 写入 B 列。如果找不到,将 url 写入 C 列,将 sku 写入 D 列。最后,将数据框保存到 csv 文件。

如果我运行以下代码,它可以工作,但我的程序内存不足。它喜欢找到一种方法来优化它。现在约 1500 个网址需要 5 小时来处理。而整个 csv 是 20k。

import urllib.request
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
from pandas import Series


urlList = pd.read_csv(r"url.csv")
urlList = urlList.url.tolist()
notfound = []
found = []
skulist =[]
skumissinglist =[]


# Function scrape, pass url, open with soup, and find class
def scrape(url):
    tag ='select'
    classused = "super-attribute-select"
    d = dict(A=np.array(found), B=np.array(skulist), C=np.array(notfound), D=np.array(skumissinglist))

    try:
        content = urllib.request.urlopen(url)
        soup = BeautifulSoup(content, features="html.parser")
        sku= soup.find("div", {"itemprop": "sku"}).string
        result = soup.find(tag, class_=classused)
        #soup returns None if can't find anything
        if result == None:
            notfound.append(url)
            skumissinglist.append(sku)
        else:
            found.append(url)
            skulist.append(sku)

    except:
        result = print("Some extraction went wrong")

    df = pd.DataFrame(dict([(k, Series(v)) for k, v in d.items()]))
    df = df.to_csv('Test.csv')

for i in urlList:
    scrape(i)

【问题讨论】:

  • 对于内存优化做:每次你使用 'with .... open' 抓取一行时将其转储到 csv 中,对于时间优化,使用多线程而不是顺序循环过程
  • 仅供参考,它是 scrape(和 scraperscrapingscraped)而不是 scrap

标签: python pandas optimization beautifulsoup numpy-ndarray


【解决方案1】:

如果我这样做,我会尝试一些事情:

(1) 更新字典而不是追加到列表。我认为字典比列表更快,内存效率更高。

(2) 不是将每个 URL 结果导出为具有相同名称的 CSV,而是 (a) 首选:等到您完成将所有结果导出为单个 CSV,或者 (b) 更糟糕:可能将它们导出到通过使用 f 字符串而不是每次都覆盖“Test.csv”来获得不同的文件名。

【讨论】:

    【解决方案2】:

    您可以使用 gevent 或 urllib3(或请求)的内置池。然后您可以根据池大小一次执行 10 或 100 个,并使用异步队列在池耗尽时获取剩余的队列。

    from gevent import monkey, spawn, joinall
    monkey.patch_all()
    from gevent.pool import Pool as GeventPool
    import pandas as pd
    from pandas import Series
    import numpy as np
    import requests
    from bs4 import BeautifulSoup
    
    urlList = pd.read_csv(r"url.csv")
    urlList = urlList.url.tolist()
    pool = GeventPool(10)
    notfound = []
    found = []
    skulist =[]
    skumissinglist =[]
    count = len(urllist)
    
    # Function scrape, pass url, open with soup, and find class
    def scrape(url):
        tag ='select'
        classused = "super-attribute-select"
        d = dict(A=np.array(found), B=np.array(skulist), C=np.array(notfound), D=np.array(skumissinglist))
    
        try:
            content = requests.get(url).text
            soup = BeautifulSoup(content, features="html.parser")
            sku= soup.find("div", {"itemprop": "sku"}).string
            result = soup.find(tag, class_=classused)
            #soup returns None if can't find anything
            if result == None:
                notfound.append(url)
                skumissinglist.append(sku)
            else:
                found.append(url)
                skulist.append(sku)
    
        except:
            print("Some extraction went wrong")
    
        df = pd.DataFrame(dict([(k, Series(v)) for k, v in d.items()]))
        return df.to_csv('Test.csv')
    
    pool.map(scrape, urllist)
    

    【讨论】:

      猜你喜欢
      • 2020-09-02
      • 1970-01-01
      • 2018-10-24
      • 1970-01-01
      • 1970-01-01
      • 2017-02-10
      • 2019-11-12
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多