本文从零开始系统讲解网络爬虫的原理、常用方法、网站常见的反爬手段,以及应对反爬的思路。文中所有代码与技术仅用于学习与合法的数据采集,请务必在合法合规的前提下使用(文末有专门的法律与道德说明)。
一、什么是网络爬虫
网络爬虫(Web Crawler / Web Spider),又叫网页蜘蛛、网络机器人,本质上是一段自动化访问网页并提取数据的程序。
我们平时用浏览器上网,做的事情其实是:
- 在地址栏输入一个网址(URL);
- 浏览器向服务器发送一个 HTTP 请求;
- 服务器返回 HTML、CSS、JS、图片等资源;
- 浏览器把这些资源渲染成我们看到的页面。
爬虫做的事情和浏览器几乎一样,区别在于:浏览器把数据渲染给人看,而爬虫把数据抓回来交给程序处理。所以可以一句话概括:
爬虫 = 模拟浏览器发请求 + 从返回的内容里提取出你需要的数据。
常见的应用场景包括:搜索引擎收录网页、电商比价、舆情监控、学术数据采集、自己做数据分析的练手项目等等。
二、爬虫的基本工作流程
无论用什么语言、什么框架,一个爬虫基本都逃不开这四步:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 1. 发请求 │ → │ 2. 拿响应 │ → │ 3. 解析 │ → │ 4. 存储 │
│ URL │ │ HTML/JSON│ │ 提取数据 │ │ 落地保存 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
- 发起请求:构造 URL 和请求头,向目标服务器发送请求。
- 获取响应:服务器返回内容,可能是 HTML 页面,也可能是 JSON 数据。
- 解析提取:从返回内容里把你关心的字段抠出来(标题、价格、链接......)。
- 数据存储:把提取到的数据存进文件、数据库或表格。
理解了这个流程,后面所有的工具其实都是在帮你更好地完成其中某一步。
三、爬虫常用方法与工具
下面以 Python 为例(Python 是爬虫最主流的语言,生态最完善),介绍几类核心工具。
3.1 发请求:requests 库
requests 是最常用、最简单的 HTTP 请求库。
python
import requests
url = "https://example.com"
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, headers=headers, timeout=10)
print(resp.status_code) # 200 表示成功
print(resp.text[:500]) # 打印前 500 个字符的 HTML
发送带参数的请求(GET 和 POST):
python
# GET 带查询参数
params = {"page": 1, "keyword": "python"}
resp = requests.get(url, params=params, headers=headers)
# POST 提交表单
data = {"username": "test", "password": "123456"}
resp = requests.post(url, data=data, headers=headers)
3.2 解析:BeautifulSoup / lxml / 正则
拿到 HTML 后,需要从中提取数据。常用三种方式:
① BeautifulSoup(适合新手,可读性强)
python
from bs4 import BeautifulSoup
html = resp.text
soup = BeautifulSoup(html, "lxml")
# 按标签和 class 提取
title = soup.find("h1", class_="article-title").text.strip()
# 提取所有链接
for a in soup.find_all("a"):
print(a.get("href"), a.text)
② XPath(lxml,定位精准,适合复杂结构)
python
from lxml import etree
tree = etree.HTML(resp.text)
titles = tree.xpath('//h2[@class="title"]/text()')
links = tree.xpath('//a/@href')
③ 正则表达式(灵活但脆弱,适合简单提取)
python
import re
# 提取所有邮箱
emails = re.findall(r'[\w.-]+@[\w.-]+\.\w+', resp.text)
经验之谈:结构化页面优先用 XPath 或 BeautifulSoup,正则只在万不得已或目标特别简单时用,否则页面一改正则就废了。
3.3 动态页面:Selenium / Playwright
现在很多网站的数据不是直接写在 HTML 里,而是页面加载后由 JavaScript 动态请求生成的。用 requests 抓回来的可能是一个"空壳"。这时有两条路:
路线 A:找到背后的接口(推荐,效率高)
打开浏览器开发者工具(F12)→ Network → XHR/Fetch,往往能看到页面真正请求数据的 API,直接请求这个接口拿 JSON 即可(见 3.4)。
路线 B:用浏览器自动化工具,让真实浏览器跑起来
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com")
page.wait_for_selector(".content") # 等待数据加载
html = page.content() # 拿到渲染后的完整 HTML
browser.close()
Selenium 和 Playwright 都能驱动真实浏览器,好处是"所见即所得",缺点是慢、占资源。能找接口就别开浏览器。
3.4 直接调用接口(API):最高效的方式
如果能在开发者工具里找到返回 JSON 的接口,直接请求是最干净高效的做法:
python
api_url = "https://example.com/api/list"
params = {"page": 1, "size": 20}
resp = requests.get(api_url, params=params, headers=headers)
data = resp.json() # 直接得到 Python 字典/列表
for item in data["list"]:
print(item["title"], item["price"])
3.5 爬虫框架:Scrapy
当项目变大(要爬成千上万页、需要去重、并发、断点续爬),手写脚本就力不从心了。Scrapy 是一个成熟的异步爬虫框架,内置了请求调度、并发控制、数据管道、中间件等机制。
一个最小的 Scrapy 爬虫:
python
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com"]
def parse(self, response):
for quote in response.css("div.quote"):
yield {
"text": quote.css("span.text::text").get(),
"author": quote.css("small.author::text").get(),
}
# 自动翻页
next_page = response.css("li.next a::attr(href)").get()
if next_page:
yield response.follow(next_page, self.parse)
quotes.toscrape.com是一个官方提供的合法练习站点,新手强烈建议拿它练手。
四、常见的反爬技术
网站为了保护数据、减轻服务器压力、防止内容被恶意抓取,会部署各种反爬手段。了解它们,既是为了让正当爬虫"更像正常用户",也是为了理解网站的安全设计思路。
4.1 请求头(Headers / User-Agent)检测
最基础的反爬。服务器检查请求头里的 User-Agent、Referer、Accept 等字段。如果发现是 Python 默认的 UA(如 python-requests/2.x),直接拒绝。
4.2 IP 与访问频率限制
同一个 IP 短时间内请求太多次,服务器会判定为机器行为,进行限流、临时封禁或返回验证码。这是最常见、最有效的反爬手段之一。
4.3 Cookie / Session / Token 校验
很多页面要求登录后才能访问,或要求请求里携带特定的 Cookie、Token。没有有效凭证就拿不到数据。
4.4 验证码(CAPTCHA)
当系统怀疑你是机器人时,弹出图形验证码、滑块验证、点选文字、行为验证(如 reCAPTCHA、各类滑动拼图)等,用来区分人和机器。这是网站重要的安全防线。
4.5 JavaScript 动态渲染与数据加密
数据不直接出现在 HTML 里,而是通过 JS 异步加载,甚至请求参数和返回数据都经过加密/混淆。直接抓 HTML 拿不到东西。
4.6 字体反爬(自定义字体映射)
页面用自定义字体文件,把真实数字/文字映射成乱码。例如你看到的是"价格 ¥38",但 HTML 源码里其实是一串编码,只有配合特定字体文件才能正确显示。常见于一些点评、招聘、票务类网站。
4.7 参数签名 / 加密
请求里带有一个由前端 JS 算出来的签名参数(如 sign、token、时间戳 + 密钥),服务器校验签名是否合法,防止别人随意构造请求。
4.8 行为检测与蜜罐
- 行为检测:分析鼠标轨迹、点击间隔、滚动行为,判断是不是真人。
- 蜜罐(Honeypot) :在页面里放一些人眼看不见但爬虫会抓到的隐藏链接,一旦程序访问了这些链接,立刻判定为爬虫并封禁。
五、应对反爬的常见思路(反反爬)
理解反爬之后,正当爬虫的核心目标其实只有一个:尽量让自己的请求行为接近一个真实、礼貌的用户。下面是常见思路,请始终在合法合规前提下使用。
5.1 伪装请求头
补全 User-Agent、Referer 等字段,模拟真实浏览器。还可以维护一个 UA 池随机切换:
python
import random
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Safari/605.1.15",
"Mozilla/5.0 (X11; Linux x86_64) ... Firefox/121.0",
]
headers = {
"User-Agent": random.choice(user_agents),
"Referer": "https://example.com/",
"Accept-Language": "zh-CN,zh;q=0.9",
}
5.2 控制频率 + 随机延时(最重要也最该做的事)
不要疯狂请求。加入随机延时,既能避开频率限制,更是对目标服务器的基本尊重------别把人家服务器爬挂了。
python
import time
import random
for url in url_list:
resp = requests.get(url, headers=headers)
# 处理数据 ...
time.sleep(random.uniform(1, 3)) # 随机停 1~3 秒
5.3 使用代理 IP
当单 IP 被限频时,可以通过代理 IP 池分散请求来源:
python
proxies = {
"http": "http://用户名:密码@代理IP:端口",
"https": "http://用户名:密码@代理IP:端口",
}
resp = requests.get(url, headers=headers, proxies=proxies, timeout=10)
注意:请使用正规渠道购买的合法代理服务。同时再次强调,代理是用来分散正常采集压力的,不是用来突破网站明确禁止访问的限制。
5.4 维持会话与登录态
用 requests.Session 自动管理 Cookie,模拟登录后的连续访问:
python
session = requests.Session()
session.headers.update(headers)
# 先登录(拿到 Cookie)
session.post("https://example.com/login", data={"user": "...", "pwd": "..."})
# 后续请求自动携带 Cookie
resp = session.get("https://example.com/profile")
仅对你自己拥有合法访问权限的账号这样做,不要尝试爬取需要他人授权才能访问的私密数据。
5.5 应对 JS 渲染
如前所述,两条路:
- 首选:分析 Network 面板,找到真实数据接口,直接请求 JSON;
- 兜底:用 Playwright / Selenium 驱动真实浏览器渲染后再取数据。
5.6 应对加密参数(逆向分析,概念层面)
对于带签名/加密参数的接口,技术上的做法是通过浏览器调试,定位到生成该参数的 JS 函数,理解其算法后在程序中复现。这属于前端逆向 范畴,难度较高,且很多网站的服务条款明确禁止此类行为。这里只做概念性说明:
- 知道有这么个技术方向即可;
- 是否进行,要先看目标网站的
robots.txt和用户协议; - 涉及破解他人安全/加密机制时,往往已经踩到法律红线,请务必谨慎。
5.7 关于验证码
验证码是网站为区分人机、保护安全而设置的防线。实践中存在 OCR 识别、打码平台等技术,但绕过验证码本质上是在突破网站的安全机制。我的建议很明确:
- 如果一个网站用验证码明确表示"不希望被自动化访问",最稳妥的做法是尊重它,不要硬爬;
- 很多时候你想要的数据,其实有官方开放 API 或公开数据集可用,那才是正路;
- 强行绕过安全验证不仅技术上不稳定,更可能违反法律和服务条款。
一句话原则:反爬越强,越说明对方不欢迎自动化访问。这时候该想的不是"怎么破",而是"我是不是该换条合法的路"。
六、一个完整的实战小例子
下面用官方练习站点 quotes.toscrape.com 演示一个完整流程:抓取名言、作者,并存成 CSV。
python
import requests
from bs4 import BeautifulSoup
import csv
import time
import random
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"
}
base_url = "https://quotes.toscrape.com/page/{}/"
results = []
for page in range(1, 6): # 爬前 5 页
url = base_url.format(page)
resp = requests.get(url, headers=headers, timeout=10)
if resp.status_code != 200:
break
soup = BeautifulSoup(resp.text, "lxml")
quotes = soup.find_all("div", class_="quote")
if not quotes:
break
for q in quotes:
text = q.find("span", class_="text").text.strip()
author = q.find("small", class_="author").text.strip()
results.append({"text": text, "author": author})
time.sleep(random.uniform(1, 2)) # 礼貌延时
# 存成 CSV
with open("quotes.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["text", "author"])
writer.writeheader()
writer.writerows(results)
print(f"共抓取 {len(results)} 条数据,已保存到 quotes.csv")
跑通这个例子,你就基本掌握了"发请求 → 解析 → 翻页 → 存储"的完整闭环。
七、法律与道德边界(请认真读)
爬虫技术本身是中性的,但怎么用决定了它是工具还是凶器。下面几条务必牢记:
-
遵守 robots.txt :网站根目录下的
robots.txt(如https://example.com/robots.txt)声明了哪些路径允许/禁止爬取。它虽不是法律,但代表网站的明确意愿,应当尊重。 -
遵守服务条款(ToS):很多网站的用户协议明确禁止自动化抓取,违反可能构成违约甚至侵权。
-
不爬取个人隐私和敏感数据:姓名、电话、身份证、住址、人脸等个人信息受法律严格保护(如中国《个人信息保护法》《数据安全法》,欧盟 GDPR 等)。
-
控制频率,不影响网站正常运行:高频爬取导致对方服务器瘫痪,可能涉及破坏计算机信息系统等法律责任。
-
尊重版权与数据所有权:抓来的数据用于个人学习是一回事,未经授权商用、转售、二次发布是另一回事。
-
不破解、不绕过安全机制:突破登录验证、加密、验证码等安全措施,在很多司法辖区可能触犯法律。
真实世界里,因为违规爬虫被起诉、被判刑、公司被罚的案例并不少见。 技术能做到,不代表法律允许你做。学技术的同时,请同步建立合规意识。
合规采集的优先级建议:
官方 API > 公开数据集 > robots.txt 允许范围内的公开页面 >(其余请三思而后行)
八、学习路线建议
如果你刚入门,建议按这个顺序循序渐进:
- 打基础:HTTP 协议(请求/响应、状态码、Headers、Cookie)、HTML/CSS 基础。
- 入门工具 :
requests+BeautifulSoup,在quotes.toscrape.com、books.toscrape.com等练习站练手。 - 进阶解析:学会用 XPath、CSS 选择器精准定位。
- 动态页面:学会用 F12 分析接口(这是最重要的实战技能),再学 Playwright。
- 工程化:学习 Scrapy 框架,掌握并发、去重、数据管道。
- 数据存储:CSV → MySQL / MongoDB。
- 合规意识:始终把"这件事合不合法、合不合规"放在技术之前。
总结
本文从爬虫的基本概念讲到工作流程、常用工具,再到网站的各类反爬手段和应对思路,最后落到法律与道德边界。核心要点回顾:
- 爬虫本质是模拟浏览器发请求 + 提取数据,逃不开"请求→响应→解析→存储"四步;
- 工具上,
requests + BeautifulSoup入门,Scrapy工程化,动态页面优先找接口、兜底用浏览器自动化; - 反爬手段五花八门(UA 检测、IP 限频、验证码、JS 加密、字体反爬等),应对的核心是让爬虫像个礼貌的真实用户;
- 反爬越强,越说明对方不欢迎自动化访问,这时更该考虑合法替代方案;
- 技术之上是法律和道德,合规永远是第一位的。
希望这篇文章能帮你建立起爬虫的整体认知。技术的路很长,迈出第一步、并且走在正道上,最重要。
如果这篇文章对你有帮助,欢迎点赞、收藏、关注。有问题可以在评论区交流~