【问题标题】:Simple web crawler very slow简单的网络爬虫非常慢
【发布时间】:2017-03-31 10:37:16
【问题描述】:

我已经构建了一个非常简单的网络爬虫来爬取下面 URL 中的大约 100 个小 json 文件。问题是爬虫需要一个多小时才能完成。考虑到 json 文件的大小,我发现这很难理解。我在这里做错了什么吗?

def get_senate_vote(vote):
    URL = 'https://www.govtrack.us/data/congress/113/votes/2013/s%d/data.json' % vote
    response = requests.get(URL)
    json_data = json.loads(response.text)
    return json_data

def get_all_votes():
    all_senate_votes = []
    URL = "http://www.govtrack.us/data/congress/113/votes/2013"    
    response = requests.get(URL)           
    root = html.fromstring(response.content)
    for a in root.xpath('/html/body/pre/a'):
        link = a.xpath('text()')[0].strip()
        if link[0] == 's':
            vote = int(link[1:-1])
            try:
                vote_json = get_senate_vote(vote)
            except:
                return all_senate_votes
            all_senate_votes.append(vote_json)

    return all_senate_votes

vote_data = get_all_votes()

【问题讨论】:

    标签: python json web-crawler


    【解决方案1】:

    这是一个相当简单的代码示例,我计算了每次调用所花费的时间。在我的系统上,每个请求平均占用 2 secs,并且有 582 个页面要访问,所以在 19 mins 附近,无需将 JSON 打印到控制台。在您的情况下,网络时间加上打印时间可能会增加。

    #!/usr/bin/python
    
    import requests
    import re
    import time
    def find_votes():
        r=requests.get("https://www.govtrack.us/data/congress/113/votes/2013/")
        data = r.text
        votes = re.findall('s\d+',data)
        return votes
    
    def crawl_data(votes):
        print("Total pages: "+str(len(votes)))
        for x in votes:
            url ='https://www.govtrack.us/data/congress/113/votes/2013/'+x+'/data.json'
            t1=time.time()
            r=requests.get(url)
            json = r.json()
            print(time.time()-t1)
    crawl_data(find_votes())
    

    【讨论】:

    • 这很有帮助,谢谢!我对爬行不太有经验,但我预计它会快得多
    • 有办法做到这一点。由于您已经有一个页面列表,因此您可以并行执行。尝试 python 池。运行多个线程,它会更快。请注意最后的速率限制。
    【解决方案2】:

    如果您正在使用 python 3.x 并且正在爬取多个站点,为了获得更好的性能,我热忱地建议您使用实现 asynchronous 原则的 aiohttp 模块。 例如:

    import aiohttp
    import asyncio
    
    sites = ['url_1', 'url_2']
    results = []
    
    def save_reponse(result):
        site_content = result.result()
        results.append(site_content)
    
    async def crawl_site(site):
        async with aiohttp.ClientSession() as session:
            async with session.get(site) as resp:
                resp = await resp.text()
                return resp
    
    tasks = []
    for site in sites:
        task = asyncio.ensure_future(crawl_site(site))
        task.add_done_callback(save_reponse)
        tasks.append(task)
    all_tasks = asyncio.gather(*tasks)
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(all_tasks)
    loop.close()
    
    print(results) 
    

    更多关于aiohttp的阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 2017-01-26
      • 2016-06-23
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      相关资源
      最近更新 更多