asyncio / aiohttp не возвращает ответ - PullRequest
0 голосов
/ 15 марта 2019

Я пытаюсь очистить некоторые данные из https://www.officialcharts.com/ путем распараллеливания веб-запросов с использованием asyncio / aiohttp.Я реализовал код, приведенный по ссылке здесь .

Я выполнил две разные процедуры.Первый из них выглядит следующим образом.

from bs4 import BeautifulSoup
from urllib.request import urlopen
from selenium import webdriver
import time
import pandas as pd
import numpy as np
import re
import json

import requests
from bs4 import BeautifulSoup
from datetime import date, timedelta
from IPython.display import clear_output
import memory_profiler

import spotipy
import spotipy.util as util
import pandas as pd
from  more_itertools import unique_everseen

weeks = []
d = date(1970, 1, 1) 
d += timedelta(days = 6 - d.weekday())

for i in range(2500):    
    weeks.append(d.strftime('%Y%m%d'))
    d += timedelta(days = 7)

import asyncio
from aiohttp import ClientSession
import nest_asyncio
nest_asyncio.apply()

result = []
async def fetch(url, session):
    async with session.get(url) as response:
        return await response.read()

async def run(r):  
    tasks = []

    # Fetch all responses within one Client session,
    # keep connection alive for all requests.
    async with ClientSession() as session:
        for i in range(r):
            url = 'https://www.officialcharts.com/charts/singles-chart/' + weeks[i] + '/'
            task = asyncio.ensure_future(fetch(url, session))
            tasks.append(task)

        responses = await asyncio.gather(*tasks)
        result.append(responses)


loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(5))
loop.run_until_complete(future)

print('Done')
print(result[0][0] == None)

Проблема с приведенным выше кодом заключается в том, что происходит сбой при выполнении более 1000 одновременных запросов.

Автор сообщения реализовал другую процедуру для решения этой проблемы, и он утверждает, что мы можем выполнить до 10 000 запросов.Я выполнил его вторую процедуру, и вот мой код для этого.

import random
import asyncio
from aiohttp import ClientSession
import nest_asyncio
nest_asyncio.apply()

result = []
async def fetch(url, session):
    async with session.get(url) as response:
        delay = response.headers.get("DELAY")
        date = response.headers.get("DATE")
        print("{}:{} with delay {}".format(date, response.url, delay))
        return await response.read()


async def bound_fetch(sem, url, session):
    # Getter function with semaphore.
    async with sem:
        await fetch(url, session)


async def run(r):
    tasks = []
    # create instance of Semaphore
    sem = asyncio.Semaphore(1000)

    # Create client session that will ensure we dont open new connection
    # per each request.
    async with ClientSession() as session:
        for i in range(r):         
            url = 'https://www.officialcharts.com/charts/singles-chart/' + weeks[i] + '/'
            task = asyncio.ensure_future(bound_fetch(sem, url, session))
            tasks.append(task)

        responses = await asyncio.gather(*tasks)
        result.append(responses)

number = 5

loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(number))
loop.run_until_complete(future)

print('Done')
print(result[0][0] == None)

По какой-то причине это не возвращает никаких ответов.

PS: я не из КС, ипросто программа для удовольствия.Я понятия не имею, что происходит внутри кода asyncio.

1 Ответ

1 голос
/ 15 марта 2019

Попробуйте использовать последнюю версию.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# python 3.7.2

from aiohttp import ClientSession, client_exceptions
from asyncio import Semaphore, ensure_future, gather, run

limit = 10
http_ok = [200]


async def scrape(url_list):

    tasks = list()

    sem = Semaphore(limit)

    async with ClientSession() as session:
        for url in url_list:
            task = ensure_future(scrape_bounded(url, sem, session))
            tasks.append(task)

        result = await gather(*tasks)

    return result


async def scrape_bounded(url, sem, session):
    async with sem:
        return await scrape_one(url, session)


async def scrape_one(url, session):

    try:
        async with session.get(url) as response:
            content = await response.read()
    except client_exceptions.ClientConnectorError:
        print('Scraping %s failed due to the connection problem', url)
        return False

    if response.status not in http_ok:
        print('Scraping%s failed due to the return code %s', url, response.status)
        return False

    return content


if __name__ == '__main__':
    urls = ['http://demin.co:8080/1', 'http://demin.co:8080/2']
    res = run(scrape(urls))

    print(res)

Это шаблон реального проекта , который работает как предсказано.

...