2017-12-21 26 views
0

私はビデオゲームのためにleaderboardからデータを非同期的に削り取ろうとしています。毎週、毎日の挑戦があります。これまでのコードはthis async client with semaphoresに基づいています。違いは、関数内でループが使用されている終わりを含むことを試みていることです。ここに私のコードの関連部分です:python aiohttpライブラリを使って複数のWebページをダウンロードするには?

from urllib.parse import urljoin 
import asyncio 
import aiohttp 

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


async def bound_fetch(url, session, sem): 
    async with sem: 
     await fetch(url, session) 

async def fetch_pages(url,pages,session): 
    tasks = [] 
    sem = asyncio.Semaphore(LIMIT) 

    for page in range(pages+1): 
     task_url = urljoin(url,str(page)) 
     task = asyncio.ensure_future(bound_fetch(task_url, session, sem)) 
     tasks.append(task) 

    await asyncio.gather(*tasks) 

def leaderboard_crawler(date, entries=0, pages=1): 
    website = "https://www.thronebutt.com/archive/" 
    date_url = urljoin(website,date+"/") 
    entries_per_page = 30 
    number_of_entries = entries or pages * entries_per_page 
    full_pages, last_page = divmod(number_of_entries,30) 
    entry_list = [30 for x in range(full_pages)] 
    if last_page != 0: 
     entry_list.append(last_page)  

    loop = asyncio.get_event_loop() 
    with aiohttp.ClientSession() as session: 
     future = asyncio.ensure_future(fetch_pages(date_url,pages,session)) 
     date_html = loop.run_until_complete(future) 

    return date_html 

def weekly_leaderboard(week, year, entries=0, pages=1): 
    weekly_date = "{0:02d}{1}".format(week, year) 
    return leaderboard_crawler(weekly_date,entries,pages) 

def daily_leaderboard(day, month, year, entries=0, pages=1): 
    daily_date = "{0:02d}{1:02d}{2}".format(day, month, year) 
    return leaderboard_crawler(daily_date, entries, pages) 

私は問題はfetch_urls機能でasyncio.gather(*tasks)部分であると思います。私はleaderboard_crawlerにそれを渡す方法を理解できません。今すぐdate_htmlはなしです。私はreturn await asyncio.gather(*tasks)を試しました。これはNonesの配列を返します。私もasyncio.ensure_futureにそれをラップしようとしましたが、それをloop.run_until_completeに渡しましたが、どちらもうまくいかないようです。

答えて

2

理由は簡単です、あなたは、コールスタック内のreturnが欠落しています

async def bound_fetch(url, session, sem): 
    async with sem: 
     # await fetch(url, session) # missing return 
     return await fetch(url, session) # this one is right 

async def fetch_pages(url,pages,session): 
    tasks = [] 
    sem = asyncio.Semaphore(LIMIT) 

    for page in range(pages+1): 
     task_url = urljoin(url,str(page)) 
     task = asyncio.ensure_future(bound_fetch(task_url, session, sem)) 
     tasks.append(task) 

    # await asyncio.gather(*tasks) # missing return 
    return await asyncio.gather(*tasks) # this one is right. 

実施例はここにある:

from urllib.parse import urljoin 
import asyncio 
import aiohttp 

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


async def bound_fetch(url, session, sem): 
    async with sem: 
     return await fetch(url, session) 

async def fetch_pages(url,pages,session): 
    tasks = [] 
    sem = asyncio.Semaphore(5) 

    for page in range(pages+1): 
     task_url = urljoin(url,str(page)) 
     task = asyncio.ensure_future(bound_fetch(task_url, session, sem)) 
     tasks.append(task) 

    return await asyncio.gather(*tasks) 

def leaderboard_crawler(date, entries=0, pages=1): 
    website = "https://www.thronebutt.com/archive/" 
    date_url = urljoin(website,date+"/") 
    entries_per_page = 30 
    number_of_entries = entries or pages * entries_per_page 
    full_pages, last_page = divmod(number_of_entries,30) 
    entry_list = [30 for x in range(full_pages)] 
    if last_page != 0: 
     entry_list.append(last_page)  

    loop = asyncio.get_event_loop() 
    with aiohttp.ClientSession() as session: 
     future = asyncio.ensure_future(fetch_pages(date_url,pages,session)) 
     date_html = loop.run_until_complete(future) 

    return date_html 

def weekly_leaderboard(week, year, entries=0, pages=1): 
    weekly_date = "{0:02d}{1}".format(week, year) 
    return leaderboard_crawler(weekly_date,entries,pages) 

def daily_leaderboard(day, month, year, entries=0, pages=1): 
    daily_date = "{0:02d}{1:02d}{2}".format(day, month, year) 
    return leaderboard_crawler(daily_date, entries, pages) 
関連する問題