恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Python爬虫实战:requests请求、数据解析与CSV保存全流程解析
首页
资讯中心
/
Python爬虫实战:requests请求、数据解析与CSV保存全流程解析
Python爬虫实战:requests请求、数据解析与CSV保存全流程解析
发布时间:2026/9/7 12:19:33
简介这是Packt出版社《Web Scraping with Python》一书的完整配套示例源码适合正在学习Python网络爬虫、渴望通过动手实践掌握抓取技巧的开发者无论是初学解析原理还是希望接管完整工程都能按图索骥找到对应章节的参考实现。压缩包内共163个文件整体仅3.54MB以53个Python脚本和101张演示图片为核心辅以Scrapy工程配置、JSON数据样例、CSV数据集及README说明覆盖书中各章节的依赖安装和运行效果目录清晰便于读者快速定位。资源已吸引489人学习下载。源码按章节组织从BeautifulSoup、lxml等基础解析库到Scrapy爬虫框架再到Selenium WebDriver动态渲染、mechanize表单交互、pytesseract验证码识别等进阶主题均有示例可循每一段代码都附带对应抓取场景与运行截图读者不仅能对照书本理解原理还能直接运行验证输出并用PIL/Pillow处理验证码图片、用MongoDB存储抓取结果完整串联起数据采集、解析、清洗与落库的实战闭环。 我最早想写Python爬虫就是因为懒——一个页面上几十条数据手动复制粘贴得折腾半天。后来用requests把HTML源码拉下来再用正则把目标字段抠出来第一次尝到“代码替我干活”的甜头。这个标题挂着“源码”我猜你手上多半也有一份现成的爬虫代码。但说实话光把源码跑起来不算会真正的功夫在理解那条链路发请求、拿响应、解析字段、落盘保存。这篇文章我就按这条主线拆开讲。它适合刚学完Python基础语法、想动手做项目的人也适合手里拿着源码却不知道怎么改、怎么扩展的读者。1. 为什么我建议用爬虫作为Python实战的起点很多Python教程喜欢让人写计算器、记账本说实话这类练习写两遍就腻了而且和真实世界没啥关系。爬虫不一样它从第一天就有“真枪实弹”的味道请求的服务器是真实存在的返回的数据是动态变化的解析过程是跟真实网页源码较劲。语法、字符串处理、文件操作、异常处理、网络请求、数据格式转换……写一个完整爬虫几乎能把Python入门的语法点全部串起来。1.1 爬虫是系统性练习不是孤立知识点学变量的时候只能算数学函数的时候只能打印语法学完了还是不知道下一步该做什么。爬虫逼你把请求、解析、存储三段全串上requests负责通信正则或XPath负责从网页源码里挖数据最后用open()或csv库落盘。这个流程走通之后你会发现自己对“字符串处理”和“数据结构”的理解完全不一样了——因为你是为了解决问题去用它们而不是为了做题去背它们。这种“带着目的学”的路径比照着文档刷十遍语法都管用。1.2 爬虫项目的真实应用场景别把爬虫想得太神秘很多日常工作场景其实都会用到自己关注的网站更新了内容想第一时间拿到变化数据做市场调研时需要收集公开的报价、商品列表统计公开页面上的汇总信息手动复制太费时间给自己常用的接口做定期数据备份。这些场景都不涉及任何敏感数据纯粹是把重复劳动交给代码。理解这一点很重要爬虫的第一价值不是“爬”而是“减少重复、自动获取”。我见过很多人一上来就想搞分布式、搞高并发结果连一个页面都解析不对这是本末倒置了。2. 动手前必须搞清的HTTP请求基础爬虫的本质是模拟浏览器向服务器发送请求然后解析返回内容。搞不清这一点你会把时间浪费在瞎猜请求参数上。这个环节不复杂但绕不开。2.1 浏览器背后发生了什么在浏览器里输入网址按回车发生的事情是浏览器解析域名拿到服务器IP然后通过HTTP协议向服务器发送一个GET请求服务器处理后返回HTML页面浏览器再把它渲染成你能看到的界面。爬虫做的就是绕过“渲染”这一步直接拿到服务器返回的原始数据。更具体地说浏览器开发者工具按F12里的Network面板会记录每一次请求的URL、请求头、请求参数和响应内容。写爬虫时打开这个面板基本就等于给数据源画了张地图。以 https://quotes.toscrape.com/ 为例。这是一个专门给爬虫学习者准备的练习站页面结构简单、数据规整没有任何敏感内容。按F12打开Network面板刷新页面你能看到第一条请求就是文档本身的GET请求请求头里带着User-Agent、Accept等字段。这些字段是服务器判断“你是人还是机器”的关键依据后面处理反爬时会用到。2.2 requests库到底帮你做了什么requests是Python生态里最常用的HTTP客户端库。它做的事情本质上就是把上面那一串手工操作封装成了几行代码。你只需要关心的核心对象是URL、params、headers、cookies、timeout以及响应对象response的status_code、text、json()。这里有个新手常见的误区以为拿到response.text就万事大吉。实际上服务器返回的可能是一段被压缩过的内容或者编码不对导致乱码。所以requests要在headers里声明Accept-Encoding响应后推荐先设置encoding比如response.encoding utf-8再去读取text。这个细节不处理解析阶段会碰到一堆莫名其妙的乱码问题到时候你还会以为是数据源的错。3. 数据解析三件套正则、XPath与BeautifulSoup请求拿到了HTML源码接下来就是从一堆标签里把数据抠出来。三种方案各有用处我的建议是正则用来处理简单文本XPath处理结构化HTML效率高BeautifulSoup对新手最友好但性能略逊。解析方案适用场景学习成本性能正则表达式提取URL、数字、固定格式文本中快XPathlxml按标签层级提取结构化数据中快BeautifulSoup快速上手、容错性好低中3.1 正则表达式抽取数据的最小工具正则不擅长解析嵌套的HTML结构但对付“从一行文本中提取链接或数字”这种场景非常利索。比如抓取页面里的所有链接一条 rhref(.?) 就能用。需要注意正则的贪婪匹配问题默认会尽量多匹配所以写的时候要习惯用非贪婪模式.?否则经常会把一大段不该匹配的内容也吞进去。举个我踩过的例子写 ra href(.) 去匹配链接结果它把一整行里所有标签都当成一个链接抓了真实数据全被污染。改成(.?)之后问题立刻消失。3.2 XPath与lxml结构化提取XPath是另一种更符合“结构”直觉的方式。它把HTML当成一棵树用类似文件路径的写法定位节点。比如//div[classquote]/span[classtext]意思是从根上找到所有class为quote的div再取里面class为text的span。lxml底层是C实现速度很快数据量大、行数多的页面建议优先用XPath。实际写起来XPath对类名变化比较敏感如果目标页面频繁改版维护成本会比BeautifulSoup高一点。3.3 BeautifulSoup对新手友好的解析器BeautifulSoup的写法和直觉接近soup.find_all(div, class_quote)然后取.text属性就能拿到标签里的文本。它容错性强即使页面源码里标签嵌套不规范也能解析出结果。缺点是纯Python实现大批量解析时性能没有lxml快。我的经验是项目初期先用BeautifulSoup把流程跑通如果后面数据量大到明显卡顿再切到lxml。路径很平滑改动量一般也不大。4. 完整实战爬取练习站点并保存数据我直接用 https://quotes.toscrape.com/ 写一个完整示例。这个站点包含名言、作者和标签三类数据正好覆盖列表页信息提取的全过程也是我推荐给所有入门者的第一个练手目标。4.1 分析目标页面结构打开页面按F12选中Elements面板你会看到一条条结构相同的div每个div的class是quote里面有span classtext放名言内容small classauthor放作者还有div classtags下面挂着多个a标签。这些结构非常稳定抓取逻辑很直接。分析DOM结构这件事几乎占整个爬虫开发工作量的一半多花点时间看清楚结构解析阶段就能少走很多弯路。4.2 完整源码拆解下面这套源码就是完整可运行的版本依赖只有requests和BeautifulSoupimport csv import requests from bs4 import BeautifulSoup def fetch_page(url): 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 } resp requests.get(url, headersheaders, timeout10) resp.encoding resp.apparent_encoding resp.raise_for_status() return resp.text def parse_page(html): soup BeautifulSoup(html, html.parser) quotes [] for item in soup.select(div.quote): text item.select_one(span.text).get_text(stripTrue) author item.select_one(small.author).get_text(stripTrue) tags [tag.get_text(stripTrue) for tag in item.select(a.tag)] quotes.append({ text: text, author: author, tags: , .join(tags) }) return quotes def save_to_csv(rows, filenamequotes.csv): with open(filename, a, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[text, author, tags]) if f.tell() 0: writer.writeheader() writer.writerows(rows) if __name__ __main__: base_url https://quotes.toscrape.com/page/{} all_quotes [] for page in range(1, 4): # 抓取前三页 html fetch_page(base_url.format(page)) all_quotes.extend(parse_page(html)) save_to_csv(all_quotes) print(f完成共采集 {len(all_quotes)} 条数据)代码跑起来之前有几个细节值得单独说明第3行的依赖要提前安装pip install requests beautifulsoup4第13行 resp.encoding resp.apparent_encoding 解决中文乱码问题apparent_encoding会从响应内容里智能判断编码比手动硬编码更省心第17行用CSS选择器定位元素比纯find_all写法更简洁直观第29行 encodingutf-8-sig 是为了让Excel打开CSV不乱码这点很多人栽过存成普通utf-8用别的工具看没问题一进Excel就出幺蛾子。运行之后当前目录会生成一个quotes.csv每行一条数据包含名言、作者和标签。到这里一个最基础的爬虫已经完整跑通了。5. 反爬应对UA伪装、频率控制与断点续爬有些网站会在服务器端检查请求特征如果发现请求头很“机器人”就直接拒绝访问。爬虫和反爬之间的博弈是个长期话题我这里只说合规、常规的做法。5.1 UA伪装和请求头服务器最常检查的就是User-Agent。requests默认的UA是python-requests/2.x一眼就能被识别出来。最简单有效的应对就是把浏览器常用的UA字符串复制到请求头里就像上面示例代码第10行那样。还可以顺手加上Referer、Accept等字段让请求看起来更接近真实浏览器。这个操作本质不是什么“偷偷绕过”而是让程序以合理身份去访问公开内容。5.2 频率控制与重试机制频率控制是爬虫领域最需要自觉的地方。请求太快轻则被服务器临时限制重则给目标服务造成压力。实操中我习惯用time.sleep(1)做最小间隔再用随机抖动打破固定规律比如time.sleep(random.uniform(0.5, 1.5))。另外要给请求加上超时和重试用requests自带的timeout参数防卡死再用try/except或退避重试来处理偶发失败。重试时推荐用指数退避第一次等1秒第二次等2秒第三次等4秒避免问题一直存在时反复打同一个接口。5.3 断点续爬数据量大时中途断网或程序崩溃不可避免。我的处理思路是不把所有数据都攒在内存里最后才写文件而是每解析完一页就追加写入一次就像上面save_to_csv那样。这样哪怕程序跑到一半挂了已经写入的数据也安全落在磁盘上。如果你需要精确到“从第几页继续”可以把当前页号单独存到一个进度文件里下次启动时读出来接着跑。这个思路实现起来只要几行代码但实战价值极高尤其适合长时间抓取的任务。6. 提速与源码组织从单线程到并发爬虫写顺了之后你会嫌一条一条爬太慢。提速的方向有很多我按性价比来排序不建议一上来就上重型框架。6.1 线程池提速requests并发访问属于IO密集型任务用线程池就能明显提速。Python标准库concurrent.futures.ThreadPoolExecutor就能干这个事代码改动很小把页号塞进一个列表让线程池并发调用fetch_page就行。几行代码速度翻几倍。注意控制线程数量常见range(4, 8)比较稳妥并发太高容易被服务器限流反而得不偿失。6.2 异步与分布式什么时候才值得上如果只是个人用、爬几千条数据线程池完全够。等到数据量到了百万级、或者需要24小时持续采集再考虑用asyncio aiohttp做异步协程或者上Scrapy这类框架。Scrapy自带请求调度、去重、管道、中间件分布式扩展也成熟但学习曲线陡得多。我的建议是先把手写的爬虫思路吃透等遇到真实的规模化需求再迁到框架不要为了用框架而用框架。手里有源码的时候也一样先把它跑起来、看懂边界再考虑替换实现。6.3 源码的模块化组织拿到一套“源码”第一件事不是急着跑而是看懂模块划分。一个结构清晰的爬虫项目通常会有这些部分配置区放URL规则、请求头、延时参数下载器负责发请求、重试、编码处理解析器负责从HTML或JSON里抽取字段存储模块负责写CSV、数据库调度入口控制抓取哪些URL、如何去重。上面示例为了演示把代码都塞在一个文件里实际项目建议按模块拆开。改别人源码的时候先找到这几个边界你会发现自己改起来顺手很多排查问题也更方便。7. 爬虫的边界与合规意识这一块内容不算硬技术但我个人觉得比硬技术更重要。写爬虫之前先判断三件事目标网站是否允许爬取、抓取的数据是否涉及个人信息、采集频率会不会影响对方服务。7.1 robots协议与平台规则大多数正规网站都提供了robots.txt文件在域名后加/robots.txt就能看到它声明了哪些路径允许爬虫访问。虽然它不具强制力但尊重它既是职业道德也是降低风险的有效策略。练习时优先选择公开的测试站点真实项目里最好先确认目标站点的使用条款。这篇文章里的示例站本身就是为了爬虫练手准备的可以放心使用。7.2 判断数据边界公开数据不等于可以随意商业化使用。涉及个人隐私、版权作品的数据用途和存储方式都有严格约束。拿来做个人学习、数据分析没问题但二次发布或商用前一定要确认授权边界。我的原则是三条守robots、控频率、不碰个人敏感数据。守住这三点爬虫就是一个绿色健康的自动化工具而不是一把乱挥的刀。最后再分享一个排查经验很多人拿到源码之后第一反应是复制、运行然后碰到报错就懵了。其实排查爬虫报错几乎都是同一个套路——先在浏览器里手动打开目标URL看看页面是否正常访问再用requests单独请求一次打印出status_code和text的前几百个字符最后才去思考是不是解析逻辑写错了。按这个顺序排查九成的问题都能自己定位不用遇事就去翻文档、问别人。写爬虫这东西动手跑通一遍比看十篇教程都管用。本文还有配套的精品资源点击获取