新手常犯的 5 个爬虫错误,你中招了吗?

刚接触爬虫时,很多人会觉得 “不就是写几行代码抓数据吗?”—— 但真正上手才发现,要么爬不到数据,要么代码跑一半崩了,甚至 IP 直接被目标网站拉黑。其实,这些问题大多不是因为技术难度,而是新手容易忽略的 “基础坑”。今天就来盘点 5 个最常见的爬虫错误,看看你有没有踩过,以及该怎么避开。
错误 1:无视 Robots 协议,踩线法律与道德红线
很多新手拿到一个目标网站,二话不说就写代码发起请求,却完全没注意网站的 “访问规则”——Robots 协议(也叫机器人协议)。这不仅是 “不礼貌”,严重时可能触及法律风险。
为什么这是坑?
Robots 协议是网站通过根目录下的robots.txt文件(比如百度的https://www.baidu.com/robots.txt),明确告诉爬虫 “哪些内容可以爬,哪些不能爬,爬的频率不能超过多少”。新手忽略它,可能会:
- 爬取网站禁止的敏感数据(如用户隐私、付费内容),违反《网络安全法》《数据安全法》;
- 即使爬公开内容,也可能因 “未遵守规则” 被网站判定为 “恶意爬虫”,直接封禁 IP。
怎么改?
- 爬之前先查 Robots 协议:在目标网站域名后加
/robots.txt,比如想爬知乎就看https://www.zhihu.com/robots.txt; - 严格遵守协议指令:比如协议写
Disallow: /api/v4/,就绝对不要爬/api/v4/开头的接口; - 即使协议允许,也别 “得寸进尺”—— 比如协议没限制频率,也别每秒发 10 个请求,给服务器留缓冲。
错误 2:不伪装请求头,被网站 “一眼识别” 为爬虫
新手最常遇到的问题之一:代码没报错,但返回的内容是空的,或者直接提示 “403 Forbidden”(禁止访问)。这大概率是因为没做 “请求伪装”,被网站轻松识破是爬虫。
为什么这是坑?
浏览器发起请求时,会附带User-Agent(浏览器标识)、Cookie等 “请求头信息”,告诉网站 “我是真实用户在浏览”。而新手直接用requests.get(url)发起请求,默认的User-Agent是 “python-requests/2.28.1”—— 网站一看就知道 “这是爬虫,拒绝!”。
比如你爬知乎时,没加请求头的代码可能是这样:
python
import requests url = "https://www.zhihu.com/question/123456" response = requests.get(url) print(response.text) # 结果可能是403页面,或者空内容 怎么改?
给请求加 “伪装头”,核心是补全User-Agent,复杂场景可加Cookie(模拟登录状态):
- 从浏览器复制真实
User-Agent:打开浏览器 F12→Network→随便点一个请求→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; - 用字典传入请求头:
python
import requests 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", "Cookie": "你的Cookie(可选,爬需要登录的内容时加)" } url = "https://www.zhihu.com/question/123456" response = requests.get(url, headers=headers) print(response.text) # 现在能拿到正常页面内容了 - 进阶技巧:用
fake-useragent库生成随机User-Agent,避免单一标识被封。
错误 3:数据存储混乱,爬完 “没法用”
新手往往只关注 “能不能爬到数据”,却忽略了 “爬到后怎么存”—— 要么存成杂乱的 TXT 文件,要么字段错位,等后期想分析数据时,发现根本没法筛选、查询。
为什么这是坑?
比如爬商品数据时,新手可能直接把 “商品名 + 价格 + 链接” 用逗号拼接存 TXT:
plaintext
手机A,2999,https://xxx.com/1 手机B,3999(缺货),https://xxx.com/2 后期想筛选 “价格低于 3000 的商品”,还要手动处理 “(缺货)” 这样的干扰内容;如果爬 10 万条数据,TXT 文件打开都要半天,更别说分析了。
怎么改?
根据数据量和用途选合适的存储方式,核心是 “结构化存储”:
- 小数据(几百条):用 Excel(
pandas库的to_excel方法),字段明确(商品名、价格、链接、库存),方便筛选; - 中大数据(几千到几十万条):用数据库,比如 MongoDB(存 JSON 格式,字段灵活)、MySQL(结构化强,支持复杂查询);
- 示例(用 pandas 存 Excel):
python
import pandas as pd # 爬取到的商品数据,用列表+字典存(结构化) goods_data = [ {"商品名": "手机A", "价格": 2999, "链接": "https://xxx.com/1", "库存": "有货"}, {"商品名": "手机B", "价格": 3999, "链接": "https://xxx.com/2", "库存": "缺货"} ] # 存成Excel df = pd.DataFrame(goods_data) df.to_excel("商品数据.xlsx", index=False) # index=False去掉行号 错误 4:不处理异常,代码 “一崩全没”
新手写的爬虫,经常遇到 “爬了一半突然报错,之前爬的数据全丢了”—— 比如网络波动导致请求超时、页面结构变了导致 XPath 找不到内容、服务器突然返回 500 错误…… 这些 “异常情况”,新手往往没做任何处理,代码直接崩溃。
为什么这是坑?
比如你爬 100 页商品,爬到第 50 页时网络断了,代码没处理 “请求超时”,直接抛出requests.exceptions.Timeout错误,停止运行。不仅第 50 页的数据没拿到,之前 49 页的数据如果没实时保存,也可能丢失。
怎么改?
用try-except捕获异常,再加 “重试机制”,确保代码 “能扛住小问题”:
- 捕获常见异常:请求超时、连接错误、XPath 解析失败等;
- 重要数据实时保存:爬一条存一条,别等全部爬完再存;
- 示例(带异常处理和重试):
python
import requests from tenacity import retry, stop_after_attempt, wait_exponential # 第三方库,处理重试 headers = {"User-Agent": "你的UA"} # 重试机制:最多重试3次,每次等待时间翻倍(1s→2s→4s) @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10)) def get_page(url): try: response = requests.get(url, headers=headers, timeout=10) # 超时时间10s response.raise_for_status() # 若返回4xx/5xx错误,抛出异常 return response.text except requests.exceptions.Timeout: print(f"请求{url}超时,重试中...") raise # 抛出异常,让retry装饰器重试 except requests.exceptions.HTTPError as e: print(f"请求{url}失败:{e},跳过该页") return None # 跳过错误页面,不重试 # 爬100页 for page in range(1, 101): url = f"https://xxx.com/goods?page={page}" page_content = get_page(url) if page_content: # 解析数据、保存数据(此处省略解析代码) print(f"第{page}页爬取成功") else: print(f"第{page}页爬取失败,跳过") 错误 5:过度请求无节制,IP 被封 “爬不了”
新手想快速爬完数据,会写一个 “无延时” 的循环:比如每秒爬 10 页,甚至用多线程同时发几十条请求。结果往往是 —— 爬了几分钟,IP 就被网站拉黑,之后再访问该网站,无论是爬虫还是浏览器,都显示 “无法访问”。
为什么这是坑?
网站的服务器承载能力有限,短时间内大量请求会被判定为 “恶意攻击”(比如 DDoS)。为了保护服务器,网站会直接封禁发起请求的 IP,少则几小时,多则永久封禁。
怎么改?
核心是 “模拟真实用户行为,控制请求频率”:
- 加延时:用
time.sleep()在每次请求后停 1-3 秒,比如time.sleep(random.uniform(1, 3))(随机 1-3 秒,更真实); - 用代理 IP 池:如果需要快速爬取,单 IP 不够用,就用代理 IP 轮换请求(注意选高匿代理,避免被识破);
- 用 Session 保持连接:用
requests.Session()代替requests.get(),复用 TCP 连接,减少对服务器的压力; - 示例(加延时 + Session):
python
import requests import time import random headers = {"User-Agent": "你的UA"} session = requests.Session() # 建立会话,复用连接 for page in range(1, 101): url = f"https://xxx.com/goods?page={page}" response = session.get(url, headers=headers) # 解析、保存数据(省略) print(f"第{page}页爬取成功") # 随机延时1-2秒 time.sleep(random.uniform(1, 2)) 最后:爬虫的核心不是 “偷数据”,而是 “合规地拿数据”
新手踩坑的本质,往往是 “只关注技术实现,忽略了规则和细节”。其实爬虫不难,但想做好,需要记住:网站是数据的所有者,我们是 “访客”,要守规矩、讲礼貌。
避开上面这 5 个错误,你就能解决 80% 的入门问题。如果还遇到其他坑(比如动态渲染页面爬不到、验证码过不去),也不用慌 —— 这些都是进阶问题,慢慢学习Selenium、Playwright或验证码识别工具就能解决。
你在爬虫入门时还遇到过哪些 “奇葩坑”?欢迎在评论区分享,一起避坑~