Scrapy 抓取无限滚动页面

发布于 2024-12-01 20:05:46 字数 3287 浏览 5 评论 0

在单页应用以及每页具有大量 AJAX 请求的时代,很多网站已经用花哨的无限滚动机制取代了“前一个/下一个”分页按钮。使用这种技术的网站每当用户滚动到页面的底部的时候加载新项(想想微博,Facebook,谷歌图片)。虽然 UX 专家 认为,无限滚动为用户提供了海量数据,但是我们看到越来越多的 web 页面诉诸于展示这种无休止的结果列表。

在开发 web 爬虫时,我们要做的第一件事就是找到能将我们引导到下一页结果的带有链接的 UI 组件。不幸的是,这些链接在无限滚动页面上不存在。

虽然这种场景可能看起来像诸如 Splash 或者 Selenium 这样的 JavaScript 引擎的一个经典案例,但是它实际上是一个简单的修复。你所需要做的是在你滚动目标页面的时候检查浏览器的 AJAX 请求,然后在 Scrapy spider 中重新创建这些请求,而不是模拟用于与此类引擎的交互。

让我们以 Spidy Quotes 为例,构建一个爬虫来获取上面列出来的所有的项。

审查页面

先说重要的事,我们需要理解无限滚动是如何在这个页面工作的,我们可以通过 浏览器的开发者工具 中的 Network 面板来完成此项工作。打开该面板,然后滚动页面,看看浏览器发送了什么请求:

点开一个请求仔细看看。浏览器发送了一个请求到 /api/quotes?page=x ,然后接收诸如以下的一个 JSON 对象作为响应:


    {
       "has_next":true,
       "page":8,
       "quotes":[
          {
             "author":{
                "goodreads_link":"/author/show/1244.Mark_Twain",
                "name":"Mark Twain"
             },
             "tags":["individuality", "majority", "minority", "wisdom"],
             "text":"Whenever you find yourself on the side of the ..."
          },
          {
             "author":{
                "goodreads_link":"/author/show/1244.Mark_Twain",
                "name":"Mark Twain"
             },
             "tags":["books", "contentment", "friends"],
             "text":"Good friends, good books, and a sleepy ..."
          }
       ],
       "tag":null,
       "top_ten_tags":[["love", 49], ["inspirational", 43], ...]
    }

这就是我们的爬虫需要的信息了。它所需要做的仅是生成到"/api/quotes?page=x"的请求,其中, x 的值不断增加,直到 has_next 字段为 false。这样做最棒的是,我们甚至无需爬取 HTML 内容以获取所需数据。这些数据都在一个漂亮的机器可读的 JSON 中。

构建 Spider

下面是我们的 spider。它从服务器返回的 JSON 内容提取目标数据。这种方法比挖掘页面的 HTML 树更容易并且更健壮,相信布局的改变不会搞挂我们的 spider。


    import json
    import scrapy


    class SpidyQuotesSpider(scrapy.Spider):
        name = 'spidyquotes'
        quotes_base_url = 'http://spidyquotes.herokuapp.com/api/quotes?page=%s' 
        start_urls = [quotes_base_url % 1]
        download_delay = 1.5

        def parse(self, response):
            data = json.loads(response.body)
            for item in data.get('quotes', []):
                yield {
                    'text': item.get('text'),
                    'author': item.get('author', {}).get('name'),
                    'tags': item.get('tags'),
                }
            if data['has_next']:
                next_page = data['page'] + 1
                yield scrapy.Request(self.quotes_base_url % next_page)

要进一步练习这个技巧,你可以做个实验,爬取我们的博客,因为它也是使用无限滚动来加载旧博文的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

神经大条

暂无简介

文章
评论
24 人气
更多

推荐作者

葬花如无物

文章 0 评论 0

nick

文章 0 评论 0

来世叙缘

文章 0 评论 0

凉城已无爱

文章 0 评论 0

樱桃奶球

文章 0 评论 0

梦中的蝴蝶

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文