Python爬虫源码包拆解:从解压到改造的完整实战指南
2026/9/7 5:17:39 网站建设 项目流程

简介:面向需要系统掌握Python爬虫的开发者,这份源码源自《Web Scraping with Python》一书的全部示例代码,既有基础静态页面的解析(BeautifulSoup、lxml),也包含动态渲染抓取(Selenium、PyQt、ghost)、表单与登录模拟(mechanize)、图片验证码识别(PIL、pytesseract)、MongoDB数据存储(pymongo)以及Scrapy框架工程化等章节内容,按书籍章节清晰组织,适合边学边查。压缩包内共163个文件,以53个Python脚本为主体,101张PNG图片用于展示运行结果与页面截图,另有JSON、CSV、cfg等文件提供配置和样例数据,包体仅3.54MB,非常轻量。目前已有489人浏览学习,是入门爬虫时颇具参考价值的可运行代码集。依赖清单在README中列明,安装指定库后即可复现书中案例;由于网站和依赖库会更新,作者还提供了Bug反馈入口,便于使用者提交问题并获取后续修复,让整套代码保持可用性。 最近在网盘里翻到一个很有意思的压缩包,文件名就叫“用Python写爬虫-源码.rar”。不用解压我都大概猜得到里面是什么——一个或者几个爬虫脚本、一个 requirements.txt、说不定还有一份写得比较随意的 README。这类资源满天飞,但真正能用自己的手把它们跑起来、改成自己需要的样子的人,其实不多。所以这篇就借着这个“源码包”的话题,把从解压到改造的全过程掰开揉碎讲一遍。不管你是刚接触Python爬虫、想找个现成例子练手,还是手头有一个爬虫需求但不知道从哪下手,这篇都能给你一套可以直接照做的思路和脚本。

爬虫这件事,说到底就是模拟浏览器去访问网页、把返回的数据拿回来、再从里面挑出有用的部分存下来。看着简单,但里面有大量细节:请求头怎么伪装、登录态怎么维持、翻页怎么处理、数据是藏在HTML里还是藏在接口返回的JSON里、频率太高被限制怎么办。这些光看教程记不住,踩过坑才记得牢。我结合这个源码包常见的结构,把整个爬虫项目的核心流程、关键代码、排查技巧都过一遍,尽量让每个环节你都能直接对着自己的项目用。

1. 源码包的整体设计与思路拆解

1.1 一个标准的爬虫源码包里面应该有什么

说实话,网上流传的“Python爬虫源码.rar”质量参差不齐,有的确实整理得清爽,有的就是随手一个脚本加一个data文件夹。我按最常见、最有参考价值的“可用型”源码包来拆解,它的目录结构一般长这样:

spider_project/ ├── requirements.txt # 依赖清单 ├── config.py # 配置:URL、请求头、延迟时间等 ├── spider.py # 主爬虫逻辑:请求 + 解析 ├── parser.py # 数据提取与清洗 ├── storage.py # 存储层:CSV / Excel / 数据库 ├── main.py # 入口:调度流程 ├── logs/ # 运行日志 └── data/ # 抓取结果

这个分包结构不是随便拍的。把配置、请求、解析、存储分开,最大的好处是改一个环节不影响其他环节。比如目标网站改了HTML结构,你只需要动parser.py,不用担心请求逻辑被误伤;想从单线程改成多线程,也只动main.py。等你以后写更大的项目,会发现这种“高内聚、低耦合”的思路是通用的。

1.2 爬虫核心流程:四个环节缺一不可

从源码包的代码逻辑来看,爬虫最核心的流程逃不出四步:构造请求、发送请求、解析响应、存储落地。这四步对应的模块就是上面目录里的spider.py、parser.py、storage.py。看起来简单,但每个环节都有讲究。

构造请求这一步,最容易被新手忽略的就是请求头(Headers)。服务器不关心你是谁,但它关心“你是不是一个真人浏览器”。浏览器访问网页时会带上User-Agent、Referer、Cookie等信息,如果你的代码里没有这些,服务器一眼就看出来你是爬虫——返回的可能是一个让你去“安全验证”的页面,而不是你想要的真实数据。所以在源码里你会经常看到类似:

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,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", }

发送请求大多数时候用requests库就够了,它是Python生态里最常用的HTTP库,接口简单、文档全。代码一般长这样:

import requests def fetch_page(url): resp = requests.get(url, headers=headers, timeout=10) resp.encoding = resp.apparent_encoding return resp.text

这里有两个细节特别值得说。一是timeout必须设置,不设置的话,遇到一个卡住的请求,你的程序可能等好几分钟才报错,多线程场景下更是灾难。二是resp.encoding这行,很多新手会漏掉,导致中文全部变成乱码,这是requests库的编码判断机制和网页实际编码不一致导致的,后面排查问题部分我会详细讲。

解析响应是个分水岭——数据是HTML还是JSON,决定了你用什么方式提取。现在的网站主要有两种架构:

  • 传统服务端渲染:数据直接嵌在HTML里,需要从HTML标签中提取。
  • 前后端分离:HTML是个空壳,真实数据在接口返回的JSON里。

对应到解析手段,前者用正则、XPath或BeautifulSoup都行,后者最简单粗暴的方法是直接用resp.json()拿到Python字典,再层层取key。源码包里如果目标站点是后者,解析代码会明显短很多,这也是一种判断“这个爬虫是不是过时了”的信号——网站改版后,原先能抓的HTML节点可能已经不存在了。

1.3 为什么推荐用这种“方案组合”而不是直接看结果

很多拿到源码包的人第一反应是直接跑,跑通了就觉得完事。但源码的真正价值不在“跑通”,而在于“看懂之后改造成自己的东西”。所以我在下面几个章节里,不单独讲某一个网站的爬虫,而是把通用技术点拆开讲。你手里的源码可能是抓新闻的、抓商品的、抓评论的——没关系,所有爬虫的地基都是这一套逻辑:分析目标、构造请求、解析数据、处理反爬。地基打牢了,换什么目标都只是换一层皮。

2. 核心细节解析与实操要点

2.1 requests请求库:你真的会用这几个参数吗

requests库是爬虫入门第一个要掌握的库,但很多人的用法还停留在“requests.get(url)”这个程度。实际项目中,这几个参数是高频使用的:

  • headers:模拟浏览器身份,能解决一部分反爬检测。注意User-Agent不要老是用同一个,可以准备几个随机切换,很多源码包里会写一个random_user_agent()函数,原因就在这里。
  • params:GET请求的查询参数,不需要自己拼URL。比如你要访问https://example.com/list?page=2&size=20,用params传参更清晰,也方便动态改变参数。
  • cookies:维持登录态,爬取需要登录的数据时用。源码里如果看到从浏览器F12复制Cookie填到代码里的操作,那叫“硬编码Cookie”,缺点是会过期,更高级的做法是用requests.Session()配合登录接口自动获取Cookie。
  • proxies:代理IP,频率高了容易被封IP时用。这属于进阶内容,后面讲反爬的时候我再细说。
  • verify:HTTPS证书验证,个别网站证书有问题时设置为False可绕过,但同时会有一个warning,用urllib3.disable_warnings()去掉。

代码示例:

import requests session = requests.Session() session.headers.update({ "User-Agent": "Mozilla/5.0 ...", }) params = {"page": 1, "size": 20} resp = session.get("https://example.com/api/list", params=params, timeout=5) if resp.status_code == 200: data = resp.json() else: print(f"请求失败,状态码:{resp.status_code}")

这里用Session而不是裸调get,是个很关键的小习惯。Session会帮你自动保存服务端返回的Cookie,下一次请求自动带上,这对某些需要先访问页面拿Cookie再请求接口的网站特别有用。

2.2 数据解析三件套:正则、XPath、BeautifulSoup怎么选

拿到网页源码之后,提取数据的方案大体有三类,源码包里大概率三选一或者混着用。

正则表达式(re)是最万能但最不易维护的。爬虫里最常见的是用它提取JSON字符串、URL、邮箱、手机号这种有明确格式的文本。优点是快、不需要额外解析库,缺点是写复杂规则时容易把自己看晕,而且网页一改版,正则就失效。入门阶段建议会写简单的就行,别把所有提取逻辑都押在正则上。

BeautifulSoup是新手友好派的代表。它把HTML转成一个可遍历的对象树,按标签名、class、id查找元素都非常直观,代码读起来就像在查字典:

from bs4 import BeautifulSoup soup = BeautifulSoup(html, "html.parser") title = soup.select_one("h1.article-title").get_text() items = [li.get_text() for li in soup.select("ul.list > li")]

XPath则是通过路径表达式来定位元素,通常配合lxml库使用,性能比BeautifulSoup高一些。如果你要爬的网站结构复杂,需要根据元素文本、属性组合定位时,XPath的表达能力更强:

from lxml import html doc = html.fromstring(html_text) titles = doc.xpath('//div[@class="news-item"]//h2//text()')

我的建议是:日常爬虫用BeautifulSoup足够,遇到复杂定位或者需要频繁交互的场景(配合Selenium)再上XPath。两个都会用,你就不会被某个库的局限性卡住。

2.3 登录、翻页、异步加载:三个绕不开的坑

先看登录场景。需要登录的网站,常见有两种登录方式。一种是表单登录,账号密码POST到登录接口,成功后会返回Cookie,用前面说的Session就能持续带着登录态。另一种是接口登录,登录接口返回一个token,后续每个请求都要在请求头里带上Authorization: Bearer <token>。源码包里如果涉及登录,去看main.py里的初始化逻辑,一般会先调一个login()函数,再进入主抓取循环。

再看翻页。老式网站是URL翻页,即?page=2?page=3这种,直接用循环改参数即可。难点在于怎么知道总页数,常见办法是解析页码区域最后一个数字,或者直接看“下一页”按钮是否还能点。还有一些网站是“滚动加载”型,下拉到页面底部就自动加载新内容,这种一般是JS通过接口取的数,直接找那条接口来抓要比模拟滚动的方式稳定得多。

最后是异步加载。判断页面数据是不是异步加载,有个最简单的办法:在浏览器里按F12,打开Network面板,刷新页面,看有没有XHR类型的请求返回的是JSON数据。如果有,那恭喜你,目标明确——直接请求那个接口,比解析HTML里的残片省事太多。source包里如果注释写着“数据从接口获取”,基本就是这个思路。

3. 实操过程:从环境配置到跑通第一个爬虫

3.1 Python环境准备:版本、虚拟环境、依赖安装

在动手跑源码包之前,先把环境准备好。我的建议是使用Python 3.9到3.12之间的版本,大多数开源爬虫代码照常运行。Python版本太老(比如3.6)会遇到语法不支持的情况,太新(比如3.13)则可能有个别第三方库还没适配。

安装Python这一步,Windows用户直接去python.org下载安装包,注意安装时勾选“Add Python to PATH”,这个钩子不勾的话,后面在cmd里敲python会提示找不到命令。macOS用户建议用Homebrew安装,Linux用户一般系统自带,但版本可能偏老,用到新特性时再考虑升级。

依赖安装就一条命令:

pip install -r requirements.txt

如果requirements.txt缺失,只看到源码里有import requests、bs4之类的语句,那你就手动装:

pip install requests beautifulsoup4 lxml

这里我强烈建议在虚拟环境里操作。虚拟环境就是给项目单独隔离出一套Python包空间,避免你装这个包时把另一个项目的依赖搞乱。创建和激活方式很简单:

python -m venv venv # Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate

看到命令行前面多了个(venv)前缀就说明激活成功了。

3.2 阅读源码的推荐顺序:别一上来就跑到黑

拿到源码包解压之后,先别急着执行。我建议的阅读顺序是:README → requirements.txt → config.py → main.py → spider.py。理由很简单:

  • README告诉你这个爬虫是干嘛的、依赖什么、怎么跑。
  • requirements.txt告诉你环境清单。
  • config.py告诉你目标站点、关键参数,这些是业务配置,先了解能帮你建立整体印象。
  • main.py把流程串起来,理解了调用关系,再看具体实现就不容易迷路。
  • spider.py、parser.py再进去看实现细节。

这个阅读顺序能避免一个常见问题:直接跑脚本,结果因为缺配置或者不知道要改哪里,报了一堆错。

看代码时重点关注这几个变量:start_url(入口地址)、max_page(最大页数)、delay(请求间隔)、save_format(保存格式)。把config.py里的参数对着自己的需求改掉,代码就完成了一半定制。

3.3 跑通第一遍:从报错到成功的一次完整记录

现在模拟一次真实操作。假设我们解压了一个源码包,里面是一个抓取某新闻网站标题和链接的爬虫,依赖装好了,直接执行:

python main.py

结果跳出来一个报错:

requests.exceptions.ConnectionError: HTTPConnectionPool(...) Max retries exceeded with url: /...

看到这个不要慌,按顺序排查:

  1. 本机能不能访问目标网站?浏览器打开看看,打不开就是目标站挂了或者你被墙/被屏蔽了。
  2. 网络代理是否干扰?有些代理工具会干扰requests的请求,在代码里设置proxies={"http": None, "https": None}跳过代理试试。
  3. 是不是需要SSL验证?加上verify=False试试。

先解决网络层,再看业务逻辑报错。第二类高频报错是:

AttributeError: 'NoneType' object has no attribute 'find_all'

这说明解析出来的内容是个空对象,大概率是页面结构变了,或者你的请求被重定向到了一个验证页面。这时候把resp.text打印出来看看,跟浏览器开发者工具里的Elements对比一下,就能定位问题出在请求环节还是解析环节。实践里这个“打印响应”的调试法,比空想定位问题快得多。

4. 常见问题与排查技巧实录

4.1 高频报错速查表

报错/现象可能原因处理办法
ModuleNotFoundError: No module named 'requests'依赖未安装pip install -r requirements.txt
中文乱码编码判断错误resp.encoding = resp.apparent_encoding
返回内容为空 / 只有JS代码数据是异步加载找XHR接口,直接请求JSON
频繁访问后被封IP触发反爬设置延时、随机User-Agent、代理池
状态码403 / 418被服务器识别为爬虫补充完整请求头,或加入Cookie
BeautifulSoup提取不到数据CSS选择器/XPath写错在浏览器里复制selector后用代码打印验证
UnicodeEncodeError控制台编码问题将结果写入文件,避免直接print

这个表我建议截图存一份。爬虫项目80%的报错都逃不出这几类,每踩一次坑,对照一次表,基本都能快速解决。

4.2 反爬应对与频率控制:别把目标站点搞崩

说到反爬,首先是态度问题。写爬虫的人最该敬畏的,是目标网站的服务压力。无节制的高频请求会拖垮别人的服务器,这不仅不道德,还可能让你的IP被拉黑。所以源码包里如果设置了time.sleep(1)这种延时,别急着删掉,那是对你对目标站都好的一行代码。

常见反爬手段和应对思路:

  • User-Agent检测:通过请求头判断是否为浏览器,解决方法是设置浏览器UA,最好多个随机切换。
  • IP频率限制:同一个IP短时间内请求次数过多会触发限制,解决方法是控制请求频率、使用代理IP池。
  • 登录验证:数据需要登录后才能看,解决方法是模拟登录或者使用Cookie维持会话。
  • 动态页面:数据由JS渲染生成,解决方法是找接口直接抓,或者用Selenium、Playwright模拟浏览器。
  • 验证码:这是最头疼的一类,基本靠第三方打码平台或OCR,但合规性要谨慎评估。

我一直信奉的原则是:先分析,再动手;请求尽量温和;只抓自己有权查看的数据。爬虫是个技术活,但它更是一个“有边界感”的技术活。多做几层合法性考量,不是限制你,是保护你。

4.3 断点续爬与日志:源码包里藏着的最实用小技巧

高质量源码包往往有一个容易被忽视的设计:断点续爬。逻辑很简单,就是把已抓取的链接或数据的唯一标识存下来(比如存进一个visited.txt或数据库),每次请求前先检查是否已处理过,是就跳过。这样程序中途崩了、被中断了,你可以从上次的位置继续,不用重新从头爬一遍。

代码思路:

import os visited_file = "visited.txt" def load_visited(): if not os.path.exists(visited_file): return set() with open(visited_file, "r", encoding="utf-8") as f: return set(line.strip() for line in f) def mark_visited(url): with open(visited_file, "a", encoding="utf-8") as f: f.write(url + "\n")

配合日志模块logging,你还能知道程序跑到哪里、哪里报错,不用一直盯着控制台。简单配置:

import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("spider.log", encoding="utf-8"), logging.StreamHandler() ] ) logger = logging.getLogger(__name__)

有了日志和断点续爬,跑一个几万页的大爬虫才心里有底。这也是我从那个不起眼的“源码.rar”里觉得最有价值的部分——它不是炫技,而是一个爬虫项目保障稳定性的根基。

5. 从源码包走向自己的项目:改造与进阶

5.1 三步把一个通用爬虫改造成自己的爬虫

如果你的目标网站和源码包里的不一样,改造通常就是三步:

第一步,改config.py里的目标地址和参数。把start_url替换成你的目标页,确认翻页规则,调整请求头。 第二步,改parser.py里的解析逻辑。用浏览器开发者工具找到你要的数据在哪个标签、哪个属性、哪条接口里,替换掉提取规则。 第三步,改storage.py里的存储方式。源码包里如果存成CSV,你想存Excel或者MySQL,就在这里动刀。

以存储为例,存CSV用标准库csv就够了:

import csv def save_to_csv(items, filename): if not items: return keys = items[0].keys() with open(filename, "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=keys) writer.writeheader() writer.writerows(items)

注意这里用了utf-8-sig而不是utf-8,否则用Excel打开CSV文件时中文会乱码。这是一个非常小但非常常见的坑。

5.2 进阶方向:异步、分布式、大模型逆向

基础跑通之后,如果想往专业级走,方向还挺多的。

异步方面可以用httpx配合asyncio,或者用aiohttp做并发请求,比多线程更高效,单机就能把抓取速度提升好几倍。写起来大概是:

import asyncio import aiohttp async def fetch(session, url): async with session.get(url) as resp: return await resp.text() async def main(): async with aiohttp.ClientSession() as session: tasks = [fetch(session, url) for url in urls] results = await asyncio.gather(*tasks)

分布式的话,Scrapy配合Redis来做URL调度、去重和队列分发,是主流方案。多个爬虫节点同时抓取,能应付非常大体量的数据任务。不过这个对工程能力要求高,得先把单机爬虫写扎实了再上。

还有一个比较热的概念是“大模型逆向爬虫”。以前我们需要手动分析接口的加密参数,比如常见的_signaturetoken等签名逻辑,需要断点调试JS代码、复现加密算法。这几年尝试的思路是:用大模型协助分析JS逻辑、生成逆向代码,甚至直接让大模型理解网页结构来定位关键节点。但说老实话,这个方向还处于辅助工具阶段,不能完全替代人工分析。想入门的话,先从读懂JS加密函数、了解常见的AES/哈希算法怎么做复写开始,更实际。

5.3 关于“源码”这一件事的真心话

最后想对这届喜欢囤源码的同学说几句。下载100个源码包,不如把1个源码包啃透。囤“用Python写爬虫-源码.rar”这种文件夹的快乐,本质上是收藏家式的快乐,是“我拥有了一套资源”的错觉。但技术进步的真相是:你能写出什么、能改出什么、能修好什么,才是你真正拥有的东西。

所以看完这篇之后,别急着去下载下一个源码包。打开手边最近的一个爬虫源码,按照第3节的阅读顺序过一遍,挑一个小的功能点改一改,把它改成你的版本。哪怕是改一个User-Agent、加一条日志、换一种存储格式——完成这个动作之后,这个源码才真正算你的。

我自己的经验是:爬虫项目是我接触Python以来练得最扎实的一项技能,因为它反馈极快——代码写错了马上报错,跑通了马上看到数据落盘,这种正反馈让人非常容易坚持。只要控制好频率、注意数据合规、多看官方文档,这个方向上能学到的远不止“写代码”,还有网络协议、数据存储、异常处理、系统设计,一环扣一环,越往后越有意思。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询