【问题标题】:How to scrape many HTML documents quickly using Python?如何使用 Python 快速抓取大量 HTML 文档?
【发布时间】:2019-11-17 13:51:47
【问题描述】:

我有一个大约 100 个 HTML 网页的列表(都有不同的结构,例如 div、锚点、类等),我正在尝试抓取每个页面的标题(其中标题位于某个 div 和班级)。为此,我使用了 get requests 和 Beautifulsoup,但是,这需要很长时间(每次我想做 10 分钟)!

我使用了一个计时器来查看花费最多的时间:它是获取请求。显然 Python (3.7) 一个接一个地执行代码,并且由于每个 get 请求大约需要 5-6 秒,因此大约需要 500-600 秒来完成大约 100 个请求。

我一直在寻找使这些请求更快地工作的方法,并遇到了许多不同的解决方案。然而,一个共同的主题似乎是让我的请求异步(因此所有请求同时开始)将解决问题(通过使其更快)。

我在网上阅读了许多可能的解决方案,包括:多线程、使用 grequest、使用 Scrapy、解析 lxml 等。但是,我是编程新手,还不够熟练,无法学习和尝试每种方法(实际上,我尝试按照 SO 上类似问题的答案进行操作,但没有成功),所以我不确定我采取的最佳途径是什么。

我不需要任何花哨的东西;我要做的就是从 HTML 文档中提取标题作为文本,然后将它们打印出来。我不需要下载任何 CSS 文件、图像、媒体等。此外,我希望使代码尽可能简单/裸露。如何在 Python 中尽可能快地做到这一点?如果有人能建议最佳路径(即使用 Scrapy),我将不胜感激,并简要说明我必须使用该工具做什么才能获得我希望的结果。您不必为我写出整个代码。谢谢!

【问题讨论】:

    标签: python html parsing web-scraping scrapy


    【解决方案1】:

    This answer 似乎为您准备了一个可剪切粘贴的答案。 (如果您的 HTML 请求大约需要 5 秒,您也可能会增加线程池大小。)对于您的确切问题,代码:

    def crawlToCSV(URLrecord):
        OpenSomeSiteURL = urllib2.urlopen(URLrecord)
        Soup_SomeSite = BeautifulSoup(OpenSomeSiteURL, "lxml")
        OpenSomeSiteURL.close()
    
        return Soup_SomeSite.title.string
    

    将在results 中创建标题列表。

    【讨论】:

      【解决方案2】:

      我可以建议的一个想法是获取 Csv 中的所有 url,并根据您的要求保留几个标题,如路径、标题 div、body div、图像 div,并继续添加特定的 div(div class=”title” )。

      例如: PATH TITLE DIV IMAGE DIV BODY DIV

      同样,你可以在一个csv文件中给出所有链接,然后通过python脚本读取它,以便提取所有数据。

      【讨论】:

        【解决方案3】:

        快速搜索“python 中的异步抓取”导致 Santhosh Hari 的 this article on medium。请阅读这篇文章,因为他解释了代码的工作原理。

        这篇文章的主要内容如下使用 asyncio 和 aiohttp 库。

        import asyncio
        import aiohttp
        import requests
        
        async def fetch_url(session, url):
            async with session.get(url, timeout=60 * 60) as response:
                return await response.text()
        
        async def fetch_all_urls(session, urls, loop):
            results = await asyncio.gather(*[fetch_url(session, url) for url in urls],
            return_exceptions=True)
            return results
        
        def get_htmls(urls):
            if len(urls) > 1:
                loop = asyncio.get_event_loop()
                connector = aiohttp.TCPConnector(limit=100)
                with aiohttp.ClientSession(loop=loop, connector=connector) as session:
                    htmls = loop.run_until_complete(fetch_all_urls(session, urls, loop))
                raw_result = dict(zip(urls, htmls))
            else:
                headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
                raw_result = requests.get(urls[0], headers=headers).text
        
            return raw_result
        
        result_dict = get_htmls(url_list)
        

        【讨论】:

        • 这个函数中的loop fetch_all_urls(session, urls, loop) 只是一个占位符,什么都不做,不是吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-20
        • 2018-11-17
        • 1970-01-01
        • 2020-04-27
        • 2018-12-26
        • 1970-01-01
        • 2014-05-12
        相关资源
        最近更新 更多