You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy爬取无分页无限滚动书店网站书籍信息失败问题排查

问题核心原因

爬取失败由两点直接导致:

  • 目标站点采用接口驱动的无限滚动懒加载,不存在静态下一页跳转链接,页面滚动时会向后端发送POST请求拉取下一批书籍数据。原有代码仅请求了首屏静态HTML,只能拿到首屏渲染的少量内容;且原有翻页逻辑完全错误,循环中引用的book是上一轮遍历的最后一个单本书选择器对象,根本不是分页地址,同时代码里引用的self.parse_links方法未做任何定义,运行会直接报错。
  • 原有CSS选择器匹配逻辑不严谨,存在错抓、漏抓字段的问题。
落地解决方法

1. 定位懒加载接口

打开浏览器开发者工具,切换到「网络」面板,选择「Fetch/XHR」类型过滤,在分类页向下滚动触发内容加载,就能抓到站点拉取书籍列表的POST接口:

  • 接口请求参数中包含分页页码字段,初始加载页码为1,每触发一次加载页码递增
  • 接口返回JSON格式数据,直接包含所有书籍的标题、作者、详情页标识等字段,无需额外解析HTML结构,爬取效率远高于解析页面源码

2. 修正后的爬虫代码

直接构造接口请求循环翻页即可,无需使用模拟浏览器方案,参考代码如下:

import scrapy
import json

class BooksSpider(scrapy.Spider):
    name = 'books'
    allowed_domains = ['www.aseeralkotb.com']
    # 以下3个参数均从浏览器抓到的接口中提取替换
    list_api = "替换为抓取到的列表接口地址"
    category_id = "替换为政治分类对应的ID参数值"
    page_size = 20 # 和接口默认的每页返回条数保持一致即可
    
    current_page = 1

    def start_requests(self):
        yield scrapy.Request(
            url=self.list_api,
            method="POST",
            body=json.dumps({
                "categoryId": self.category_id,
                "page": self.current_page,
                "limit": self.page_size
            }),
            headers={
                "Content-Type": "application/json",
                "Referer": "https://www.aseeralkotb.com/categories/%D8%B3%D9%8A%D8%A7%D8%B3%D8%A9",
                "User-Agent": "替换为你自己浏览器的UA值,避免被反爬拦截"
            },
            callback=self.parse
        )

    def parse(self, response):
        resp_data = response.json()
        book_list = resp_data.get("data", {}).get("books", [])
        # 返回空列表说明已到最后一页,终止爬取
        if not book_list:
            return

        for book in book_list:
            yield {
                "title": book.get("title"),
                "author": book.get("author", {}).get("name"),
                "detailslinks": f"/books/{book.get('slug')}"
            }
            # 若需要爬取详情页内容,在这里follow详情链接,指定对应解析回调即可

        # 构造下一页请求
        self.current_page += 1
        yield scrapy.Request(
            url=self.list_api,
            method="POST",
            body=json.dumps({
                "categoryId": self.category_id,
                "page": self.current_page,
                "limit": self.page_size
            }),
            headers={
                "Content-Type": "application/json",
                "Referer": "https://www.aseeralkotb.com/categories/%D8%B3%D9%8A%D8%A7%D8%B3%D8%A9",
                "User-Agent": "替换为你自己浏览器的UA值,避免被反爬拦截"
            },
            callback=self.parse
        )

注意事项

  • 代码里的接口地址、分类ID、请求体参数不要直接硬抄,必须从自己浏览器开发者工具抓到的真实接口里复制,站点可能随时调整接口规则
  • 如果接口加了签名、token校验,直接从浏览器请求头里复制对应参数加到请求头里即可
  • 爬取时控制请求频率,不要短时间发大量请求,避免被站点封禁IP

内容的提问来源于stack exchange,提问作者Karim Bn Abdlaziz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 08:09:42