Python爬虫实战:Goodreads书单数据抓取与清洗
1. 项目背景与核心需求最近在整理个人阅读清单时发现Goodreads的Listopia功能提供了大量优质书单资源。但手动记录每本书的书名、作者和评分实在太费时间。作为Python开发者我决定写一个爬虫来自动化这个过程并实现数据清洗和持久化存储。这个爬虫需要解决几个关键问题从Listopia页面准确提取书名和作者信息经常混杂在HTML标签中处理评分数据的各种显示格式星级、文字描述等清洗数据中的异常值和格式不一致问题提供CSV导出和SQLite存储两种持久化方案2. 技术选型与工具准备2.1 核心工具链import requests from bs4 import BeautifulSoup import pandas as pd import sqlite3 import re选择这些库的原因requests比urllib更人性化的HTTP库适合快速开发BeautifulSoupHTML解析的瑞士军刀对标签处理特别友好pandas数据清洗和CSV导出的最佳选择sqlite3Python内置无需额外安装适合小型项目持久化2.2 开发环境配置建议使用虚拟环境避免依赖冲突python -m venv goodreads-scraper source goodreads-scraper/bin/activate # Linux/Mac goodreads-scraper\Scripts\activate # Windows pip install requests beautifulsoup4 pandas3. 页面分析与爬取策略3.1 Goodreads页面结构解析以Best Books of 2022书单为例https://www.goodreads.com/list/show/175269.Best_Books_of_2022关键DOM结构tr itemscope itemtypehttp://schema.org/Book td classnumber1/td td classcover a href/book/show/12345img.../a /td td classmain div classtitle a href/book/show/12345 itempropurl span itempropnameBook Title/span /a by span itempropauthorAuthor Name/span /div div classrating4.12 avg rating/div /td /tr3.2 分页处理逻辑Goodreads使用传统的页码分页base_url https://www.goodreads.com/list/show/175269 for page in range(1, total_pages1): url f{base_url}?page{page} response requests.get(url, headersheaders) # 解析逻辑...注意务必设置合理的请求间隔建议3-5秒避免触发反爬机制4. 核心数据提取实现4.1 书名与作者提取def extract_book_info(book_element): title book_element.find(span, itempropname).text.strip() author book_element.find(span, itempropauthor).text.strip() # 处理作者名中的冗余信息 author re.sub(r,.*$, , author) # 去除,...部分 author re.sub(r\s, , author) # 合并多余空格 return title, author4.2 评分数据解析评分可能以多种形式出现4.12 avg rating → 提取4.12really liked it 4.00 → 提取4.00★★★★☆ → 转换为4.0处理代码def parse_rating(rating_text): # 匹配数字评分 num_match re.search(r(\d\.\d{2}), rating_text) if num_match: return float(num_match.group(1)) # 处理星级评分 star_count rating_text.count(★) half_star 0.5 if ½ in rating_text else 0 return star_count half_star5. 数据清洗与标准化5.1 常见数据问题处理def clean_data(df): # 处理缺失值 df[rating] df[rating].fillna(0) # 统一书名格式 df[title] df[title].str.title() # 作者名标准化 df[author] df[author].apply( lambda x: re.sub(r^(by|and)\s, , x, flagsre.IGNORECASE) ) return df5.2 数据验证添加合理性检查def validate_row(row): if not row[title] or len(row[title]) 2: return False if row[rating] 0 or row[rating] 5: return False return True df df[df.apply(validate_row, axis1)]6. 持久化存储实现6.1 CSV导出def save_to_csv(df, filename): df.to_csv(filename, indexFalse, encodingutf-8-sig) # 添加BOM头解决Excel中文乱码问题 with open(filename, r, encodingutf-8-sig) as f: content f.read() f.seek(0) f.write(\ufeff content)6.2 SQLite存储def save_to_sqlite(df, db_namebooks.db): conn sqlite3.connect(db_name) df.to_sql(books, conn, if_existsreplace, indexFalse) conn.close()优化建议添加索引加速查询使用事务批量插入添加created_at时间戳7. 反爬策略应对7.1 请求头设置headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept-Language: en-US,en;q0.9, Referer: https://www.goodreads.com/, }7.2 代理与重试机制from time import sleep from random import uniform def safe_request(url, max_retries3): for _ in range(max_retries): try: sleep(uniform(1, 3)) # 随机延迟 response requests.get(url, headersheaders, timeout10) if response.status_code 200: return response except Exception as e: print(fRequest failed: {e}) return None8. 完整代码结构# goodreads_scraper.py class GoodreadsScraper: def __init__(self): self.base_url None self.session requests.Session() self.session.headers.update(headers) def scrape_list(self, list_url, pages1): books [] for page in range(1, pages1): url f{list_url}?page{page} response self.safe_request(url) if response: books.extend(self.parse_page(response.text)) return pd.DataFrame(books) def parse_page(self, html): soup BeautifulSoup(html, html.parser) books [] for book in soup.select(tr[itemtypehttp://schema.org/Book]): title, author self.extract_book_info(book) rating self.parse_rating(book.select_one(.rating).text) books.append({title: title, author: author, rating: rating}) return books # 包含之前定义的所有方法...9. 实际应用示例9.1 运行爬虫scraper GoodreadsScraper() df scraper.scrape_list( https://www.goodreads.com/list/show/175269, pages3 ) # 数据清洗 df clean_data(df) # 持久化 save_to_csv(df, best_books_2022.csv) save_to_sqlite(df, books.db)9.2 数据分析示例# 评分最高的10本书 top_books df.sort_values(rating, ascendingFalse).head(10) # 作者作品数量统计 author_counts df[author].value_counts().head(10)10. 常见问题与解决方案10.1 数据提取不完整可能原因页面结构变化 → 更新CSS选择器动态加载内容 → 考虑使用Selenium解决方案# 添加更健壮的选择器 title book.find(span, {itemprop: name}) or book.find(a, {class: bookTitle})10.2 编码问题处理方案response.encoding response.apparent_encoding # 自动检测编码10.3 数据库优化# 创建索引 conn sqlite3.connect(books.db) conn.execute(CREATE INDEX IF NOT EXISTS idx_author ON books(author)) conn.close()11. 项目扩展思路增加图书详情抓取通过图书URL获取更多元数据ISBN、页数等集成到阅读管理系统自动同步到Notion或Readwise可视化分析使用Matplotlib生成阅读趋势图定时任务每周自动更新书单数据这个爬虫项目最实用的部分是它的数据清洗逻辑特别是处理Goodreads上不规则的作者名字格式。在实际使用中我发现正则表达式的精细调整可以显著提高数据质量。比如处理J.K. Rowling, Mary GrandPré (Illustrator)这种情况需要特别设计模式匹配。

相关新闻

Goodreads书单爬虫实战:高效采集与数据清洗技巧

Goodreads书单爬虫实战:高效采集与数据清洗技巧

1. 项目背景与核心需求Goodreads作为全球最大的书评和推荐网站之一,其Listopia功能汇集了大量用户创建的主题书单。这些书单数据对于图书市场分析、读者偏好研究或个人阅读规划都具有重要价值。但网站并未提供结构化数据导出功能,手动收集效率极低。这个…

2026/10/15 15:07:52 阅读更多 →
SSM框架在酒吧管理系统中的实践与优化

SSM框架在酒吧管理系统中的实践与优化

1. 项目概述与核心价值酒吧后台管理系统是典型的餐饮娱乐行业信息化解决方案,采用JavaWeb技术栈实现。这个系统本质上解决的是夜间娱乐场所运营中的三大痛点:人工记录易出错、营业数据不透明、多岗位协作低效。我在2018年参与过某连锁酒吧集团的系统升级…

2026/10/15 15:06:48 阅读更多 →
win-acme v2.1.18-x64:Windows免费证书自动续期与IIS部署指南

win-acme v2.1.18-x64:Windows免费证书自动续期与IIS部署指南

简介:win-acme.v2.1.18-x64 是一款面向 Windows 平台、用于自动化申请与续订 Lets Encrypt 免费 SSL 证书的工具,适合个人站长、小型项目开发者及需要为 IIS 等 Web 服务器配置 HTTPS 的运维人员。它基于 ACME 协议实现证书申请、安装、自动续订与多域名…

2026/10/15 15:06:48 阅读更多 →

最新新闻

PID算法实战指南:从仿真调参到硬件部署避坑

PID算法实战指南:从仿真调参到硬件部署避坑

简介:本资源是一套面向嵌入式开发初学者与单片机工程师的PID控制算法实战代码库,聚焦STM32平台闭环控制场景,解决电机调速、温控系统、姿态稳定等典型应用中控制器设计与移植难题。压缩包共394个文件,以99个C源文件和102个头文件&…

2026/10/15 15:49:04 阅读更多 →
reladraw美化指南:自定义SVG图标、badge徽章与14种主题打造专属图表风格

reladraw美化指南:自定义SVG图标、badge徽章与14种主题打造专属图表风格

开发工具CLIAI 技能 【免费下载链接】reladraw 项目地址: https://gitcode.com/gh_mirrors/re/reladraw 点击查看 免费下载 reladraw 是一款用纯文本描述布局的图表语言:它把 .reladraw 文件渲染成独立 SVG,无需手动拖拽坐标。本文是面向新手…

2026/10/15 15:49:04 阅读更多 →
Southstreet Critical CSS深度解析:内联关键样式消除渲染阻塞,首屏1秒内可用

Southstreet Critical CSS深度解析:内联关键样式消除渲染阻塞,首屏1秒内可用

文档/教程示例工程 【免费下载链接】Southstreet Filament Groups core tools & workflow for delivering rich cross-device web applications 项目地址: https://gitcode.com/gh_mirrors/so/Southstreet 点击查看 免费下载 Southstreet 是 Filament Group 打…

2026/10/15 15:49:04 阅读更多 →
深入auto_reg核心架构:FastAPI+React+APScheduler的任务调度与插件注册表设计

深入auto_reg核心架构:FastAPI+React+APScheduler的任务调度与插件注册表设计

【免费下载链接】auto_reg codex全自动注册机 项目地址: https://gitcode.com/gh_mirrors/au/auto_reg 点击查看 免费下载 auto_reg 是一个多平台账号自动注册与管理系统,其核心架构由 FastAPI 后端、React 前端和插件注册表三大支柱构成。理解 auto_re…

2026/10/15 15:49:04 阅读更多 →
三维点云圆柱拟合:工业级鲁棒优化实战指南

三维点云圆柱拟合:工业级鲁棒优化实战指南

简介:本资源是一套面向计算机视觉与三维重建方向初学者及工程实践者的C圆柱面拟合实现方案,聚焦于从无序三维点云中稳健估计圆柱几何参数——包括半径、轴线单位方向向量及轴线过点(起始位置),适用于工业检测、逆向建模…

2026/10/15 15:49:04 阅读更多 →
MCP接入虚幻引擎实战:协议解析到UE桥接全链路

MCP接入虚幻引擎实战:协议解析到UE桥接全链路

最近 MCP 这个词在 AIGC 圈子里的热度非常高。如果你用过 Claude Desktop、Cursor、Windsurf 这类 AI 工具,大概率听过“MCP Server”“工具调用”这些概念。但一说到“把 MCP 接到虚幻引擎(Unreal Engine)里”,网上的资料就开始各…

2026/10/15 15:48:03 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →