本文还有配套的精品资源点击获取简介一套拿来就能跑的Python爬虫练习代码从发请求开始用requests获取网页内容再用BeautifulSoup解析HTML结构提取文字、链接、图片等信息最后保存成CSV文件test-1.csv、test-2.csv或纯文本lines.txt、test.txt。里面包含豆瓣读书简介抓取、新东方教师头像批量下载、Glassdoor城市职位分布统计、Merkle树图片采集等真实小场景脚本还覆盖基础语法实践字符串处理、列表/元组/字典操作、条件判断、循环遍历、函数封装、CSV文件读写、简单数据库交互。所有脚本依赖少仅requests、beautifulsoup4等主流轻量库环境配置简单适合新手边敲边理解每个环节怎么衔接——比如怎么把response.text变成表格字段怎么跳过空标签、处理编码异常、模拟浏览器请求头、控制请求节奏。代码不含复杂框架或异步逻辑专注讲清采集链路的核心步骤。注意仅供学习参考使用前请务必查阅目标网站robots.txt、服务条款确保数据获取行为合法合规。1. 这不是“写个爬虫”的速成课而是一条能踩实每一步的采集链路你打开这个资源包看到的不是一行行孤立的代码片段而是一整条从键盘敲下第一个import requests开始到双击生成的test-1.csv里真正看到豆瓣图书标题、评分、作者那一列列数据为止的完整路径。它不教你“如何成为爬虫大神”而是手把手带你把“网页→文本→结构→文件”这四个环节像拧螺丝一样一颗一颗、严丝合缝地拧紧。我带过几十个零基础转行做数据工作的学员最常卡死的地方从来不是“BeautifulSoup怎么用”而是——为什么response.text里明明有“评分9.2”用.find()却返回None为什么CSV打开全是乱码为什么下载了10张头像第11张就报错ConnectionResetError这些问题全在这个包里被拆解成了可复现、可调试、可打断点的具体脚本。核心关键词“Python爬虫, requests, BeautifulSoup, CSV存储, 网页数据提取”说的不是五个并列技术点而是一条不可分割的流水线requests是你的手伸出去拿到网页这团毛线BeautifulSoup是你的梳子把毛线理出经纬标签结构数据提取是你的剪刀沿着经纬剪下需要的布片文字、链接、图片URLCSV存储是你的针线盒把布片按固定格式钉成可用的表格。这条链路上任何一个环节松动整条线就断。所以这个包里的每个.py文件都不是“示例”而是这条链路上一个被刻意设计出来的“故障点”或“衔接点”。比如01-网络请求-requests.py里故意没加headers跑一次你就立刻明白什么叫“403 Forbidden”豆瓣读书简介.py里专门留了一处div classintro可能为空的逻辑分支让你亲手处理NoneType错误新东方头像下载.py里用time.sleep(1)硬控节奏不是为了“防封”而是让你亲眼看到请求频率和服务器响应之间的肉眼可见关系。它适合谁适合那种对着教程敲完print(soup.title.text)能跑通但一想“我要抓100本书的简介存进Excel”就卡在“怎么循环怎么去重怎么处理有的书没简介”的人。也适合刚学完Python基础语法发现for循环和dict字面量都懂但不知道它们在真实数据流里该往哪儿塞的初学者。它不假设你懂HTTP状态码所以Glassdoor-cityjobs.py开头就用注释标出status_code 200才是安全继续的信号它也不假设你熟悉编码所以文件处理-csv.py里直接演示了open(..., encodingutf-8-sig)这个Windows下救过无数人的参数。所有脚本都基于标准库或requests、beautifulsoup4这两个轻量依赖意味着你装完Python 3.8pip install -r requirements.txt就能在任何一台笔记本上从第一行代码开始稳稳当当地走完这条链路。记住爬虫的本质不是对抗而是理解——理解网页怎么生成理解服务器怎么响应理解数据怎么流动。这个包就是给你一把理解的尺子。2. 内容整体设计与思路拆解为什么是requests BeautifulSoup CSV这条铁三角很多人问“现在都用Scrapy、Playwright了为啥还教requests和BeautifulSoup”我的回答很直接因为它们是唯一能让你看清数据从网络管道里‘流出来’那一刻模样的工具组合。Scrapy像一辆全自动装配线你放进去种子URL它吐出来ItemPlaywright像一个真人操作浏览器你告诉它“点这里、输那里”它帮你模拟。而requests BeautifulSoup是你亲手拧开水管接头看着水HTML哗啦啦涌出来再蹲在地上用一把小镊子.find()、.select()把水里的沙子无关标签、碎石空格换行、浮萍广告div一点点挑干净最后把清水纯文本/结构化字段舀进你准备好的玻璃瓶CSV里。这个过程慢但每一个动作你都看得见、摸得着、改得了。2.1 为什么选requests而不是urlliburllib是Python自带的“裸金属”工具它把HTTP协议的每个螺丝钉都暴露给你你需要手动构造Request对象手动处理urlencode手动管理cookie jar手动解析Content-Encoding。而requests做了三件关键事自动处理重定向、自动解码gzip压缩、自动管理会话Session。这绝不是“偷懒”。举个真实例子你用urllib去抓豆瓣读书页面response.read()拿到的可能是二进制的gzip流直接.decode(utf-8)会报错而requests.get(url).text它内部已经根据Content-Encoding: gzip自动解压并根据Content-Type里的charsetutf-8自动解码。这个“自动”省掉的是新手至少两天的编码排查时间。Glassdoor-cityjobs.py里用session requests.Session()就是为了复用TCP连接和cookies避免每次请求都重新握手这是性能优化的起点也是理解“会话”概念的入口。requests没有隐藏复杂性而是把复杂性封装在合理的位置让你专注在“我要什么数据”上而不是“HTTP协议怎么工作”。2.2 为什么选BeautifulSoup而不是正则或lxml正则表达式regex能匹配HTML吗技术上可以但那是自虐。HTML是嵌套结构正则是线性模式用正则去匹配divphello/pspanworld/span/div里的world你得写一个能处理任意层级嵌套的恐怖表达式。而BeautifulSoup的核心价值在于它把HTML文档解析成一棵树DOM Tree。soup.find(div, class_intro)你不是在字符串里找文本而是在树的节点里找一个叫div、属性class值为intro的“枝杈”。soup.select(a[href^https])用CSS选择器语法直觉地定位所有以https开头的链接。这种思维转换是爬虫从“字符串处理”跃升到“结构化提取”的分水岭。02-遍历文档-BeautifulSoup.py里那几行for tag in soup.find_all([h1, h2, p])就是在教你怎么用树的遍历逻辑替代笨拙的while循环字符串切片。至于lxml它更快更底层但学习曲线陡峭错误提示晦涩。BeautifulSoup用html.parser作为默认解析器虽然慢一点但胜在稳定、容错强——遇到 malformed HTML现实中90%的网页都是它能尽力修复并继续解析而lxml可能直接抛异常。对入门者稳定性比速度重要一百倍。2.3 为什么CSV是首选存储而非JSON或数据库JSON适合存储嵌套结构数据库适合海量查询但新手的第一个目标永远是“让数据出现在Excel里”。CSV是Excel、Google Sheets、甚至记事本都能直接打开的通用语言。test-1.csv和test-2.csv的设计就是刻意暴露CSV的“脆弱性”当你用csv.writer写入包含逗号的书名如《Python, Data Science and Machine Learning》时它会自动用双引号包裹字段当你写入换行符\n时它会正确处理多行单元格。文件处理-csv.py里演示了DictWriter它强制你定义fieldnames这看似多此一举实则是建立“数据契约”的第一步——你知道这张表永远有title、author、rating三列不会因为某本书缺作者就少一列导致后续分析错位。而数据库如数据库.py里用的sqlite3它的价值不在“存”而在“查”。数据库.py里那句cursor.execute(SELECT * FROM books WHERE rating ? ORDER BY rating DESC, (8.5,))是在告诉你当你的数据量从100行涨到10万行当你要查“上海地区薪资过2万的Python职位”CSV就得靠Excel筛选到崩溃而SQL一句就能搞定。所以这个包的存储路径是CSV练手、验证、交付小批量结果→ SQLite本地中等规模数据管理→ 真实数据库生产环境。它不跳步每一步都踩在真实需求的痛点上。3. 核心细节解析与实操要点从response.text到test-1.csv的每一处暗礁拿到一个网页的HTML只是万里长征第一步。response.text看起来是纯文本但它背后藏着编码、结构、动态渲染、反爬策略四座大山。这个包里的每一个脚本都在帮你翻越其中一座。3.1 编码问题为什么中文总是乱码response.contentvsresponse.text的生死抉择requests.get(url)返回的response对象有两个核心属性.content原始字节流和.text解码后的字符串。新手最大的坑就是无脑用.text。豆瓣读书简介.py里有一行注释# 注意豆瓣部分页面返回的charset可能未在meta中声明需手动指定。什么意思浏览器看到meta charsetutf-8就知道用UTF-8解码但requests只看HTTP响应头里的Content-Type: text/html; charsetutf-8。如果网站没在响应头里声明很多老站不规范requests就会用ISO-8859-1拉丁文去解码UTF-8字节结果就是李连如这种乱码。解决方案是先用.content拿到字节再用chardet库检测编码或直接指定response.content.decode(utf-8)。01-网络请求-requests.py里就演示了response.content.decode(utf-8, errorsignore)errorsignore是保命参数它会跳过无法解码的字节保证程序不死。但更优雅的做法是response.encoding utf-8强制requests用UTF-8解码.text。这个细节决定了你抓下来的数据是“可用的中文”还是“一堆无法搜索、无法分析的方块字”。3.2 结构解析如何精准定位“豆瓣简介”那个div.find()、.find_all()、.select()的实战取舍BeautifulSoup提供了三种主要查找方式它们不是功能重复而是适用场景不同-.find()找第一个匹配项。soup.find(div, idlink-report)适用于页面中ID唯一、且你确定它存在的场景如豆瓣的简介区ID是固定的。-.find_all()找所有匹配项。soup.find_all(img, srcTrue)适用于批量提取所有带src属性的图片标签这是下载头像的基础。-.select()用CSS选择器语法最灵活强大。soup.select(div.indent div p)能精确描述“在class为indent的div下的div里的p标签”这是处理复杂嵌套结构的利器。豆瓣读书简介.py里有个关键细节它先用.find(div, idlink-report)定位到简介容器再用.find(div, class_intro)在里面找真正的文本div。为什么不能一步到位因为idlink-report的div里可能包含编辑推荐、豆瓣用户评论等多个classintro的div直接.find_all(div, class_intro)会抓混。这就是“分层定位”的思想——先用强约束ID锁定大区域再用弱约束class在区域内精确定位。新东方头像下载.py里用.find_all(img, {data-src: True})利用了BeautifulSoup的字典语法只找那些data-src属性存在不为空的img标签完美避开占位图。这些不是技巧而是对HTML结构本质的理解标签是容器属性是标识层级是关系。3.3 数据清洗空值、多余空格、HTML实体如何让数据“干净得能直接喂给模型”爬下来的数据90%的时间花在清洗上。test.txt和lines.txt的存在就是为了让你练习这个过程。豆瓣读书简介.py里有这样一段intro_div soup.find(div, class_intro) if intro_div: # 去掉所有标签只留纯文本 raw_text intro_div.get_text() # 去掉首尾空白合并中间多个空格为一个 clean_text .join(raw_text.split()) # 将HTML实体如 nbsp; 转为普通空格 import html final_text html.unescape(clean_text)这里包含了清洗三板斧1.get_text()剥离所有HTML标签只保留文本内容。这是最基础也最关键的一步。2.raw_text.split()将字符串按空白字符空格、换行、制表符分割成列表再用 .join()拼接天然解决“多空格变单空格、换行变空格”的问题。比写正则re.sub(r\s, , raw_text)简洁高效。3.html.unescape()处理HTML实体。网页里常见的amp;、quot;”、nbsp;不间断空格都会被正确还原。merkle.jpg的采集脚本里图片URL可能包含%20空格编码urllib.parse.unquote()就是干这个的。Glassdoor-cityjobs.py里还有个经典场景职位数1,234直接存CSV会当成字符串无法排序。脚本里用int(job_count.replace(,, ))先去掉千分位逗号再转整型。这些细节就是真实项目里区分“能跑”和“能用”的分水岭。3.4 反爬基础不是“绕过”而是“尊重”——请求头模拟与频率控制的底层逻辑所谓“反爬”本质是服务器在识别“非人类流量”。新东方头像下载.py里那几行headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 } response requests.get(img_url, headersheaders, timeout10)User-Agent不是伪装而是告知服务器“我是谁”。如果你的请求头是空的requests默认的python-requests/2.x服务器一眼就认出这是爬虫程序可能直接返回403。加上一个主流浏览器的UA是告诉服务器“我是一个Chrome浏览器来正常访问”。这不是欺骗是遵循HTTP协议的“自我介绍”规范。timeout10同样重要它防止你的程序卡死在某个慢响应上。run_all.py里用time.sleep(1)不是为了“躲过检测”而是模拟人类阅读间隔。人不会一秒刷10次页面服务器的QPS每秒查询率限制本质上是对“资源公平使用”的保护。Glassdoor-cityjobs.py里用try...except requests.exceptions.RequestException as e:捕获所有网络异常再配合time.sleep(2)重试这才是健壮爬虫的写法——它不追求最快而追求最稳。4. 实操过程与核心环节实现手把手跑通豆瓣读书简介抓取全流程现在我们以豆瓣读书简介.py为核心完整走一遍从零到生成test-1.csv的实操流程。这不是照着抄而是理解每一步背后的“为什么”。4.1 环境准备与依赖安装三分钟搞定拒绝“环境配置地狱”确认Python版本打开命令行输入python --version确保是3.8或更高。低于3.8的版本某些语法如f-string可能不支持。创建独立虚拟环境强烈推荐避免污染全局Python环境。bash # 在资源包根目录下执行 python -m venv venv # Windows激活 venv\Scripts\activate.bat # macOS/Linux激活 source venv/bin/activate安装依赖requirements.txt里只有两行requests2.31.0 beautifulsoup44.12.2执行pip install -r requirements.txt。注意这里指定了具体版本号是为了保证你和我运行的是完全一致的库避免因版本差异导致行为不同比如旧版BeautifulSoup对某些HTML解析有bug。4.2 代码逐行解析豆瓣读书简介.py的深度拆解import requests from bs4 import BeautifulSoup import csv import time import htmlrequests发起HTTP请求。BeautifulSoup解析HTML。csv操作CSV文件标准库无需额外安装。time控制请求间隔time.sleep()。html处理HTML实体标准库。def get_book_intro(book_url): 获取单本书的简介 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 } try: response requests.get(book_url, headersheaders, timeout10) response.raise_for_status() # 检查HTTP错误状态码4xx, 5xx # 关键手动指定编码规避豆瓣部分页面meta声明缺失问题 response.encoding utf-8 soup BeautifulSoup(response.text, html.parser) # 分层定位先找大容器再找具体内容 link_report_div soup.find(div, idlink-report) if not link_report_div: return None, 未找到简介容器 intro_div link_report_div.find(div, class_intro) if not intro_div: return None, 未找到简介文本div # 清洗数据三板斧 raw_text intro_div.get_text() clean_text .join(raw_text.split()) # 合并空白 final_text html.unescape(clean_text) # 解析HTML实体 return final_text, None # 成功返回简介文本和None错误 except requests.exceptions.RequestException as e: return None, f网络请求失败: {e} except Exception as e: return None, f解析失败: {e}这段函数是整个脚本的“心脏”。它封装了所有核心逻辑-response.raise_for_status()这是必须加的保险。没有它response.status_code 404时程序还会继续往下执行导致BeautifulSoup解析一个404页面的HTML通常是错误提示页结果抓到一堆垃圾数据。-response.encoding utf-8再次强调这是解决豆瓣乱码的钥匙。-link_report_div.find(div, class_intro)演示了分层定位的威力。如果简介容器不存在函数直接返回None和错误信息避免后续.get_text()对None调用报错。-try...except捕获了两类错误网络层RequestException和解析层Exception并返回清晰的错误信息方便调试。# 主程序 if __name__ __main__: # 示例豆瓣《深入理解计算机系统》的URL urls [ https://book.douban.com/subject/1017772/, https://book.douban.com/subject/1007305/, https://book.douban.com/subject/1008522/ ] results [] for i, url in enumerate(urls): print(f正在抓取第{i1}本书: {url}) intro, error get_book_intro(url) if error: print(f❌ 抓取失败: {error}) results.append([url, , error]) else: print(f✅ 抓取成功简介长度: {len(intro)} 字) results.append([url, intro, ]) # 控制节奏模拟人类行为 if i len(urls) - 1: # 最后一次不sleep避免无谓等待 time.sleep(2) # 保存到CSV with open(test-1.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([书籍URL, 简介文本, 错误信息]) # 表头 writer.writerows(results) # 写入所有数据 print(\n 全部完成结果已保存至 test-1.csv)urls列表定义了要抓取的目标。你可以轻松地把这个列表换成一个包含100个URL的文件读取逻辑。results列表这是一个二维列表每一行是一个[url, intro, error]的列表最终会变成CSV的一行。这是将“结构化数据”映射到“表格行”的最直观方式。with open(..., encodingutf-8-sig)utf-8-sig是Windows平台的救星它会在文件开头写入BOM字节顺序标记确保Excel能正确识别UTF-8编码避免打开CSV时仍是乱码。writer.writerow()和writer.writerows()前者写表头一行后者写数据多行。writerows(results)比循环调用writerow()效率更高。4.3 运行与验证如何读懂test-1.csv里的每一行执行python 豆瓣读书简介.py后打开生成的test-1.csv。你会看到三列-书籍URL原始链接用于溯源。-简介文本清洗后的纯文本可以直接复制到Word里做分析或者喂给NLP模型。-错误信息如果某本书抓取失败这里会记录具体原因如“未找到简介容器”、“网络请求失败”这是调试的黄金线索。打开test-1.csv用Excel的“数据”→“分列”功能按逗号分隔就能看到整齐的三列。你会发现简介文本列里所有多余的空格、换行、HTML符号都消失了只剩下干净的中文。这就是“数据清洗”完成的标志。test-2.csv的生成逻辑类似但它可能包含更多字段如书名、作者、评分其results列表的每一行就是[title, author, rating, intro]writer.writerow()的表头也要相应改为[书名, 作者, 评分, 简介]。这个模式就是你扩展到抓取100本书、1000本书的基石。5. 常见问题与排查技巧实录那些让我熬夜到凌晨三点的坑在真实项目里90%的问题都出在“意料之外”的地方。下面这些是我和学员们踩过的、最典型、最高频的坑以及对应的、经过实战检验的排查技巧。5.1 “403 Forbidden”不是被封了是你的“身份证”没填对现象requests.get(url)返回response.status_code 403response.text里是“Access Denied”或“Forbidden”。排查思路1.检查User-Agent这是90%的原因。用浏览器开发者工具F12→ Network → 刷新页面 → 点击第一个HTML请求 → Headers → Request Headers →User-Agent复制粘贴到你的代码里。新东方头像下载.py里的UA就是这么来的。2.检查Referer有些网站要求请求必须来自特定页面如从首页跳转过来。在Headers里找Referer加到你的headers字典里Referer: https://www.example.com/。3.检查Cookies极少数网站需要登录态。用浏览器登录后复制Cookie字符串加到headers里Cookie: your_cookie_string_here。但这通常意味着你需要先模拟登录超出了本包范围。终极技巧用curl命令行工具验证。在终端里输入curl -H User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 https://example.com如果curl能拿到正常HTML说明你的Python代码UA设置有问题如果curl也403说明网站有更严格的防护如JS挑战这时就需要升级工具如Selenium但这已超出本包“基础链路”的范畴。5.2 “AttributeError: ‘NoneType’ object has no attribute ‘get_text’”你的.find()找空了现象程序崩溃报错指向intro_div.get_text()提示intro_div是None。根本原因soup.find()没找到匹配的标签返回None你却把它当成了一个BeautifulSoup Tag对象来调用方法。排查与解决-永远不要假设.find()一定成功。豆瓣读书简介.py里用if not intro_div: return None, 未找到...就是最佳实践。-用print(soup.prettify()[:500])在.find()之后打印出前500个字符的美化HTML肉眼检查目标标签是否存在、ID/class名是否拼写正确。豆瓣的idlink-report很容易手误写成link-reportt。-用print(soup.find(div, idlink-report))直接打印查找结果如果是None说明目标容器根本不存在需要检查URL是否正确或者该页面结构是否发生了变化网站改版。5.3 CSV乱码不是Python错了是Excel“装傻”现象用记事本打开test-1.csv是正常的中文但用Excel打开就是乱码如“李连如”。原因Excel在Windows上默认用ANSI编码通常是GBK打开CSV而你的文件是UTF-8编码。解决方案三选一1.最推荐保存时用encodingutf-8-sig已在代码中体现。utf-8-sig会在文件开头写入BOMExcel就能正确识别。2.Excel内解决数据 → 从文本/CSV → 选择文件 → 在导入向导中“文件原始格式”选择“65001: Unicode (UTF-8)”。3.终极方案放弃CSV用pandas库直接生成Excel文件df.to_excel(output.xlsx, indexFalse)一劳永逸。5.4 图片下载失败ConnectionResetError和IncompleteRead现象新东方头像下载.py运行到一半报错ConnectionResetError: [WinError 10054]或http.client.IncompleteRead。原因服务器主动断开了连接通常是因为请求过于频繁触发了服务器的连接数限制或速率限制。排查与解决-增加time.sleep()这是最简单有效的办法。新东方头像下载.py里是sleep(1)你可以根据实际情况调大到2或3秒。-使用Session对象session requests.Session()然后用session.get(img_url)。Session会自动复用TCP连接减少握手开销比每次都新建连接更“温和”。-添加重试机制在try...except里捕获ConnectionResetError然后time.sleep(5)后重试一次。Glassdoor-cityjobs.py里就有类似的重试逻辑。5.5 动态渲染内容缺失“明明网页上有为啥BeautifulSoup找不到”现象你在浏览器里能看到完整的简介文本但用requests抓下来的HTML里对应位置是空的或者只有div idintro/div这样的占位符。原因简介内容是通过JavaScript异步加载的AJAX。requests只能拿到初始的HTML骨架拿不到JS执行后填充的内容。判断方法在浏览器开发者工具里Network → 刷新 → 查看XHR/Fetch标签页找那些返回JSON数据的请求通常是/api/book/intro?id123这样的URL。如果找到了说明数据是API提供的。解决方案本包范围内-直接请求API接口把requests.get()的URL从网页URL换成那个XHR请求的URL。Glassdoor-cityjobs.py里抓取城市分布就是直接调用了Glassdoor的公开API而不是解析它的前端页面。-升级工具如果必须渲染JS就需要Selenium或Playwright。但这已超出本包“基础链路”的定位属于进阶内容。提示遇到任何问题第一步永远是print(response.status_code)和print(len(response.text))。状态码告诉你请求是否成功长度告诉你是否拿到了有效内容。这是所有排查的起点。6. 从练习到生产如何用这个包搭建你自己的数据采集工作流这个资源包的价值不在于它能帮你抓多少本书或多少张头像而在于它为你提供了一个可无限扩展的“脚手架”。当你熟练掌握了豆瓣读书简介.py的模式就可以把它当作模板快速构建任何你需要的数据采集任务。6.1 模板化改造三步替换生成你的专属爬虫假设你想抓取“知乎热榜”的问题标题和热度值。你只需要三步1.替换URL来源把urls列表改成从知乎热榜API如https://www.zhihu.com/api/v4/hot获取的JSON数据里提取出的问题URL列表。2.替换解析逻辑把get_book_intro()函数里soup.find(div, idlink-report)的部分改成针对知乎页面结构的查找比如soup.find(h1, class_QuestionHeader-title)。3.替换存储字段把results.append([url, intro, error])改成results.append([question_title, hot_score, url])并相应修改CSV表头。这个过程就是把“豆瓣模式”迁移到“知乎模式”。02-遍历文档-BeautifulSoup.py里演示了如何遍历所有a标签提取链接03-list.py里展示了如何用列表推导式高效处理数据06-dictionary.py里讲解了如何用字典存储结构化信息如{title: xxx, score: 123}。这些基础语法就是你组装新爬虫的“乐高积木”。6.2 工程化演进从单脚本到可维护项目当你从抓3本书发展到抓3000本书时单个.py文件就难以维护了。这时你应该-拆分模块把get_book_intro()函数单独放到scraper.py里把URL列表放到config.py里把CSV写入逻辑放到storage.py里。-引入日志用Python内置的logging模块替代print()记录每一次成功/失败方便回溯。-添加配置文件用config.ini或settings.json管理headers、sleep_time、timeout等参数不用再改代码。-错误重试与持久化用retrying库包装get_book_intro()失败自动重试用pickle或SQLite记录已抓取的URL避免重复劳动。run_all.py就是这个演进的雏形——它试图统一运行所有脚本。你可以把它改造成一个命令行工具python run_all.py --target douban --count 100让它按需启动。6.3 合规性与伦理技术能力的边界在哪里最后也是最重要的一点技术无罪但使用有界。这个包里所有的脚本都严格遵守了robots.txt协议。豆瓣读书简介.py的URL是公开可访问的图书详情页新东方头像下载.py的目标是教师公开的个人主页。摘要描述里反复强调的“查阅目标网站robots.txt、服务条款及数据使用合规性”不是一句空话。robots.txt是网站管理员发布的“访客指南”它明确告诉你哪些区域可以爬哪些不可以。https://book.douban.com/robots.txt里写着Allow: /subject/说明图书详情页是允许抓取的而Disallow: /search则明确禁止抓取搜索结果页。Glassdoor-cityjobs.py之所以能运行是因为Glassdoor的公开API非官方但长期稳定并未在robots.txt中被禁止且其返回的数据是面向公众的职位信息。我的建议是永远把你抓取的数据想象成图书馆里的一本书。你可以借阅、摘抄、做笔记用于个人学习、研究但不能整本复印去卖商业分发也不能把书撕了卖纸破坏性采集。这个包教会你的不仅是技术更是对数据、对规则、对他人劳动成果的敬畏。当你能稳稳地走完这条从requests到CSV的链路并始终记得这条边界时你才真正跨过了爬虫工程师的第一道门槛。我在实际使用中发现最可靠的爬虫往往不是最快的而是最“守规矩”的。它会耐心等待会礼貌问候UA会按指示行动robots.txt会及时收手频率控制。这种“守规矩”不是束缚而是让你的采集工作能长久、稳定、可持续运行的根本保障。本文还有配套的精品资源点击获取简介一套拿来就能跑的Python爬虫练习代码从发请求开始用requests获取网页内容再用BeautifulSoup解析HTML结构提取文字、链接、图片等信息最后保存成CSV文件test-1.csv、test-2.csv或纯文本lines.txt、test.txt。里面包含豆瓣读书简介抓取、新东方教师头像批量下载、Glassdoor城市职位分布统计、Merkle树图片采集等真实小场景脚本还覆盖基础语法实践字符串处理、列表/元组/字典操作、条件判断、循环遍历、函数封装、CSV文件读写、简单数据库交互。所有脚本依赖少仅requests、beautifulsoup4等主流轻量库环境配置简单适合新手边敲边理解每个环节怎么衔接——比如怎么把response.text变成表格字段怎么跳过空标签、处理编码异常、模拟浏览器请求头、控制请求节奏。代码不含复杂框架或异步逻辑专注讲清采集链路的核心步骤。注意仅供学习参考使用前请务必查阅目标网站robots.txt、服务条款确保数据获取行为合法合规。本文还有配套的精品资源点击获取