news 2025/12/30 13:52:22

Python 爬虫实战:静态网页爬取全流程演示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 爬虫实战:静态网页爬取全流程演示

前言

静态网页是指内容固定、由服务器直接返回 HTML 源码的网页,其数据直接嵌入在源码中,无需动态加载,是爬虫入门的最佳实践场景。掌握静态网页的爬取流程,能帮助开发者建立完整的爬虫开发思维,为后续处理动态网页、反爬网页奠定基础。本文将以 **豆瓣读书 Top250** 为实战目标,从需求分析、请求发送、数据提取到数据清洗、结果输出,完整演示静态网页爬取的全流程,拆解每个环节的核心技巧与注意事项。

摘要

本文聚焦静态网页爬取的全流程实战,以豆瓣读书 Top250 为爬取目标,系统讲解 “需求分析→请求构造→响应解析→数据提取→数据清洗→结果输出” 六大核心环节,结合 urllib 库、正则表达式、BeautifulSoup 等工具实现静态网页数据的完整爬取。文中包含全流程代码示例、数据提取对比表格、输出结果解析,旨在帮助读者掌握静态网页爬取的标准化流程,理解各环节的核心逻辑与实操技巧。

一、静态网页爬取核心流程梳理

静态网页爬取的核心逻辑遵循 “请求 - 解析 - 提取 - 输出” 的标准化流程,各环节职责明确:

流程环节核心目标常用工具 / 技术关键注意事项
需求分析明确爬取目标、数据字段、输出格式人工分析网页结构确认数据是否在 HTML 源码中(静态特征)
请求构造发送合法请求,获取完整 HTML 源码urllib/requests、请求头构造模拟浏览器请求,避免被反爬拦截
响应解析将字节流响应转为可解析的字符串字符编码处理(utf-8/gbk)匹配网页实际编码,避免乱码
数据提取从 HTML 源码中提取目标数据正则表达式、BeautifulSoup、XPath精准匹配数据所在的标签 / 属性
数据清洗去除冗余数据、格式化字段字符串处理、数据类型转换统一数据格式,提升数据可用性
结果输出将清洗后的数据保存 / 展示控制台输出、TXT/CSV/Excel 保存按需求选择输出格式,便于后续使用

1.1 静态网页特征识别

判断目标网页是否为静态网页的核心方法:

  1. 打开目标网页,按F12进入开发者工具,切换至Elements标签,直接搜索关键数据(如书名、评分),若能在 HTML 源码中找到,即为静态网页;
  2. 切换至Network标签,刷新页面后仅需加载 HTML 文件即可显示完整内容,无额外的 XHR/JSON 请求;
  3. 禁用 JavaScript 后(开发者工具Settings→Debugger→Disable JavaScript),页面内容仍完整显示。

二、实战目标分析:豆瓣读书 Top250

2.1 爬取需求

  • 目标网站:豆瓣读书 Top250
  • 爬取字段:排名、书名、作者、出版社、出版时间、评分、简介
  • 输出格式:控制台结构化输出 + 文本文件保存
  • 爬取范围:豆瓣读书 Top250 第一页数据(演示核心流程)

2.2 网页结构分析

通过浏览器开发者工具分析豆瓣读书 Top250 页面结构:

  • 每本图书的信息包裹在class="item"的 li 标签中;
  • 排名:class="pic"下的 em 标签;
  • 书名:class="pl2"下的 a 标签(title 属性);
  • 作者 / 出版社 / 出版时间:class="pl"的 span 标签;
  • 评分:class="rating_nums"的 span 标签;
  • 简介:class="inq"的 span 标签(部分图书无简介)。

三、全流程代码实现与解析

3.1 环境准备

需安装 BeautifulSoup(用于 HTML 解析):

bash

运行

pip install beautifulsoup4

3.2 完整爬取代码

python

运行

import urllib.request import urllib.error from bs4 import BeautifulSoup import re # ===================== 1. 配置基础参数 ===================== # 目标URL url = "https://book.douban.com/top250" # 请求头(模拟Chrome浏览器) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Referer": "https://book.douban.com/" } # ===================== 2. 发送请求,获取响应 ===================== def get_html(url, headers): """ 发送HTTP请求,获取网页HTML源码 :param url: 目标URL :param headers: 请求头 :return: 解码后的HTML字符串(失败返回None) """ try: # 构造请求对象 request = urllib.request.Request(url=url, headers=headers, method="GET") # 发送请求 response = urllib.request.urlopen(request, timeout=15) # 读取响应字节流,解码为字符串(豆瓣读书编码为utf-8) html = response.read().decode("utf-8") print(f"请求成功,响应状态码:{response.getcode()}") return html except urllib.error.HTTPError as e: print(f"HTTP错误:状态码 {e.code},原因 {e.reason}") return None except urllib.error.URLError as e: print(f"网络错误:{e.reason}") return None except Exception as e: print(f"未知错误:{e}") return None # ===================== 3. 解析HTML,提取数据 ===================== def extract_data(html): """ 解析HTML源码,提取目标数据 :param html: 网页HTML字符串 :return: 提取后的字典列表 """ if not html: return [] # 初始化BeautifulSoup对象(使用lxml解析器,需提前安装:pip install lxml) soup = BeautifulSoup(html, "lxml") # 定位所有图书项 book_items = soup.find_all("li", class_="item") # 存储提取的数据 book_list = [] # 遍历每个图书项,提取字段 for item in book_items: book_info = {} try: # 1. 排名 book_info["排名"] = item.find("em").text.strip() # 2. 书名(优先取title属性,无则取文本) title_tag = item.find("span", class_="title") book_info["书名"] = title_tag.get("title", title_tag.text.strip()) # 3. 作者/出版社/出版时间(统一提取后拆分) pl_tag = item.find("p", class_="pl") pl_text = pl_tag.text.strip() # 拆分规则:作者 / 出版社 / 出版时间 / 定价(部分有定价,需兼容) pl_parts = pl_text.split("/") book_info["作者"] = pl_parts[0].strip() if len(pl_parts) > 0 else "" book_info["出版社"] = pl_parts[-3].strip() if len(pl_parts) >= 3 else "" book_info["出版时间"] = pl_parts[-2].strip() if len(pl_parts) >= 2 else "" # 4. 评分 score_tag = item.find("span", class_="rating_nums") book_info["评分"] = score_tag.text.strip() if score_tag else "无评分" # 5. 简介 inq_tag = item.find("span", class_="inq") book_info["简介"] = inq_tag.text.strip() if inq_tag else "无简介" book_list.append(book_info) except Exception as e: print(f"提取单条图书数据失败:{e}") continue print(f"共提取到 {len(book_list)} 条图书数据") return book_list # ===================== 4. 数据清洗 ===================== def clean_data(book_list): """ 清洗数据,统一格式,去除冗余 :param book_list: 提取后的字典列表 :return: 清洗后的字典列表 """ cleaned_list = [] for book in book_list: cleaned_book = {} # 排名转为整数 cleaned_book["排名"] = int(book["排名"]) if book["排名"].isdigit() else 0 # 书名去除特殊字符 cleaned_book["书名"] = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s]', '', book["书名"]) # 作者/出版社/出版时间去除首尾空格 cleaned_book["作者"] = book["作者"].strip() cleaned_book["出版社"] = book["出版社"].strip() cleaned_book["出版时间"] = book["出版时间"].strip() # 评分转为浮点数 cleaned_book["评分"] = float(book["评分"]) if book["评分"].replace(".", "").isdigit() else 0.0 # 简介去除换行符 cleaned_book["简介"] = book["简介"].replace("\n", "").strip() cleaned_list.append(cleaned_book) return cleaned_list # ===================== 5. 结果输出 ===================== def output_result(book_list): """ 输出结果:控制台结构化输出 + 保存为TXT文件 :param book_list: 清洗后的字典列表 """ if not book_list: print("无数据可输出") return # 1. 控制台输出 print("\n=== 豆瓣读书Top250(第一页) ===") for book in book_list: print(f"排名:{book['排名']} | 书名:{book['书名']}") print(f"作者:{book['作者']} | 出版社:{book['出版社']} | 出版时间:{book['出版时间']}") print(f"评分:{book['评分']} | 简介:{book['简介']}") print("-" * 80) # 2. 保存为TXT文件 with open("豆瓣读书Top250_第一页.txt", "w", encoding="utf-8") as f: f.write("豆瓣读书Top250(第一页)\n") f.write("=" * 80 + "\n") for book in book_list: f.write(f"排名:{book['排名']}\n") f.write(f"书名:{book['书名']}\n") f.write(f"作者:{book['作者']}\n") f.write(f"出版社:{book['出版社']}\n") f.write(f"出版时间:{book['出版时间']}\n") f.write(f"评分:{book['评分']}\n") f.write(f"简介:{book['简介']}\n") f.write("-" * 80 + "\n") print("\n数据已保存至:豆瓣读书Top250_第一页.txt") # ===================== 主函数:整合全流程 ===================== if __name__ == "__main__": # 1. 发送请求,获取HTML html = get_html(url, headers) # 2. 提取数据 raw_data = extract_data(html) # 3. 数据清洗 cleaned_data = clean_data(raw_data) # 4. 结果输出 output_result(cleaned_data)

3.3 输出结果展示

控制台输出(节选)

plaintext

请求成功,响应状态码:200 共提取到 25 条图书数据 === 豆瓣读书Top250(第一页) === 排名:1 | 书名:红楼梦 作者:曹雪芹 高鹗 | 出版社:人民文学出版社 | 出版时间:1996年2月 评分:9.6 | 简介:满纸荒唐言,一把辛酸泪。都云作者痴,谁解其中味? -------------------------------------------------------------------------------- 排名:2 | 书名:活着 作者:余华 | 出版社:作家出版社 | 出版时间:2012年8月 评分:9.3 | 简介:人是为活着本身而活着的,而不是为活着之外的任何事物所活着。 -------------------------------------------------------------------------------- 排名:3 | 书名:百年孤独 作者:加西亚·马尔克斯 范晔 译 | 出版社:南海出版公司 | 出版时间:2011年6月 评分:9.3 | 简介:生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。 -------------------------------------------------------------------------------- ... 数据已保存至:豆瓣读书Top250_第一页.txt
TXT 文件输出(节选)

plaintext

豆瓣读书Top250(第一页) ================================================================================ 排名:1 书名:红楼梦 作者:曹雪芹 高鹗 出版社:人民文学出版社 出版时间:1996年2月 评分:9.6 简介:满纸荒唐言,一把辛酸泪。都云作者痴,谁解其中味? -------------------------------------------------------------------------------- 排名:2 书名:活着 作者:余华 出版社:作家出版社 出版时间:2012年8月 评分:9.3 简介:人是为活着本身而活着的,而不是为活着之外的任何事物所活着。 --------------------------------------------------------------------------------

四、核心环节深度解析

4.1 请求构造:模拟浏览器避免反爬

  • 配置完整的请求头(User-AgentRefererAccept),模拟 Chrome 浏览器请求,避开豆瓣的基础反爬机制;
  • 设置超时时间(timeout=15),避免请求长时间阻塞;
  • 异常捕获覆盖 HTTP 错误、网络错误、未知错误,确保程序稳定性。

4.2 数据提取:BeautifulSoup vs 正则表达式

静态网页数据提取有两种核心方式,各有优劣:

提取方式实现示例优势劣势
BeautifulSoup(标签定位)item.find("span", class_="rating_nums").text代码可读性高,适配 HTML 结构变化,无需写复杂正则解析速度略慢,依赖标签 /class 属性
正则表达式(文本匹配)re.findall(r'<span class="rating_nums">(.*?)</span>', html)解析速度快,可匹配无固定标签的数据代码可读性差,HTML 结构变化易失效

实战建议:静态网页优先使用 BeautifulSoup,仅当标签结构极不稳定时使用正则表达式。

4.3 数据清洗:提升数据可用性

  • 类型转换:将排名(字符串)转为整数,评分(字符串)转为浮点数,便于后续排序 / 计算;
  • 字符过滤:使用正则表达式去除书名中的特殊字符,避免乱码 / 冗余;
  • 空值兼容:对无简介、无评分的字段设置默认值,避免程序报错;
  • 空格清理:去除字段首尾空格,统一数据格式。

4.4 结果输出:多格式适配需求

  • 控制台输出:结构化展示数据,便于调试和快速查看;
  • TXT 文件保存:持久化存储数据,便于后续查看和使用;
  • 拓展方向:可通过csv库保存为 CSV 文件,或通过openpyxl保存为 Excel 文件,适配数据分析场景。

五、常见问题与解决方案

问题现象原因分析解决方案
提取数据为空1. HTML 解析器错误(如未安装 lxml);2. 标签 /class 属性拼写错误1. 安装 lxml 解析器(pip install lxml);2. 核对浏览器中标签的 class 属性(注意空格 / 大小写)
数据乱码响应解码编码与网页实际编码不一致1. 查看网页Content-Type响应头确认编码;2. 尝试gbk/gb2312等编码(如中文网页)
部分数据提取失败个别图书的 HTML 结构不一致(如无简介)在提取时增加异常捕获,为缺失字段设置默认值
保存文件时编码错误未指定文件编码为 utf-8打开文件时指定encoding="utf-8"

六、拓展优化:爬取多页数据

静态网页爬取的进阶需求是多页数据爬取,以豆瓣读书 Top250 为例,其分页 URL 规律为:

  • 第一页:https://book.douban.com/top250
  • 第二页:https://book.douban.com/top250?start=25
  • 第三页:https://book.douban.com/top250?start=50
  • 分页规则:start参数为(页码 - 1)*25

多页爬取核心代码(整合到主函数)

python

运行

# 多页爬取:爬取前3页 if __name__ == "__main__": all_book_data = [] # 遍历前3页 for page in range(3): start = page * 25 # 构造分页URL page_url = f"https://book.douban.com/top250?start={start}" if start > 0 else "https://book.douban.com/top250" print(f"\n===== 爬取第 {page+1} 页:{page_url} =====") # 1. 获取HTML html = get_html(page_url, headers) # 2. 提取数据 raw_data = extract_data(html) # 3. 数据清洗 cleaned_data = clean_data(raw_data) # 4. 合并数据 all_book_data.extend(cleaned_data) # 增加请求间隔,避免反爬 import time time.sleep(1) # 输出所有数据 output_result(all_book_data)

七、总结

静态网页爬取是爬虫开发的基础,其核心流程 “请求 - 解析 - 提取 - 清洗 - 输出” 适用于所有爬虫场景。本文以豆瓣读书 Top250 为实战案例,完整演示了静态网页爬取的全流程,重点讲解了请求构造的反爬技巧、BeautifulSoup 的数据提取方法、数据清洗的标准化操作以及结果输出的多格式适配。

在实际开发中,需注意以下核心要点:

  1. 模拟浏览器请求,避免被基础反爬机制拦截;
  2. 优先使用结构化解析工具(如 BeautifulSoup),提升代码可维护性;
  3. 数据清洗是提升数据可用性的关键,需处理空值、格式、类型等问题;
  4. 多页爬取时需遵循网站分页规则,增加请求间隔,避免请求频率过高。

掌握静态网页爬取的全流程,能帮助开发者建立标准化的爬虫开发思维,为后续处理动态网页(如 AJAX 加载、JavaScript 渲染)、复杂反爬网页奠定坚实基础。

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

揭秘Q#量子程序开发痛点:如何在VSCode中自动生成高质量文档?

第一章&#xff1a;揭秘Q#量子程序开发痛点&#xff1a;从现状到挑战 量子计算正逐步从理论研究走向工程实践&#xff0c;而Q#作为微软推出的专用量子编程语言&#xff0c;旨在为开发者提供构建量子算法的高级抽象能力。然而&#xff0c;在实际开发过程中&#xff0c;Q#的应用仍…

作者头像 李华
网站建设 2025/12/26 2:27:23

Python 爬虫实战:批量爬取网页的基础实现

前言 在爬虫应用场景中&#xff0c;单页面爬取仅能满足简单的数据采集需求&#xff0c;而批量爬取多页面、多目标网址的数据才是解决实际业务问题的核心能力。批量爬取的核心挑战在于如何高效管理待爬取 URL 队列、控制爬取节奏、避免重复爬取&#xff0c;并保证大规模数据采集…

作者头像 李华
网站建设 2025/12/27 0:05:39

Python 爬虫实战:使用 chardet 解决网页编码问题

前言 在 Python 爬虫开发过程中&#xff0c;网页编码问题是高频出现的基础痛点 —— 不同网站采用的字符编码&#xff08;如 UTF-8、GB2312、GBK、ISO-8859-1 等&#xff09;差异&#xff0c;极易导致爬取的网页内容出现乱码、字符缺失、解析失败等问题。chardet 作为 Python …

作者头像 李华
网站建设 2025/12/26 15:14:11

Git项目管理利器:一站式.gitattributes模板集合

Git项目管理利器&#xff1a;一站式.gitattributes模板集合 【免费下载链接】gitattributes 项目地址: https://gitcode.com/gh_mirrors/gita/gitattributes 还在为跨平台开发时的文件格式问题头疼吗&#xff1f;想要告别烦人的换行符冲突和二进制文件误识别&#xff1…

作者头像 李华
网站建设 2025/12/26 18:24:11

Python 爬虫实战:爬虫请求超时设置与重试机制

前言 在爬虫开发中&#xff0c;网络环境的不稳定性&#xff08;如延迟、断连&#xff09;、目标服务器的限流策略、反爬机制触发等问题&#xff0c;极易导致请求超时或失败。若缺乏有效的超时控制和重试机制&#xff0c;爬虫程序可能陷入无限等待、频繁崩溃&#xff0c;甚至被…

作者头像 李华
网站建设 2025/12/26 15:13:07

【顶尖量子开发者都在用】:VSCode Jupyter缓存配置的7个黄金规则

第一章&#xff1a;VSCode Jupyter 的量子模拟缓存在进行量子计算研究与开发时&#xff0c;VSCode 集成 Jupyter Notebook 提供了高效且直观的交互环境。当运行复杂的量子模拟任务时&#xff0c;中间结果的重复计算会显著降低开发效率。利用 VSCode 中 Jupyter 的缓存机制&…

作者头像 李华