Python asyncio веб-очистка не экспортируется в Excel - PullRequest
0 голосов
/ 26 декабря 2018

Я новичок в Python asyncio.Я хочу экспортировать очищенные данные, чтобы преуспеть, используя панд.Похоже, мой код ниже очищает целевые поля, но пока я экспортирую вывод, используя pandas для преуспевания, я получаю пустой выходной файл.

import asyncio
from concurrent.futures.thread import ThreadPoolExecutor
import pandas as pd
import os
import requests
from bs4 import BeautifulSoup

input_file = os.path.join(os.getcwd(), 'Sample.xlsx')
df = pd.read_excel(input_file, usecols=0)

req = requests.Session()
req.trust_env = False

Url, title, price = [], [], [],
executor = ThreadPoolExecutor(10)


def scrape(url, *, loop):
    loop.run_in_executor(executor, load_html, url)


def load_html(url):
    print(url)
    res = req.get(url)
    soup = BeautifulSoup(res.content, 'html.parser')
    Url.append(url)
    title.append(soup.select('.pinfo-title')[0].text)
    price.append(soup.select('.sale-price')[0].text)


loop = asyncio.get_event_loop()
for url in df['Urls']:
    scrape(url, loop=loop)

loop.run_until_complete(asyncio.gather(*asyncio.all_tasks(loop)))

output = pd.DataFrame({
        'Url': Url,
        'Title': title,
        'Price': price
})
output.to_excel('Output.xlsx', index=False)

, но если я использую печать вместо добавления списков, таких как ниже, то этораспечатать нужный вывод.

def load_html(url):
    print(url)
    res = req.get(url)
    soup = BeautifulSoup(res.content, 'html.parser')
    print(url)
    print(soup.select('.pinfo-title')[0].text)
    print(soup.select('.sale-price')[0].text)

1 Ответ

0 голосов
/ 27 декабря 2018

Похоже, run_in_executor не добавляет задачу в цикл.Это нужно ждать.Таким образом, вам нужно обернуть это в подпрограмму и создать задачу в цикле.Ниже приведен более простой пример.

import asyncio
from urllib.request import urlopen
import json

URLS = [
    "http://localhost:8000/a",
    "http://localhost:8000/b",
    "http://localhost:8000/c",
    "http://localhost:8000/d",
]

data = []


def load_html(url):
    print(url)
    res = urlopen(url)
    data.append(res.read().decode())


async def scrape(url, loop):
    await loop.run_in_executor(None, load_html, url)


def main():
    loop = asyncio.get_event_loop()
    for url in URLS:
        loop.create_task(scrape(url, loop))

    loop.run_until_complete(asyncio.gather(*asyncio.all_tasks(loop)))
    with open('/tmp/j_dump', 'w') as fp:
        json.dump(data, fp)


if __name__ == '__main__':
    main()

Обновление:

Код можно упростить, как показано ниже.Нет необходимости в дополнительных подпрограммах или глобальных данных.

def load_html(url):
    print(url)
    res = urlopen(url)
    return res.read().decode()


def main():
    loop = asyncio.get_event_loop()
    tasks = [loop.run_in_executor(None, load_html, url) for url in URLS]
    data = loop.run_until_complete(asyncio.gather(*tasks))
    with open('/tmp/j_dump', 'w') as fp:
        json.dump(data, fp)
...