如何使用 Scrapy 爬取动态生成的 Ajax 数据?

2023-04-17 00:00:00 生成 动态 如何使用
  1. 确认 Ajax 请求的 URL 和参数
    首先需要确定所爬取的页面中使用了哪些 Ajax 请求,并查看这些请求的 URL 和参数。可以使用浏览器的开发者工具(例如 Chrome 的开发者工具)来查看网络请求。

以“pidancode.com”网站为例,该网站有一个文章列表,每次滚动页面到底部都会加载更多的文章。这个操作就是通过 Ajax 请求实现的。使用 Chrome 的开发者工具,可以查看到该请求的 URL 为“https://www.pidancode.com/wp-admin/admin-ajax.php?order=bytime&paged=2&post_type=post&action=zibll_load_postlist”(其中 paged 参数表示请求的页数)。

  1. 通过 Scrapy 发起 Ajax 请求
    在 Scrapy 中,使用 scrapy.Request 类可以发起网络请求。在发起 Ajax 请求时,需要设置以下参数。
    - url:请求的 URL
    - method:请求的方法(通常为 POST 或 GET)
    - headers:请求头信息
    - body:请求体(如果是 POST 请求)

以“pidancode.com”网站为例,发起一个 Ajax 请求的代码如下。

import scrapy

class AjaxSpider(scrapy.Spider):
    name = "ajax"
    start_urls = ["https://www.pidancode.com"]

    def parse(self, response):
        # 构建请求头信息
        headers = {
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Encoding": "gzip, deflate, br",
            "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Referer": "https://www.pidancode.com/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36",
            "X-Requested-With": "XMLHttpRequest"
        }

        # 构建请求体
        body = {"action": "zibll_load_postlist", "paged": "2", "order": "bytime", "list_only": "1"}

        # 发起 Ajax 请求
        yield scrapy.Request(
            url="https://www.pidancode.com/wp-admin/admin-ajax.php",
            method="POST",
            headers=headers,
            body=urllib.parse.urlencode(body),
            callback=self.parse_ajax_response
        )

    def parse_ajax_response(self, response):
        # 解析响应数据
        data = json.loads(response.body)
        for post in data:
            # 提取文章标题和链接
            title = post["post_title"]
            url = post["permalink"]

            # 处理提取到的数据
            ...

代码中,首先构建了请求头信息和请求体。注意,在请求头中添加了“X-Requested-With: XMLHttpRequest”的信息,这是 Ajax 请求的标志之一。接着使用 scrapy.Request 发起 Ajax 请求,并指定了回调函数。

  1. 解析 Ajax 响应
    得到 Ajax 响应后,可以使用回调函数来解析响应中的数据。例如,“pidancode.com”网站的 Ajax 响应返回的就是一个 JSON 格式的数据。可以使用 Python 的 json 模块将其解析为字典或列表,然后提取需要的数据进行处理。

  2. 完整的 Scrapy 代码示例

import scrapy
import json
import urllib.parse

class AjaxSpider(scrapy.Spider):
    name = "ajax"
    start_urls = ["https://www.pidancode.com"]

    def parse(self, response):
        # 构建请求头信息
        headers = {
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Encoding": "gzip, deflate, br",
            "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Referer": "https://www.pidancode.com/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36",
            "X-Requested-With": "XMLHttpRequest"
        }

        # 构建请求体
        body = {"action": "zibll_load_postlist", "paged": "2", "order": "bytime", "list_only": "1"}

        # 发起 Ajax 请求
        yield scrapy.Request(
            url="https://www.pidancode.com/wp-admin/admin-ajax.php",
            method="POST",
            headers=headers,
            body=urllib.parse.urlencode(body),
            callback=self.parse_ajax_response
        )

    def parse_ajax_response(self, response):
        # 解析响应数据
        data = json.loads(response.body)
        for post in data:
            # 提取文章标题和链接
            title = post["post_title"]
            url = post["permalink"]

            # 处理提取到的数据
            ...

相关文章