
1. 先聊聊爬虫新手为什么越学越懵前几天我朋友转给我一个网盘链接里面存了十几个G的“Python爬虫全套教程”问我该从哪一部开始看。我翻了翻目录发现第一节课教的是Scrapy框架第二节课教的是分布式爬虫第三节课已经开始教怎么爬短视频平台的评论区了。我当时的反应是这哪是新手路线这分明是把新手往火坑里推。这不是个例。市面上绝大多数爬虫教程要么一上来就堆框架要么动不动就搞分布式、逆向、JS混淆看起来高大上实际上把最基本的“怎么把网页内容拿回来、怎么把数据摘出来、怎么存下来”这三件事全跳过了。Python爬虫入门最常见的失败原因根本不是代码写不出来而是方向选错导致学了两周还在复制粘贴别人的代码换个网站就抓瞎。2026年了Web前端技术的迭代速度比前几年更快页面越来越多地依赖JavaScript动态渲染反爬机制也越来越成熟。但新手需要明白一个道理不管技术怎么变爬虫的底层能力始终只有三块。一是发送请求拿到响应二是从响应里精准提取目标数据三是管理好访问节奏和身份信息让自己不被封、不误伤对方服务器。这三块能力练扎实后面学Scrapy、异步、分布式、逆向都是水到渠成的事这三块没练好就算把框架API背得滚瓜烂熟遇到一个稍微有点反爬的网站照样寸步难行。这篇文章我就围绕这三块核心能力展开每个部分都会讲清楚“为什么这样做”和“实际会踩什么坑”最后用一个可以直接运行的完整案例收尾。内容不追求炫技只追求让零基础的人看完之后能真正跑通自己的第一个爬虫。2. 核心技能一把“拿到页面”这件事做扎实2.1 请求库选择requests、httpx还是curl_cffi很多新手第一个接触的请求库是requests这个选择本身没错requests的API设计非常人性化一行代码就能拿到页面内容是打基础的绝佳工具。但到了2026年我建议你在入门阶段就把httpx也一起学了原因很简单requests在同步请求场景下足够用但httpx同时支持同步和异步而且对HTTP/2的原生支持比requests更友好。部分反爬网站已经通过HTTP/2指纹识别来拦截纯requests请求这种情况在某些小众站点上越来越常见。这里插一句如果你只是练手requests完全够用。我自己的习惯是requests负责“快速验证能不能拿到数据”httpx负责“需要并发或遇到HTTP/2问题时替换过去”。两个库的语法相似度很高基本是改个名就能跑所以不存在“学了一个就用不了另一个”的情况。至于curl_cffi它是一个模拟浏览器TLS指纹的库适合那些对请求库指纹检测很严格的场景。新手阶段我不建议一上来就依赖它因为它掩盖了“为什么requests会被识别”这个核心问题。先学会用普通请求库等遇到真实的指纹校验时再引入它理解会更深刻。2.2 响应对象里的隐藏信息不只是text拿到response之后新手最常见的操作是直接打印response.text看到一堆HTML就觉得自己成功了。但这里有个严重的隐患你看到的这串内容很可能不是浏览器里真正显示的内容。原因在于很多网站返回的是压缩后的响应或者采用动态渲染初始HTML里根本没有数据。我处理爬虫时有个习惯拿到响应后先看四样东西。第一是status_code200只代表服务器有响应不代表数据有效很多网站对异常请求返回200但内容是一个验证页。第二是response.headers里的content-type和content-encoding这决定了你怎么解码。第三是response.encoding乱码问题十有八九出在这试着用response.encoding utf-8或根据headers里的charset指定编码。第四是response.url有时候你请求的是A地址最终被重定向到了B地址如果不关注这个后面所有解析都会出错。我见过太多新手卡在“明明复制了浏览器里的请求地址但爬回来是乱码”这个问题上最后发现就是编码设置不对。学会通过response对象自带的属性去诊断问题比背任何教程都有用。2.3 请求头不是玄学UA、Referer与Cookie的真正作用新手群里经常流传一个说法“必须带上User-Agent否则会被封。”这话对但不完整。User-Agent只是最基础的身份标识很多网站还会看Referer、Origin、Cookie甚至浏览器指纹。如果你从浏览器开发者工具里看到某个请求成功返回了200那就把请求头里比较关键的几个字段都复制过来尤其是User-Agent、Referer、Cookie这三个。我自己在调试阶段的习惯是先用浏览器正常访问目标页面打开开发者工具找到那个真正返回数据的请求右键复制为cURL命令再粘贴到调试工具里转成Python代码。这样做的好处是请求头几乎不会漏能最大程度复现浏览器的请求环境。新手不用觉得这很作弊这本来就是逆向工程的基础思路——你是在模仿一个正常用户而不是在硬碰硬攻击服务器。这里要特别提醒一个认知问题。很多人一提到Cookie就紧张觉得那是“黑客才用的东西”。其实Cookie就是服务器放在你浏览器里的一张身份卡爬虫带上它和你在浏览器里登录后继续访问本质目的是一样的都是为了维持会话状态。只要你不尝试窃取他人的Cookie、不越权访问未授权数据单纯使用自己登录态里的Cookie是合规且常见的开发行为。3. 核心技能二从HTML里精准“切”出你要的数据3.1 三种解析方案别一上来就学正则拿到页面内容之后下一步就是把目标数据提取出来。新手最容易掉进去的坑是正则表达式。正则强不强强但它是纯文本匹配工具面对结构清晰但层级嵌套的HTML时写起来又长又容易出错。我见过的极简爬虫教程里十有八九在用正则抓数据可那只是因为它看起来“一行代码就搞定”并不是因为它适合HTML解析。我建议新手的优先级顺序是XPath等于CSS选择器然后是BeautifulSoup最后才是正则。前两种是面向HTML结构的查询语言代码写出来可读性好修改也方便。第三种适合兜底比如从一段JavaScript变量里抽文本这种场景XPath和CSS确实无能为力。以XPath为例你用//div[classitem]就可以选中页面上所有class为item的div块然后再配合.//span[contains(class, title)]从每个块里提取标题信息。这种思路一旦建立起来解析逻辑会变得非常清晰先定位到包含数据的容器再逐层向内提取字段而不是在整篇HTML里大海捞针。3.2 XPath与CSS选择器的基本功怎么练最有效我曾被问过无数次“XPath和CSS选择器该学哪个”答案是两个都该会因为有些页面结构更适合XPath有些更适合CSS实际情况里经常混着用。但入门阶段我强烈建议先死磕XPath。为什么因为XPath除了支持class、id选择还支持“根据元素文本内容”定位比如//a[contains(text(), 下一页)]这在翻页场景里极其好用。而CSS选择器虽然简洁但在动态加载的页面里能定位的属性往往不够用。练法也很简单打开浏览器的开发者工具在Elements面板里对着某个元素右键选择Copy再选择Copy XPath或Copy selector然后粘贴到你的解析代码里跑一下。这个动作看似机械但多试几次你就会发现浏览器生成的XPath往往很长且泛化性差你会自然地去手动精简它真正理解“层级定位”的内涵。我自己的习惯是拿到一个数据时先把目标元素在页面上找到然后用XPath的contains和位置索引来写一个尽量通用的表达式这样即使页面结构发生小范围变化代码也不容易挂。3.3 别忽略数据清洗提取到的是字符串不是答案很多新手走到“成功打印出目标内容”这一步就开始欢呼但接下来往往遇到更尴尬的事数据里混着换行符、空格、广告词或者金额带了单位、日期格式不统一。这时候你才意识到解析只是第一步清洗同样重要。清洗这块没有统一标准但有几个高频处理动作可以提前掌握。一是用strip()去掉字符串首尾空白二是用正则把数字从混着“元”、“¥”等符号的文本中抠出来三是用replace把不需要的杂质替换掉四是用datetime库把“2026-01-15”这类字符串转成真正的日期对象。听起来琐碎但这些操作在真实项目里能占掉你40%的调试时间。我建议新手在写解析代码的时候顺手就把每个字段的预期类型和格式写在注释里比如“发布时间字符串格式为yyyy-mm-dd”。这样你在清洗数据时就有据可依而不是等数据处理到一半才反应过来某字段格式不对。4. 核心技能三请求节奏与会话保持让爬虫像个正常用户4.1 为什么“爬得快”不是本事“爬得稳”才是新手拿到爬虫代码后第一个冲动是“赶紧跑跑得越快越好”。结果往往是对面服务器直接给你返回一片验证码或者一个“拒绝访问”页面。这不是服务器歧视你而是你的访问行为太不像人了。一个正常用户就算再手速快也不可能在同一秒内连续请求20个不同页面。服务器检测爬虫最基础的手段就是频率统计短时间内大量请求来自同一个IP、同一个会话就会被自动标记。所以控制请求间隔是爬虫开发里最朴素但也最有效的反反爬手段。我的习惯是在循环请求里至少加1到3秒的随机延时用time.sleep(random.uniform(1, 3))原因不只是降低请求频率更在于让访问间隔呈现出人类操作的“不规则性”。定时器写得像机器一样精准每个请求间隔都恰好2秒反而更容易被识别。4.2 Session、Cookie和请求顺序三个最容易忽视的细节很多静态页面其实不需要登录就能直接抓但一旦涉及“登录后可见”“分页加载依赖Token”这些场景你就必须理解Session和Cookie的作用。简单说Session是你在客户端保存的一组会话信息它内部自动帮你维护Cookie。如果你每次都用requests.get来请求而不是先创建session requests.Session()那就等于每次访问都是一个全新用户服务器无法把你前面的登录状态关联起来。新手最常犯的错误就是从浏览器里复制了Cookie然后硬编码到代码里结果Cookie过期之后整个爬虫报废。正确的做法是如果目标站点允许优先用“账号密码登录后获取Cookie”的方式把session对象用起来如果只是临时调试再从浏览器复制Cookie填进去同时做好“Cookie可能失效”的心理准备。请求顺序同样重要有些页面对前一个页面的访问路径有依赖比如你必须先访问首页拿到初始Cookie再访问目标接口否则就会返回空数据。这听起来不讲道理但在实际网站里非常常见。4.3 遇到验证码和风控最聪明的应对是“绕开”2026年的网站风控水平已经比几年前高了很多滑块验证码、行为验证、无感验证满天飞。新手如果在练手阶段碰到这些我真心建议不要硬碰硬。破解验证码是一个独立的技术方向涉及图像识别、轨迹模拟、机器学习甚至打码平台这不是爬虫入门阶段该面对的事情。更合理的思路是换一个更友好的目标网站来练手。比如一些公开的新闻门户、天气接口、政府公开数据平台这些站点对爬虫的容忍度比较高适合新手把请求、解析、存储这套流程跑通。等你对爬虫的基本功扎实了再来研究验证码和加密参数的逻辑那叫技术进阶什么都没学会就去研究验证码那叫自我折磨。还有个细节要提醒如果某个网站的robots协议里明确写了禁止爬取或者页面底部有“禁止采集”的声明那就不要拿它当实验对象。爬虫这个技术本身不是灰色地带但前提是你只访问公开、允许访问的数据不影响对方服务器的正常运转。5. 一个完整的练手项目抓取公开列表页并保存到Excel5.1 动手之前先用伪代码把流程理清楚很多新手拿到需求就直接写代码写到一半发现数据取不出来又回去看页面结构来回折腾半天。我的习惯是先花5分钟写伪代码把完整流程拆成几个动作确认每个动作的输入输出是什么。假设我们现在要爬取一个公开的新闻列表页目标是提取每条新闻的标题、链接和发布时间最后保存到Excel里。伪代码可以这样写第一步请求列表页HTML 第二步解析HTML取出新闻条目容器 第三步遍历每个容器提取标题、链接、时间 第四步把数据写入Excel文件就这么四句话看起来简单但它能帮你强制思考一个关键问题我到底是从一个接口拿JSON还是要从HTML页面里解析如果页面数据是接口返回的JSON那解析方式完全不同。很多新手在“解析错误”上浪费的时间其实都源于没想清楚这个问题。5.2 代码实现requests、lxml和openpyxl的协作下面这段代码是我平时给新手演示的模板结构非常清晰你完全可以把它当作自己第一个爬虫的骨架。这里以lxml配合XPath为例因为它定位速度快语法也直观。import time import random import requests from lxml import html from openpyxl import Workbook url https://example.com/news # 替换为你实际要爬的公开页面 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://example.com } session requests.Session() resp session.get(url, headersheaders) resp.encoding utf-8 if resp.status_code 200: root html.fromstring(resp.text) # 假设每条新闻都在 class 为 news-item 的 div 中 items root.xpath(//div[contains(class, news-item)]) rows [] for item in items: title item.xpath(.//a/text())[0].strip() link item.xpath(.//a/href)[0].strip() publish_time item.xpath(.//span[classdate]/text())[0].strip() rows.append([title, link, publish_time]) print(f已提取: {title} | {publish_time}) wb Workbook() ws wb.active ws.title 新闻列表 ws.append([标题, 链接, 发布时间]) for row in rows: ws.append(row) wb.save(news.xlsx) print(f共保存 {len(rows)} 条数据到 news.xlsx) else: print(f请求失败状态码: {resp.status_code})这段代码有几个地方值得单独说。一是enconding的设置如果你发现中文变成乱码第一反应就是去看页面meta标签里的charset改成对应的编码。二是XPath表达式里的[0]这是取第一个命中节点因为text()返回的是一个列表如果你确定只有一个直接取[0]最方便。三是为什么用session而不是直接用requests.get因为session能自动管理后续请求的Cookie虽然这个案例里可能用不上但养成这个习惯对后续学习很重要。5.3 存储到Excel时别忽略数据类型把数据存到Excel看起来很简单openpyxl几行代码就解决了但我遇到过很多新手做出来的表没法用原因有两个。第一个原因是所有字段都是字符串日期不能参与排序数字不能做计算。所以在写入Excel之前尽量把字段转换成正确类型。比如发布时间的格式如果是“2026-02-10”你可以先用datetime.strptime(publish_time, %Y-%m-%d)转成日期对象再写入这样Excel里就可以按日期排序和筛选了。第二个原因是空值处理。如果某一行的标题为空XPath的[0]会直接抛IndexError而不是给你一个空字符串。这算是新手最容易遇见的坑。解决办法是在提取时加一个判断或者用try/except把异常抓住把对应字段填充成空字符串。代码多两行但稳定性提升很明显。6. 新手避坑速查表与进阶路线6.1 高频Bug排查清单直接对着找原因我在带新手的过程中发现很多报错反复出现于是整理了一份排查清单。遇到问题时先对照这个表往往比漫无目的地搜“爬虫报错”更高效。现象常见原因排查方向返回的HTML是乱码编码设置与页面实际编码不一致查看页面charset设置response.encoding明明能访问页面但代码返回403缺少关键请求头或请求身份异常补充User-Agent、Referer、CookieXPath拿不到任何元素页面数据是动态渲染的或表达式写错换成Selenium/Playwright或先用浏览器验证XPath第一页正常后面页没数据翻页参数没带上或者链接拼接错误对比浏览器第二页的请求URL与代码中的URL爬一会儿就被封请求频率过高增加随机延时降低并发写入Excel时中文乱码openpyxl一般不会乱码但CSV会CSV保存时指定utf-8-sig编码目标又名叫“验证码”频繁触发对方风控换站点练手或减少请求量这张表的价值在于它把散落在各种报错里的经验集中到了一起。我建议你把它收藏下来每次遇到问题先来这里对照一遍基本上能解决80%的新手期烦恼。6.2 学完这三个核心技能之后下一步怎么走如果你把上面这三块能力都练扎实了大概需要一个月左右的时间每天投入两小时。到了这个阶段你已经能做到看到任意一个静态页面能快速分析出数据结构写出请求和解析代码把结果保存成本地文件。接下来再学什么就不该由别人替你拍脑袋决定了而应该看你的目标是什么。如果你想去企业做数据采集方向的工作那建议开始系统学习Scrapy框架和分布式采集因为生产环境更看重工程化能力和调度效率。如果你只是想做个人数据分析项目那建议学一下Pandas和异步请求把数据清洗和批量抓取串到一起效率会高很多。如果你对Web安全感兴趣再往逆向、混淆对抗的方向深入学习但这已经不是爬虫入门范畴而是独立的细分领域。我自己更推荐第二条路因为对多数人来说爬虫是获取数据的手段而不是目的。数据拿到手能解决实际问题和创造价值才是最重要的。很多人纠结“我用requests就够了为什么还要学Scrapy”这种问题不用纠结你的实际项目会告诉你答案——当你有天需要一次性爬几万个页面的时候自然就明白框架存在的意义了。最后再分享一点我个人的坚持也算是踩过不少坑之后的体会写爬虫时始终留一个字段记录数据抓取的时间并给自己的代码加上简单的日志输出。这样做不是为了在朋友圈展示专业度而是当数据出问题时你能一眼定位是哪一步、哪个时间点开始出错的。这个习惯的成本几乎为零但价值极高尤其是当你开始跑长时间任务时它甚至能帮你避免“跑了两小时结果全部是脏数据”的灾难。