当你想采集一个网站的数据时,可能会遇到这样的问题:
-
请求太频繁,IP被封锁
-
网站需要登录才能访问
-
目标网站有反爬机制
代理、爬虫、蜘蛛就是解决这些问题的核心工具组合。本文将带你从零开始,理解这三个概念,并通过实战掌握它们的使用方法。
一、概念扫盲:代理、爬虫、蜘蛛是什么?
爬虫程序(Spider) 经过代理服务器(Proxy) 最后到目标网站(Target)
在实际开发中,“爬虫”和“蜘蛛”经常混用。严格来说,蜘蛛是爬虫的一种特殊形式,遵循robots.txt协议,用于搜索引擎索引。
二、实验环境准备
安装Python依赖
创建虚拟环境(推荐) python3 -m venv spider-env source spider-env/bin/activate # Windows: spider-env\\Scripts\\activate
安装核心库 pip install requests pip install beautifulsoup4 pip install scrapy pip install selenium pip install fake-useragent
三、实验一:基础爬虫 – 从零写一个简单爬虫
3.1 实验目标
爬取一个公开的新闻列表页,提取所有新闻标题和链接。
3.2 完整代码
python
import requests
from bs4 import BeautifulSoup
# 目标URL(示例使用,请替换为你需要爬取的网站)
url = "https://example-news.com/"
# 模拟浏览器请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
# 发送请求
response = requests.get(url, headers=headers)
# 检查请求是否成功
if response.status_code == 200:
print("✅ 请求成功")
# 解析HTML
soup = BeautifulSoup(response.text, "html.parser")
# 提取新闻标题(具体选择器根据目标网站调整)
news_items = soup.find_all("a", class_="news-title")
for item in news_items:
title = item.get_text(strip=True)
link = item.get("href")
print(f"标题:{title}")
print(f"链接:{link}")
print("-" * 50)
else:
print(f"❌ 请求失败,状态码:{response.status_code}")
3.3 运行结果示例
text
✅ 请求成功
标题:某地发生6.0级地震
链接:/news/1001
————————————————–
标题:科技公司发布新款产品
链接:/news/1002
————————————————–
标题:天气预报:周末将有强降雨
链接:/news/1003
————————————————–
四、实验二:代理IP的使用
4.1 为什么需要代理?
| IP被封 | 更换代理IP继续访问 |
| 访问限制 | 通过代理绕过地域限制 |
| 隐藏身份 | 目标网站看不到你的真实IP |
4.2 代理类型对比
高匿代理(最安全)
普匿代理 (较安全)
透明代理 (不安全)
结论:爬虫请使用高匿代理。
4.3 代理IP来源
方式1:免费代理(不推荐生产环境)
-
https://free-proxy-list.net/
-
https://www.sslproxies.org/
方式2:付费代理(推荐)
-
芝麻代理
-
快代理
-
阿布云
方式3:自建代理池
python
proxy_pool = [ "http://127.0.0.1:8080", "http://192.168.1.100:3128", "socks5://127.0.0.1:1080", ]
4.4 代码实战:使用代理发送请求
python
import requests
# 代理配置(以快代理为例)
proxy = {
"http": "http://用户名:密码@host:port",
"https": "http://用户名:密码@host:port",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
try:
response = requests.get(
"https://httpbin.org/ip", # 测试IP的接口
proxies=proxy,
headers=headers,
timeout=10
)
print(f"代理IP返回的结果:{response.text}")
except requests.exceptions.ProxyError as e:
print(f"代理连接失败:{e}")
4.5 代理轮换(避免单IP请求过快)
python
import requests
import random
import time
class ProxyRotator:
def __init__(self, proxy_list):
self.proxy_list = proxy_list
self.current_index = 0
def get_proxy(self):
"""轮换获取代理"""
proxy = self.proxy_list[self.current_index]
self.current_index = (self.current_index + 1) % len(self.proxy_list)
return {"http": proxy, "https": proxy}
def random_proxy(self):
"""随机获取代理"""
proxy = random.choice(self.proxy_list)
return {"http": proxy, "https": proxy}
# 使用示例
proxies = [
"http://proxy1:8080",
"http://proxy2:8080",
"http://proxy3:8080",
]
rotator = ProxyRotator(proxies)
for i in range(10):
proxy = rotator.random_proxy()
try:
response = requests.get("https://httpbin.org/ip", proxies=proxy, timeout=5)
print(f"第{i+1}次请求,使用代理:{proxy}")
except:
print(f"第{i+1}次请求失败,切换代理")
time.sleep(1) # 控制请求频率
五、实验三:Scrapy框架 – 专业的爬虫蜘蛛
5.1 什么是Scrapy?
Scrapy是一个用Python编写的快速、高层次的Web爬取框架,适合大规模数据采集。
5.2 创建第一个Scrapy项目
bash
# 安装scrapy
pip install scrapy
# 创建项目
scrapy startproject myspider
# 进入项目目录
cd myspider
# 生成一个蜘蛛
scrapy genspider example example.com
5.3 项目目录结构
text
myspider/
├── scrapy.cfg # 配置文件
├── myspider/
│ ├── __init__.py
│ ├── items.py # 定义数据结构
│ ├── middlewares.py # 中间件(代理、User-Agent)
│ ├── pipelines.py # 数据处理管道
│ ├── settings.py # 项目配置
│ └── spiders/ # 蜘蛛代码目录
│ ├── __init__.py
│ └── example.py # 刚才生成的蜘蛛
5.4 编写一个完整的蜘蛛
以爬取某网站新闻为例,编辑 spiders/news_spider.py:
python
import scrapy
class NewsSpider(scrapy.Spider):
name = "news"
allowed_domains = ["example-news.com"]
start_urls = ["https://example-news.com/news"]
def parse(self, response):
"""解析首页,提取新闻列表和翻页链接"""
# 提取每条新闻
for news in response.css("div.news-item"):
yield {
"title": news.css("h3 a::text").get(),
"url": news.css("h3 a::attr(href)").get(),
"date": news.css("span.date::text").get(),
"summary": news.css("p.summary::text").get(),
}
# 处理翻页
next_page = response.css("a.next-page::attr(href)").get()
if next_page:
yield scrapy.Request(
url=response.urljoin(next_page),
callback=self.parse
)
5.5 运行蜘蛛
bash
# 运行并输出到JSON文件
scrapy crawl news -o news.json
# 运行并输出到CSV文件
scrapy crawl news -o news.csv
# 带日志输出
scrapy crawl news -o news.json –logfile spider.log
六、实验四:反爬策略与应对
6.1 常见的反爬手段
| IP限流 | 同一IP短时间内请求过多 | 代理池轮换 |
| User-Agent检测 | 识别非浏览器请求 | 随机UA |
| 验证码 | 要求人工识别 | OCR识别/打码平台 |
| JavaScript渲染 | 数据由JS动态加载 | Selenium/Playwright |
| 请求头校验 | 检查Referer、Cookie等 | 完整模拟请求头 |
6.2 应对方案1:随机User-Agent
python
from fake_useragent import UserAgent
ua = UserAgent()
headers = {
"User-Agent": ua.random # 随机生成UA
}
print(f"随机UA:{ua.random}")
# 输出示例:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
6.3 应对方案2:模拟浏览器(Selenium)
当目标网站使用JavaScript渲染数据时,Requests无法获取内容,需要用Selenium模拟真实浏览器。
python
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# 初始化浏览器驱动
driver = webdriver.Chrome() # 需要安装chromedriver
# 访问目标页面
driver.get("https://example.com")
# 等待页面加载
time.sleep(3)
# 提取数据
titles = driver.find_elements(By.CSS_SELECTOR, "h3.title")
for title in titles:
print(title.text)
# 关闭浏览器
driver.quit()
配置无头模式(后台运行):
python
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("–headless") # 无头模式,不显示浏览器窗口
options.add_argument("–no-sandbox")
driver = webdriver.Chrome(options=options)
6.4 应对方案3:请求频率控制
python
import time
import random
def polite_request(url):
"""礼貌爬取:随机间隔2-5秒"""
time.sleep(random.uniform(2, 5))
return requests.get(url)
# 使用示例
for url in url_list:
response = polite_request(url)
print(f"已爬取:{url}")
七、实验五:构建完整的代理爬虫
7.1 完整代码:带代理轮换的爬虫
python
import requests
import random
import time
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
class SmartSpider:
"""智能爬虫:支持代理轮换、随机UA、请求间隔"""
def __init__(self, proxy_list=None):
self.ua = UserAgent()
self.proxy_list = proxy_list or []
self.request_count = 0
def get_headers(self):
"""获取随机请求头"""
return {
"User-Agent": self.ua.random,
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
}
def get_proxy(self):
"""获取随机代理"""
if not self.proxy_list:
return None
proxy = random.choice(self.proxy_list)
return {"http": proxy, "https": proxy}
def fetch(self, url, max_retries=3):
"""发送请求,支持重试"""
for attempt in range(max_retries):
try:
response = requests.get(
url,
headers=self.get_headers(),
proxies=self.get_proxy(),
timeout=10
)
self.request_count += 1
if response.status_code == 200:
return response
else:
print(f"状态码异常:{response.status_code},重试中…")
except requests.exceptions.RequestException as e:
print(f"请求失败:{e},重试中…")
# 等待后重试
time.sleep(2)
return None
def parse(self, response):
"""解析响应(子类可覆盖)"""
soup = BeautifulSoup(response.text, "html.parser")
return soup
# 使用示例
if __name__ == "__main__":
# 代理列表(实际使用时替换为有效代理)
proxies = [
"http://127.0.0.1:8080",
"http://127.0.0.1:8888",
]
spider = SmartSpider(proxy_list=proxies)
# 要爬取的URL列表
urls = [
"https://httpbin.org/ip",
"https://httpbin.org/headers",
]
for url in urls:
response = spider.fetch(url)
if response:
print(f"✅ {url} 请求成功")
print(f"响应内容:{response.text[:200]}…")
else:
print(f"❌ {url} 请求失败")
# 请求间隔
time.sleep(random.uniform(1, 3))
print(f"\\n共发送 {spider.request_count} 次请求")
八、robots.txt 与爬虫礼仪
8.1 什么是robots.txt?
robots.txt 是网站根目录下的一个文本文件,告诉爬虫哪些页面可以抓取,哪些不能。
示例:
txt
# 允许所有爬虫抓取所有内容
User-agent: *
Disallow:
# 禁止所有爬虫
User-agent: *
Disallow: /
# 禁止某爬虫抓取指定目录
User-agent: BadBot
Disallow: /private/
Disallow: /admin/
8.2 如何查看网站的robots.txt?
text
https://www.baidu.com/robots.txt
https://www.taobao.com/robots.txt
8.3 Python解析robots.txt
python
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()
# 检查是否允许抓取
can_fetch = rp.can_fetch("*", "https://example.com/private-page")
print(f"是否允许抓取:{can_fetch}")
九、完整工作流程图
爬虫项目完整工作流程
第一阶段:准备
① 分析目标网站结构
② 检查robots.txt
③ 准备代理池
第二阶段:开发
④ 编写爬虫代码(Requests/Scrapy)
⑤ 配置代理轮换
⑥ 设置请求间隔和重试机制
第三阶段:运行
⑦ 小规模测试
⑧ 全量爬取
⑨ 数据存储(JSON/CSV/数据库)
第四阶段:维护
⑩ 监控IP封禁情况
⑪ 更新代理池
⑫ 应对网站改版
十、常见问题排查
| 请求返回403 | 被识别为爬虫 | 更换UA、添加代理、增加请求间隔 |
| 代理连接超时 | 代理服务器失效 | 更新代理列表、缩短超时时间 |
| 页面内容不完整 | JS渲染未执行 | 使用Selenium或分析API接口 |
| 请求大量失败 | IP被临时封禁 | 使用代理池轮换、降低请求频率 |
| 中文乱码 | 编码问题 | response.encoding = 'utf-8' |



