尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python爬虫源码包实战:从请求到数据清洗的全流程解析
简介这份源码包面向已具备一定Python基础、希望深入掌握网络爬虫实战的开发者取材于《用Python写爬虫》一书覆盖静态网页解析、动态渲染抓取、表单交互、图片识别与爬虫框架等场景涉及BeautifulSoup、lxml、Selenium、mechanize、Pillow、pytesseract、Scrapy等常用第三方库的调用方法是一份相当完整的进阶参考。包内共163个文件其中53个py脚本构成学习主线索101张png截图用于核对运行效果另含json、csv、cfg、md等配置与说明文件整包约3.54MB目录按功能划分方便对照原书逐章实践。目前已有490人学习使用。通过阅读示例和配套截图读者可以弄清楚不同库在不同场景下的选择与配合也能直接在本地运行调试避免从零搭建环境。对于课程作业、个人项目或是工作需求这套源码都能提供可复用的代码范式尤其适合作为系统学习爬虫技术的参考。1. 用 Python 写爬虫一份源码包能帮你省掉多少事用 Python 写爬虫最容易卡住的不是语法而是拿到一份网页源码后不知道下一步该做什么。这个项目是一份完整的爬虫源码包把请求、解析、清洗、导出这几段串成了一条能直接跑通的链路。不需要从零搭工程解压后改一下目标地址和字段就能看到数据落盘。适合两类人刚学完 Python 基础、想用真实网站练手的初学者或者平时需要做小规模数据采集、又不想每次重复写模板的从业者。源码包不解决所有反爬难题但能让你照着一个可靠模板快速起步避开多数新手都会踩的坑。2. 跑通前的准备项目结构、依赖安装与工具选型2.1 源码包结构先看文件再动手收到源码包之后我习惯先看目录而不是直接双击运行。这份资源解压后会看到一个典型的爬虫项目骨架核心文件大致是这几个. |-- main.py # 入口脚本串起整个抓取流程 |-- spider/ | |-- crawler.py # 请求与下载模块封装 requests 调用 | |-- parser.py # 页面解析模块封装 BeautifulSoup 操作 | |-- cleaner.py # 数据清洗模块处理空白字符和格式 | |-- exporter.py # 数据导出模块落盘为 CSV 或 JSON | -- config.py # 配置文件放请求头、目标 URL、字段映射 |-- requirements.txt # 依赖清单 |-- README.md # 使用说明 | |-- sample_data.csv # 抓取后的样例输出先读 README再打开 config.py 看配置区。config.py 里通常已经把请求头、基础 URL、下一页链接规则单独做成变量这意味着抓取目标更换时只需要改这个文件不需要动主逻辑。这个分层方式值得保留写爬虫最怕把请求、解析、导出全揉在一个脚本里改一处就要牵动全局拆成模块之后排查问题快很多。几个文件里最该细读的是 parser.py 和 cleaner.py它们决定了抓下来的数据能不能直接用。如果 README 里写了 Python 版本要求务必照做版本不一致常常导致依赖装不上或者语法报错。2.2 环境准备依赖安装与验证安装依赖是这个项目里最简单的步骤。在项目根目录执行cd python-spider-source python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install -r requirements.txt依赖清单里通常包含 requests、beautifulsoup4、lxml 这三个基础项。如果还涉及表格数据处理可能会多一个 pandas但核心抓取链路很少依赖它。用虚拟环境是值得养成的习惯爬虫用到的库版本迭代快直接装在全局环境里某天另一个项目需要旧版 requests就会出现依赖打架。装完之后跑一条命令验证python -c import requests, bs4; print(requests.__version__, bs4.__version__)能正常输出版本号说明环境就绪。如果 lxml 安装失败换成纯 Python 的 html.parser 解析器也能跑代价是解析速度会慢一些。源码包里如果默认用了 lxml而你是 Windows 环境且 pip 装不上常见做法是装 wheel 包或者直接用 conda 管理环境不必在源码包里硬改。2.3 为什么选 requests BeautifulSoup选型边界要清楚源码包选用 requests BeautifulSoup 的组合是有理由的。requests 是目前 Python 里最顺手的 HTTP 客户端相比内置 urllib它的连接池、请求头管理、cookie 自动处理都更省心。BeautifulSoup 则专攻 HTML 解析容错能力很强即使面对不规范的页面结构也能把节点提取出来。相比之下Scrapy 功能更重适合大规模采集、需要分布式调度、自带去重和中间件管理但学习曲线陡峭一个简单的单页抓取用 Scrapy 属于杀鸡用牛刀。Selenium 则用来对付动态渲染的页面代价是慢而且需要额外维护一个浏览器驱动。这份源码包把边界定在了 requests BeautifulSoup 这一层意味着它默认目标是静态页面的数据采集。我用这个模板跑过多个信息展示类的网站只要目标内容直接嵌在 HTML 里这套组合基本没有对手。遇到数据藏在接口里或者页面靠 JS 渲染的源码包也留了后路在进阶部分会讲到怎么处理。先记住一个原则解析层选 BeautifulSoup 能搞定就不用上正则能上正则就不用上无头浏览器资源开销和复杂度是逐级上升的。3. 请求层实战headers、超时和重试参数的设置3.1 headers 里的关键参数User-Agent、Referer、Accept-Language请求层的质量直接决定了抓取成功率。源码包里 crawler.py 的初始状态应该长这样import requests def build_session(): session requests.Session() session.headers.update({ 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-Language: zh-CN,zh;q0.9,en;q0.8, Referer: https://example.com/, Connection: keep-alive, }) return session三个参数各有讲究。User-Agent 告诉服务器你是什么客户端缺了它很多网站直接给 403。这个字段最好复制真实浏览器的完整 UA而不是只写一个短字符串。Referer 表示你从哪个页面跳过来的有些网站会校验它比如列表页详情页之间的跳转关系不对详情页会拒答。Accept-Language 声明你接受的语言抓中文内容网站时这个字段缺失会导致部分反爬规则直接判定为非浏览器行为。如果想要更灵活可以把 UA 做成列表轮流切换import random USER_AGENTS [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/120.0.0.0, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Safari/537.36, ] def get_random_ua(): return random.choice(USER_AGENTS)把随机 UA 塞进 session.headers可以降低被识别为同一客户端反复请求的概率。不过注意默认情况下列表页和详情页的 Referer 会不一样如果遇到 403 错误先检查是不是 Referer 没对齐目标站的跳转来源。3.2 超时和重试请求不稳时的保命设置新手最容易犯的错是不设置 timeout。服务器响应慢时requests 会一直等表现就是脚本卡死不动你以为它挂了其实它还在等一个永远不会来的响应。源码包里 crawler.py 的请求函数应该这样写def fetch(session, url, timeout10, retries3): for attempt in range(retries): try: resp session.get(url, timeouttimeout) resp.raise_for_status() return resp.text except (requests.Timeout, requests.ConnectionError, requests.HTTPError) as exc: if attempt retries - 1: raise exc time.sleep(2 * (attempt 1))timeout 可以传一个数字也可以传个双值元组(connect_timeout, read_timeout)分别限制建连和读数据的等待时间。比如timeout(3.05, 10)前一个是连接超时后一个是读取超时。如果拿不准使用一个统一的 10 秒即可。重试机制的核心是退避策略。连续失败时立刻重试还容易加剧对方服务器的压力等 2 秒、4 秒逐次增加效果比固定间隔好。这里额外注意raise_for_status() 会在返回 4xx 或 5xx 时抛出异常但 403 这种错误往往不是网络问题重试也解决不了需要回头检查 headers 配置而不是盲目增加重试次数。Session 保持的原理是自动保存 cookie。同一个 Session 实例发出的请求会携带前一次响应里设置的 Cookie这对需要登录才能浏览的站点特别关键。你可以先用 requests.post 提交登录表单再用同一个 Session 去抓取需要身份认证的页面cookie 的管理全部交给 requests 内部处理。4. 解析与清洗从 HTML 中提取结构化字段4.1 BeautifulSoup 选择器find、find_all 与 select 的取舍页面下载到本地只是第一步真正决定产出质量的是解析逻辑。源码包的 parser.py 里BeautifulSoup 的典型用法是from bs4 import BeautifulSoup def parse_list_page(html): soup BeautifulSoup(html, lxml) items [] for node in soup.select(div.list-item): title node.select_one(h2 a).get_text(stripTrue) link node.select_one(h2 a)[href] price node.select_one(span.price).get_text(stripTrue) items.append({title: title, link: link, price: price}) return items这里的 select 用的是 CSS 选择器语法div.list-item表示选中所有 class 为 list-item 的 div 元素。select_one 表示只取第一个匹配项适合页面结构固定、每条数据唯一的情况。如果同一个页面里有多个相同结构的数据块就用 select 拿到列表再循环。关于解析器选型lxml 是 C 语言实现解析速度快html.parser 是纯 Python慢一些但不用额外装库。抓数据量不大的场景两者差别不大数据量大的时候再换 lxml。要重点说明的是 get_text(stripTrue) 这个参数它会自动去掉标签内部首尾的空白字符但不会去掉多个连续空格。如果你想要的标题里有多个空格被压缩成一个需要在数据清洗步骤再做处理。处理动态加载的数据时如果 BeautifulSoup 拿不到内容先打印 response.text 确认数据是否真的在 HTML 里。如果只在浏览器的开发者工具里能看到那就是 JS 渲染的结果需要用进阶章节的接口分析法解决。4.2 正则表达式作为补充什么时候该用它源码包里正则主要用于两类情况一类是数据藏在 script 标签里的 JSON 字符串中另一类是页面结构极不规范、BeautifulSoup 解析起来反而费劲时。比如从一段 JS 变量里取数据import re import json def extract_from_script(html): match re.search(rwindow\.__INITIAL_STATE__\s*\s*(\{.*?\});, html, re.S) if match: data json.loads(match.group(1)) return data.get(list, []) return []这段正则的意思是匹配window.__INITIAL_STATE__ 后面的 JSON 对象直到第一个分号为止。re.S 标志让点号可以匹配换行符避免 JSON 跨行时匹配失败。非贪婪模式.*?保证只匹配到第一个分号而不是最后一个。正则的适用边界要控制好。抓取数据结构规整时优先用 BeautifulSoup因为 CSS 选择器直观且不容易写错。正则适合处理文本内部的模式比如邮箱地址、手机号、连续数字编码这些用 bs4 反而不顺手。项目源码里 cleaner.py 通常会包含一组常用正则比如去除 HTML 标签、匹配日期格式可以直接照着扩展。4.3 数据清洗去空白、去重、类型转换抓下来的原始字段基本都带着回车、制表符和前后空格不做清洗就直接入库后面查询统计阶段全是坑。cleaner.py 里常见的一套处理流程是def clean_text(raw): return re.sub(r\s, , raw).strip() def clean_price(raw): digits re.sub(r[^\d.], , raw) return float(digits) if digits else 0.0 def normalize_date(raw): date_part re.search(r(\d{4}-\d{2}-\d{2}), raw) return date_part.group(1) if date_part else Noneclean_text 把连续的空白字符包括换行、缩进统一压缩成一个空格再去掉首尾空格。clean_price 把 1,299.00 这种字符串变成 1299.00再转成浮点数注意这里去掉了逗号分隔符否则 float 转换会直接报错。normalize_date 从混杂文本里提取标准的 yyyy-MM-dd 日期不匹配时返回 None保证后续写入 CSV 不会因为格式不统一而出错。清洗逻辑要独立成函数而不是写在解析循环里原因是清洗规则通常要反复调试。封装成一个纯函数后单测和复用都很方便这也正是源码包分层设计的价值所在。5. 常见问题排查五个典型的爬虫失败现场5.1 打印出来全是乱码编码没对齐现象response.text 输出之后中文变成了一堆Ã¥Â之类的乱码。原因服务器返回的响应头里 Content-Type 没写 charset或者写错了requests 默认按 ISO-8859-1 解码中文当然崩。解决在请求时指定编码或者直接根据响应内容反推resp.encoding resp.apparent_encodingapparent_encoding 是从响应内容里探测字符编码靠谱程度比较高。也可以自己指定resp.encoding utf-8前提是你清楚目标站的编码。亲手踩过的坑某网站页面声明是 UTF-8实际返回的是 GBK最终的判断准则以实际字节为准不要无脑相信声明。5.2 请求成功但解析结果为空页面结构和你的选择器不匹配现象response.status_code 是 200response.text 里也能看到目标数据但 select 出来的列表是空的。原因目标节点的 class 名是动态生成的可能带着纯数字后缀形如list-item-163987你照着浏览器里的固定 class 写选择器下一次加载就变了或者是页面里有多处同名 class实际数据在另一层。解决先用soup.prettify()或直接用文本编辑器打开抓下来的 HTML确认真实的 class 名称。或者改用更稳定的父节点定位比如用div[class^list-item]匹配以 list-item 开头的类名。遇到 JS 动态渲染时还要检查 HTML 里数据是否真的存在。5.3 被服务器封禁请求频率过快导致 403 或 429现象脚本跑前几十条正常突然连续报 403 或 429 Too Many Requests。原因请求频率超过了目标站的限流阈值IP 被临时标记。解决在两次请求之间加 sleep请求量大的时候可以把间隔从单值改成随机区间import random, time time.sleep(random.uniform(1, 3))随机间隔比固定间隔更接近真人操作节奏。同时把重试逻辑里的退避时间也加大比如首次失败后等 5 秒再失败等 30 秒。这里提醒一句别去碰代理池那类黑匣子免费代理不如不加质量差还会拉低成功率控制频率才是正道。5.4 正则取不到内容转义符号被吞了现象正则表达式在在线测试工具里能匹配到数据放到 Python 脚本里却返回 None。原因正则字符串里的反斜杠被 Python 解释器转义了比如\d在字符串里变成d。解决用原始字符串 r 声明正则。养成习惯写正则一律用r...可以避开大多数转义问题。另一个坑是 re.match 只从字符串开头匹配如果你要找的内容在中间换用 re.search。5.5 CSV 文件打开后中文乱码或字段错位现象生成的 CSV 用 Excel 打开后中文全部乱码或者一行数据被撑到多个单元格。原因CSV 默认以 ASCII 编码保存中文写入时出问题。解决在导出时指定编码和换行符with open(output.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([标题, 链接, 价格])utf-8-sig 会写入 BOM 头Excel 才认得。newline 是为了防止写入时出现多余空行。如果发现字段错位检查原始数据里是否包含分隔符比如标题里带逗号清洗时可以替换掉这些特殊字符。6. 进阶从跑通到可靠的三个改造技巧6.1 数据落地为 CSV 与 JSON源码包的 exporter.py 提供了基础导出能力但实际使用时有几个细节值得补丁升级。写入 CSV 时按字段映射写别用字典顺序直接写因为 Python 3.8 以下字典顺序和插入顺序一致性要碰运气JSON 导出时设置 ensure_asciiFalse否则中文会变成 \uXXXX 转义序列肉眼没法看。import json def export_json(items, filename): with open(filename, w, encodingutf-8) as f: json.dump(items, f, ensure_asciiFalse, indent2)indent2 让输出文件可读性好调排查数据问题也方便。6.2 验证抓取结果是否完整有效的验证手段是字段长度统计和抽样人工比对。抓完一批数据后我会先检查 CSV 中各字段的缺失率再随机挑 5 条数据和网页手动核对。缺失率突然升高往往意味着页面改版或者选择器失效这时候去查清洗函数里对应字段的清理规则而不是盲目调请求频率。6.3 增量采集与去重控制爬虫跑久了重复抓取是个大问题。常见的做法是维护一个 URL 或内容摘要的集合在写入前判断是否已经处理过。用 SHA-1 对标题和链接生成指纹指纹不在集合里才写入同时把指纹追加到集合中控制增量。从那以后我每次写完爬虫都强制走一遍全流程先用单页验证选择器和清洗函数再小批量试跑最后调频率和重试参数。这个顺序能省掉大量反复排查的时间。如果你也正卡在某个抓取环节这份源码包至少能提供一个可靠的起点希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

一个汉字三种编码:UTF-8、GBK、UTF-16 逐字节对比实测

一个汉字三种编码:UTF-8、GBK、UTF-16 逐字节对比实测

「汉」在 UTF-8 里是 E6 B1 89,在 GBK 里是 BA BA,在 UTF-16LE 里是 49 6C。 同一个字,三种编码,分别是 3 字节、2 字节、2 字节。 我把这三个数字摊在同一张表里对了一遍,谁多一个字节、谁换了字节序,一眼…

📅 2026/10/14 19:40:27
重组蛋白与传统蛋白的区别:从来源到特性的全面解析

重组蛋白与传统蛋白的区别:从来源到特性的全面解析

在生命科学研究中,蛋白质作为重要的实验试剂,其获取方式和特性直接影响研究结果。传统蛋白与重组蛋白在多个维度存在显著差异,本文将系统解析二者的区别。一、定义与来源的本质差异传统蛋白通常指从生物体组织、器官或体液中直接提取的天然蛋…

📅 2026/10/14 19:40:27
又一编程顶级编程CLI开源,实测Step Code开发像素游戏并一键上线

又一编程顶级编程CLI开源,实测Step Code开发像素游戏并一键上线

这两天在Github上看到一个新的harness,阶跃星辰开发的的Step Code,这是继ZCode、DeepSeek harness、MiniMax Code之后又一开源编程Agent,开发者们有好工具可以用了,阶跃上个月刚发布新旗舰模型Step 5 Preview,现在配套…

📅 2026/10/14 19:40:27
MORE NEWS

更多资讯

📰

C/C++数据范围全解析:整型溢出、浮点精度与跨平台陷阱

1. 为什么数据范围是C/C程序员绕不开的基本功刚入行那会儿,我对变量数据范围这件事完全不上心,觉得无非就是int装整数、float装小数,够用就行。直到有一次做一个传感器数据采集的小工具,采集回来的原始值一直不对,排查…

📰

DirectX 11键鼠输入处理:Win32消息机制与渲染循环协作实战

1. 从消息循环到输入处理:为什么键鼠输入值得单独拎出来讲 很多人学DirectX 11,画三角形、贴纹理、写光照都挺顺,一到"用键盘控制相机移动"就卡壳。问题往往不在图形API本身,而在于没搞清楚Win32的消息机制和DX11渲染循…

📰

社交媒体海量行为数据如何用Hadoop体系完成存储、治理与离线计算

做社交媒体方向的数据开发这些年,有一个感受越来越深:很多团队一开始根本不知道自己该上什么技术栈,一听到“海量数据”就喊着要上实时计算,结果离线报表还没跑利索,集群先被跑崩了。Hadoop在社交媒体的应用&#xff0…

📰

无标题内容创作工作流:从空白选题到高效成稿的完整实操指南

“无标题”这三个字,在创作者眼里往往意味着两种极端:要么是灵感枯竭时的一片空白,要么是项目初期故意不设限、让内容自己长出头绪的留白。我做了这么多年内容,接到过不少真的就叫“无标题”的草稿、文件夹甚至需求文档。说实话&a…

📰

数电票时代发票管理工具选型指南:从全票种识别到合规归档

1. 为什么财务人都在重新审视发票管理工具总有朋友问我,你们财务人整天说发票发票,不就是开票、收票、验真、入账这几件事吗?怎么就值得专门花时间研究工具了?我通常的回答是:如果你还在用Excel台账管发票、手动登录税…

📰

nginx离线安装实战:rpm依赖打包与本地yum源配置指南

简介:面向离线或内网环境下的 Linux 服务器运维人员,这套资源将 nginx 离线安装过程中所需的编译器依赖包与 nginx 自身依赖集合整合为一体,解决无网络时无法用常见包管理器安装的痛点。压缩包共 4 个文件,以三个 gz 格式的依赖归…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬