Оптимизируйте просмотр списка URL и пишите в csv - PullRequest
0 голосов
/ 14 октября 2019

С помощью csv из 20k + url я хочу очистить и найти html-элемент "super-attribute-select". Если найдено, укажите URL-адрес в столбце A вместе с номером продукта (sku) в столбце B. Если не найдено, укажите URL-адрес в столбце C и sku в столбце D. Наконец, сохраните кадр данных в файл CSV.

Если я запускаю следующий код, он работает, но моей программе не хватает памяти. Было приятно найти способ оптимизировать это. Теперь для обработки ~ 1500 URL-адресов требуется 5 часов. В то время как весь CSV составляет 20 тыс.

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 scrap, pass url, open with soup, and find class
def scrap(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:
    scrap(i)

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Вы можете использовать пул либо с 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 scrap, pass url, open with soup, and find class
def scrap(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(scrap, urllist)
0 голосов
/ 14 октября 2019

Если бы я делал это, я бы попробовал несколько вещей:

(1) Обновите словарь вместо добавления в список. Я думаю, что словари работают быстрее и эффективнее, чем списки.

(2) Вместо того, чтобы экспортировать каждый результат URL в виде CSV с тем же именем, либо (а) предпочтительнее: подождите, пока вы закончите, чтобы экспортировать всерезультаты в виде одного CSV или (б) хуже: возможно, экспортируйте их в разные имена файлов, используя f-строки вместо того, чтобы каждый раз перезаписывать «Test.csv».

...