news 2026/5/15 3:25:49

Python爬虫实战(一):图书网站API接口爬取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python爬虫实战(一):图书网站API接口爬取

一、前言

在大数据时代,数据采集是数据分析的第一步。对于初学者来说,爬虫技术往往从静态网页起步,但现代Web应用大量采用前后端分离架构,数据通过Ajax接口动态加载。这种场景下,传统的BeautifulSoup解析HTML往往力不从心,必须转向API接口分析JSON数据解析

本文将以 Scrape Center图书网站 为实战目标,深入讲解如何:

  • 分析动态网站的API接口规律
  • 使用requests库构造请求并处理SSL证书问题
  • 解析嵌套JSON数据结构
  • 实现列表页+详情页的两级爬取策略
  • 使用pandas进行数据清洗与持久化存储

目标站点特点:该网站是一个典型的单页应用(SPA),页面内容由JavaScript渲染,数据通过RESTful API接口返回JSON格式,非常适合练习接口型爬虫技术。


二、网站分析与接口探测

2.1 网站首页概览

首先打开目标网站https://spa5.scrape.center/,可以看到一个精美的图书展示页面:

观察发现:页面加载后,图书信息并非直接写在HTML源码中,而是通过异步请求获取。这意味着我们需要打开浏览器开发者工具(F12),切换到Network → XHR面板,分析背后的数据接口。

2.2 接口规律分析

通过抓包分析,我们可以发现两个核心API:

接口类型URL格式说明
列表接口https://spa5.scrape.center/api/book/?limit={数量}&offset={偏移量}返回图书列表,含基础信息
详情接口https://spa5.scrape.center/api/book/{id}/返回单本图书的详细信息

分页参数逻辑:

  • limit:每页返回的图书数量(实测为18条/页)
  • offset:数据偏移量,第1页offset=0,第2页offset=18,以此类推

这种偏移量分页(Offset-based Pagination)是RESTful API中最常见的分页方式之一,相比页码分页更加灵活,但也需要注意边界条件判断。

2.3 返回数据结构剖析

列表接口返回的JSON结构如下(已简化):

{"count":1000,"results":[{"id":"1","name":"解忧杂货店","authors":["东野圭吾"],"score":"8.5","price":39.5,"cover":"https://.../cover.jpg"}]}

详情接口返回更丰富的字段:

{"id":"1","name":"解忧杂货店","authors":["东野圭吾"],"tags":["小说","日本文学","治愈"],"url":"https://spa5.scrape.center/detail/1","introduction":"...","comments":[...]}

关键洞察:id字段是连接列表页与详情页的枢纽。列表页获取id,再拼接详情页URL获取完整数据——这是典型的两级爬取架构


三、代码实现与深度解析

3.1 完整源码

importjsonimportpandasaspdimportrequestsimporturllib3# ========================================# 第一部分:环境配置与初始化# ========================================# urllib3.disable_warnings() 的作用是禁用由 urllib3 引发的 SSL 证书验证警告。# 目标站点使用了自签名证书或证书链不完整,直接请求会抛出 InsecureRequestWarning。# 在生产环境中,建议配置正确的证书路径而非直接禁用,此处仅为学习目的。urllib3.disable_warnings()# 初始化数据容器:采用"列式存储"策略,每个字段维护一个列表# 这种设计便于最后直接构建 DataFrame,比逐行追加字典效率更高book_ids=[]# 图书IDnames=[]# 书名authors_list=[]# 作者(可能有多位,需处理为字符串)urls=[]# 详情页链接themes=[]# 主题标签# 构造请求头:模拟真实浏览器行为,绕过基础的UA检测反爬机制# 现代反爬系统会检查User-Agent、Accept-Language等字段的一致性headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ''AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0','Accept':'application/json, text/plain, */*','Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8','Referer':'https://spa5.scrape.center/'}# ========================================# 第二部分:分页爬取逻辑# ========================================RECORDS_PER_PAGE=18# 每页记录数,与接口limit参数保持一致MAX_PAGES=3# 控制爬取页数,避免对目标服务器造成过大压力page=0# 页码计数器whilepage<MAX_PAGES:# 计算偏移量:offset = 页码 × 每页数量# 这种分页方式的优势在于可以灵活调整起始位置,支持"断点续爬"offset=page*RECORDS_PER_PAGE# 构造列表页API地址:使用f-string进行参数拼接,清晰直观list_url=f'https://spa5.scrape.center/api/book/?limit={RECORDS_PER_PAGE}&offset={offset}'print(f"\n{'='*50}")print(f"正在爬取第{page+1}页,偏移量 offset={offset}")print(f"请求URL:{list_url}")print(f"{'='*50}")# 发送GET请求:# verify=False 跳过SSL证书验证(学习用途)# timeout参数建议添加,防止网络波动导致程序卡死try:response=requests.get(list_url,headers=headers,verify=False,timeout=10)response.raise_for_status()# 检查HTTP状态码,4xx/5xx会抛出异常exceptrequests.RequestExceptionase:print(f"请求失败:{e}")break# 解析JSON响应:requests内置的.json()方法比json.loads(response.text)更简洁# 但底层原理相同:将JSON字符串反序列化为Python字典data=response.json()# 边界条件判断:如果results为空列表,说明已到达最后一页,优雅退出循环ifnotdata.get('results'):print("未获取到数据,可能已到达最后一页,爬取结束。")break# ========================================# 第三部分:列表页数据提取 + 详情页递归爬取# ========================================# 遍历当前页的每一本图书forbook_itemindata['results']:# 提取列表页已有字段book_id=book_item['id']book_name=book_item['name']# 作者字段处理技巧:# 接口返回的是列表类型,如 ["东野圭吾"] 或 ["刘慈欣", "韩松"]# 需要转换为字符串,同时清洗换行符、单引号等噪音字符book_authors=str(book_item['authors'])\.replace('[','')\.replace(']','')\.replace("'","")\.replace('\\n','')\.strip()print(f"\n[列表页] ID:{book_id}| 书名:{book_name}| 作者:{book_authors}")# 将列表页数据暂存到容器book_ids.append(book_id)names.append(book_name)authors_list.append(book_authors)# ========================================# 详情页爬取:基于ID拼接URL,实现"由浅入深"的数据获取# ========================================detail_url=f'https://spa5.scrape.center/api/book/{book_id}/'try:detail_response=requests.get(detail_url,headers=headers,verify=False,timeout=10)detail_response.raise_for_status()exceptrequests.RequestExceptionase:print(f"详情页请求失败 ID={book_id}:{e}")# 失败时填充空值,保证数据结构完整性,避免后续DataFrame构建时报错urls.append('')themes.append('')continue# 解析详情页JSONdetail_data=detail_response.json()# 提取详情页特有字段book_url=detail_data.get('url','')# 使用.get()提供默认值,防止KeyError# 主题标签同样为列表类型,需做字符串转换与清洗book_theme=str(detail_data.get('tags',[]))\.replace('[','')\.replace(']','')\.replace("'","")\.strip()print(f"[详情页] URL:{book_url}| 主题:{book_theme}")urls.append(book_url)themes.append(book_theme)# 页码递增,准备下一页page+=1# 礼貌爬取:在页与页之间添加短暂延迟,降低服务器负载,避免触发频率限制# 实际生产环境中建议使用 random.uniform(1, 3) 随机延时,模拟人类行为# import time; time.sleep(1)# ========================================# 第四部分:数据整合与持久化# ========================================print(f"\n{'='*50}")print(f"爬取完成!共获取{len(names)}条图书记录")print(f"{'='*50}")# 使用字典构造"列式数据",键为列名,值为列表(DataFrame的标准输入格式)book_dict={"链接":urls,"书名":names,"作者":authors_list,"主题":themes,}# 构建DataFrame:pandas会自动对齐各列长度,进行向量化操作work=pd.DataFrame(book_dict)# 数据持久化:保存为制表符分隔的txt文件# sep='\t' 使用制表符分隔,Excel可直接打开且不会混淆内容中的逗号# index=False 不保存行索引,保持数据整洁# encoding='utf-8' 确保中文不乱码output_file='books_list.txt'work.to_csv(output_file,sep='\t',index=False,encoding='utf-8')print(f"\n数据已保存至:{output_file}")print("预览前5条数据:")print(work.head())

3.2 核心设计思想解析

(1)两级爬取架构

本案例采用了**“列表页→详情页”**的两级爬取策略,这是工业爬虫中最常见的模式之一:

列表页API ── 获取ID列表 ── 循环拼接详情API ── 获取完整数据

优势:

  • 减少单次请求的数据传输量(列表页轻量,详情页丰富)
  • 降低服务器压力,避免一次性返回过多数据导致超时
  • 便于实现断点续传:如果中断,只需记录当前处理到的ID
(2)数据清洗策略

接口返回的authorstags字段均为Python列表类型,直接存储会导致数据格式混乱。我的处理策略是:

# 原始数据:['东野圭吾'] 或 ['刘慈欣', '韩松']# 转换后:"东野圭吾" 或 "刘慈欣, 韩松"

这里使用了防御性编程str()转换 +replace()清洗 +strip()去空白,确保即使接口返回格式微调,代码也能健壮运行。

(3)异常处理机制

代码中在每个网络请求点都设置了try-except块:

  • 列表页失败:直接退出循环,避免无效重试
  • 详情页失败:填充空字符串,保证DataFrame列长度一致,不中断整体流程

这种**“优雅降级”**思想在实际生产中至关重要——爬虫面对的是不可靠的网络环境,必须假设每一步都可能失败。


四、运行效果展示

4.1 控制台输出

程序运行时的控制台输出如下,可以清晰看到两级爬取的流程:

输出特征:

  • 每页请求前有清晰的分隔线与页码提示
  • 列表页与详情页数据分行展示,便于调试时定位问题
  • 实时打印进度,长任务执行时给予用户反馈

4.2 最终数据文件

爬取完成后,生成的books_list.txt文件用Excel打开后效果如下:

文件特点:

  • 制表符分隔,Excel自动识别为表格
  • 中文显示正常(UTF-8编码)
  • 无行索引干扰,数据纯净可直接用于后续分析

五、进阶思考与优化方向

5.1 性能优化:异步并发

当前代码采用同步串行请求,详情页逐个获取效率较低。当数据量达到数千条时,建议使用aiohttp实现异步并发:

importaiohttpimportasyncioasyncdeffetch_detail(session,book_id):url=f'https://spa5.scrape.center/api/book/{book_id}/'asyncwithsession.get(url)asresponse:returnawaitresponse.json()

据测试,异步模式可将爬取效率提升5-10倍,特别适合此类I/O密集型任务。

5.2 反爬对抗策略

虽然本站点为学习用途未设置强反爬,但实际场景中需要考虑:

  • 请求频率控制:使用time.sleep(random.uniform(1, 3))模拟人类操作间隔
  • IP代理池:高频率请求时轮换代理IP
  • 请求头轮换:定期更换User-Agent,甚至模拟完整的浏览器指纹

5.3 数据存储升级

当数据量增大时,txt/CSV文件的管理变得困难,建议升级存储方案:

场景推荐方案优势
结构化数据 < 10万条SQLite轻量级,无需单独部署
大规模数据 + 分析MySQL/PostgreSQL支持复杂查询与索引
非结构化/文档型MongoDB灵活存储JSON原生数据

六、总结

通过本次实战,我们完整掌握了接口型爬虫的核心技术栈:

  1. 接口分析能力:学会使用浏览器开发者工具抓取Ajax请求,分析URL规律与参数含义
  2. JSON解析技巧:理解Python字典/列表的嵌套结构,熟练进行数据提取与清洗
  3. 两级爬取架构:掌握"列表页获取ID → 详情页获取完整数据"的经典模式
  4. 工程化思维:异常处理、数据校验、礼貌爬取等生产级代码习惯

如果本文对你有帮助,欢迎点赞、收藏、关注!有任何问题欢迎在评论区留言讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 3:24:04

LinkedIn高管AI时代生存指南:别卷了,AI时代拼的是做人

AI浪潮席卷&#xff0c;职场人难免焦虑。LinkedIn (领英) 坐拥超过12亿会员的数据&#xff0c;看清了工作重塑的真实轨迹。LinkedIn首席经济机遇官Aneesh Raman惊人言论&#xff1a;AI时代&#xff0c;做个真正的人&#xff0c;别再模仿机器&#xff0c;没人能打败你。AI重塑工…

作者头像 李华
网站建设 2026/5/15 3:22:06

基于Cursor API构建Web端AI编程助手:架构、实现与自动化集成

1. 项目概述&#xff1a;一个为开发者打造的“云端大脑”最近在折腾一个很有意思的开源项目&#xff0c;叫eriknson/cursor-web。如果你是一个重度使用 Cursor 编辑器的开发者&#xff0c;或者对 AI 编程助手的工作流有更高的定制化需求&#xff0c;那么这个项目很可能就是你在…

作者头像 李华
网站建设 2026/5/15 3:21:06

开发者技能图谱工具:从能力矩阵到职业规划的实践指南

1. 项目概述&#xff1a;一个为开发者量身定制的技能图谱如果你是一名开发者&#xff0c;无论是刚入行的新人&#xff0c;还是摸爬滚打多年的老手&#xff0c;可能都曾有过这样的困惑&#xff1a;技术栈日新月异&#xff0c;我该学什么&#xff1f;我的技能树有没有明显的短板&…

作者头像 李华
网站建设 2026/5/15 3:18:25

OpenClaw Ultra Generator技能:让AI分析任务输出专业级报告

1. 项目概述与核心价值最近在折腾AI Agent的开发&#xff0c;特别是基于OpenClaw这个框架&#xff0c;我发现一个痛点&#xff1a;很多分析类任务&#xff0c;比如代码审查、文档摘要、数据洞察&#xff0c;虽然Agent能处理&#xff0c;但输出的结果往往停留在“能用”的层面&a…

作者头像 李华
网站建设 2026/5/15 3:18:19

开源CRM Clawnify:轻量自托管,专为SaaS与AI Agent设计

1. 项目概述&#xff1a;一个为SaaS和AI Agent设计的开源CRM如果你正在为你的SaaS产品寻找一个轻量、可自托管、且能无缝嵌入的客户关系管理&#xff08;CRM&#xff09;模块&#xff0c;或者你厌倦了HubSpot、Salesforce这类重量级SaaS的复杂配置、高昂费用和API限制&#xff…

作者头像 李华