✅ 无缝衔接基础版内容,从“爬取静态/简单动态网页”到“应对企业级爬虫场景”过渡
✅ 技术适配:基于Python 3.12 + Scrapy框架 + 反爬突破 + 异步爬虫 + 数据存储进阶 + 分布式爬虫入门,聚焦高并发、反爬应对、规模化爬取三大核心场景
✅ 白话拆解+代码示例+实战场景,无冗余知识点,零基础可理解、可落地
✅ 核心目标:掌握企业级爬虫开发必备技能,能应对反爬机制、实现高效爬取、完成规模化数据采集
一、进阶学习核心定位
基础版聚焦“入门级爬取+基础数据存储”,进阶版核心解决:
✅ 效率提升:从单线程同步爬取到异步/多线程爬取,效率提升10倍+
✅ 反爬突破:应对常见反爬机制(IP封禁、验证码、Cookie验证、JS加密)
✅ 工程化落地:掌握Scrapy框架、分布式爬虫、数据去重/清洗、爬虫监控
✅ 合规与稳定:构建健壮的爬虫体系,避免被封、数据丢失
二、第一部分:爬虫效率进阶
1. 异步爬虫(aiohttp)
基础版的Requests是同步请求(一个请求完成再发下一个),异步爬虫可同时发送多个请求,大幅提升爬取效率,适合大批量数据采集。
核心代码示例:
import aiohttp
import asyncio
from bs4 import BeautifulSoup
# 异步请求函数
async def fetch_url(session, url):
headers = {"User-Agent": "Chrome/120.0.0.0"}
try:
async with session.get(url, headers=headers, timeout=10) as response:
if response.status == 200:
html = await response.text()
return parse_html(html) # 解析数据
return None
except Exception as e:
print(f"请求失败:{url},错误:{e}")
return None
# 数据解析函数
def parse_html(html):
soup = BeautifulSoup(html, "lxml")
title = soup.title.text.strip()
return title
# 主异步函数
async def main(urls):
# 创建异步会话
async with aiohttp.ClientSession() as session:
# 批量创建任务
tasks = [fetch_url(session, url) for url in urls]
# 执行所有任务
results = await asyncio.gather(*tasks)
# 过滤空结果
valid_results = [res for res in results if res]
print(f"成功爬取 {len(valid_results)} 个页面")
print(valid_results[:5])
if __name__ == "__main__":
# 待爬取的URL列表
test_urls = [f"https://book.douban.com/top250?start={i*25}" for i in range(10)]
# 运行异步程序
asyncio.run(main(test_urls))
关键要点:
- 核心库:
aiohttp(异步HTTP请求)、asyncio(异步任务调度); - 语法规则:异步函数用
async def定义,耗时操作前加await; - 优势:批量请求时效率远超同步爬虫,适合爬取海量URL。
2. 多线程/多进程爬虫
多线程:同一进程下同时运行多个任务,适合IO密集型(如网络请求);
多进程:利用多核CPU,适合CPU密集型(如大量数据解析)。
多线程示例(threading):
import requests
from bs4 import BeautifulSoup
import threading
import queue
# 队列存储URL(线程安全)
url_queue = queue.Queue()
# 结果存储(加锁避免冲突)
result_list = []
lock = threading.Lock()
# 线程任务函数
def crawl_worker():
headers = {"User-Agent": "Chrome/120.0.0.0"}
while not url_queue.empty():
url = url_queue.get()
try:
response = requests.get(url, headers=headers, timeout=5)
response.encoding = "utf-8"
soup = BeautifulSoup(response.text, "lxml")
title = soup.title.text.strip()
# 加锁写入结果
with lock:
result_list.append(title)
except Exception as e:
print(f"爬取失败:{url},错误:{e}")
finally:
url_queue.task_done()
if __name__ == "__main__":
# 填充URL队列
for i in range(10):
url_queue.put(f"https://book.douban.com/top250?start={i*25}")
# 创建5个线程
threads = []
for _ in range(5):
t = threading.Thread(target=crawl_worker)
t.start()
threads.append(t)
# 等待所有线程完成
for t in threads:
t.join()
print(f"爬取完成,共获取 {len(result_list)} 个标题")
print(result_list[:5])
关键要点:
- 线程安全:用
queue.Queue存储URL,threading.Lock保护共享数据; - 适用场景:多线程适合爬虫(IO密集),多进程适合数据处理(CPU密集);
- 注意:避免创建过多线程(建议10-20个),否则会引发连接异常。
三、第二部分:反爬机制突破
1. IP代理池(应对IP封禁)
网站会限制单一IP的请求频率,代理池可切换不同IP发送请求,避免被封。
核心实现:
import requests
# 代理池(可对接免费/付费代理接口)
proxies_list = [
{"http": "http://123.45.67.89:8080", "https": "https://123.45.67.89:8080"},
{"http": "http://98.76.54.32:8080", "https": "https://98.76.54.32:8080"}
]
def crawl_with_proxy(url):
headers = {"User-Agent": "Chrome/120.0.0.0"}
# 随机选择代理
import random
proxy = random.choice(proxies_list)
try:
# 超时控制+代理请求
response = requests.get(url, headers=headers, proxies=proxy, timeout=10)
print(f"代理 {proxy['http']} 请求成功,状态码:{response.status_code}")
return response.text
except Exception as e:
print(f"代理 {proxy['http']} 请求失败:{e}")
return None
# 测试
crawl_with_proxy("https://httpbin.org/ip") # 查看当前IP
关键要点:
- 代理类型:免费代理(稳定性差)、付费代理(如阿布云、快代理,企业级首选);
- 代理验证:爬取
https://httpbin.org/ip验证代理是否生效; - 异常处理:代理失效时自动切换下一个,避免程序中断。
2. 验证码处理(入门级)
2.1 手动打码(简单场景)
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://www.xxx.com/login")
# 等待用户手动输入验证码
time.sleep(10) # 10秒内完成验证码输入+登录
# 后续爬取逻辑
...
driver.quit()
2.2 第三方打码平台(如超级鹰,自动化处理)
import requests
from PIL import Image
import base64
# 1. 下载验证码图片
captcha_url = "https://www.xxx.com/captcha.jpg"
response = requests.get(captcha_url)
with open("captcha.jpg", "wb") as f:
f.write(response.content)
# 2. 调用超级鹰接口识别(需注册账号)
def recognize_captcha(image_path):
api_url = "http://upload.chaojiying.net/Upload/Processing.php"
params = {
"user": "你的账号",
"pass": "你的密码",
"softid": "你的软件ID",
"codetype": "1004" # 验证码类型(数字+字母)
}
with open(image_path, "rb") as f:
files = {"userfile": f}
response = requests.post(api_url, data=params, files=files)
result = response.json()
return result["pic_str"] if result["err_no"] == 0 else None
# 3. 获取识别结果
captcha_code = recognize_captcha("captcha.jpg")
print(f"验证码识别结果:{captcha_code}")
3. Cookie与Session保持
部分网站需要登录后才能爬取,通过Session保持登录状态,避免重复登录。
import requests
# 创建Session(自动保持Cookie)
session = requests.Session()
headers = {"User-Agent": "Chrome/120.0.0.0"}
# 1. 登录(获取Cookie)
login_url = "https://www.xxx.com/login"
login_data = {
"username": "你的账号",
"password": "你的密码"
}
session.post(login_url, data=login_data, headers=headers)
# 2. 爬取需要登录的页面(自动携带Cookie)
user_center_url = "https://www.xxx.com/user-center"
response = session.get(user_center_url, headers=headers)
print(response.text) # 已登录后的内容
四、第三部分:工程化爬虫(Scrapy框架)
1. Scrapy核心优势
- 内置异步处理、数据解析、数据存储、反爬配置;
- 模块化设计,支持中间件、扩展,适合规模化爬虫开发;
- 内置日志、统计、断点续爬等功能,企业级必备。
2. Scrapy入门实战(爬取豆瓣书籍)
步骤1:创建Scrapy项目
# 创建项目
scrapy startproject douban_spider
# 创建爬虫
cd douban_spider
scrapy genspider book book.douban.com
步骤2:编写爬虫代码(douban_spider/spiders/book.py)
import scrapy
class BookSpider(scrapy.Spider):
name = "book" # 爬虫名
allowed_domains = ["book.douban.com"] # 允许爬取的域名
start_urls = ["https://book.douban.com/top250"] # 起始URL
def parse(self, response):
# 解析书籍列表(XPath语法)
book_items = response.xpath('//tr[@class="item"]')
for item in book_items[:10]:
# 提取数据(XPath/CSSelector均可)
yield {
"rank": item.xpath('.//em/text()').extract_first(),
"name": item.xpath('.//div[@class="pl2"]/a/@title').extract_first(),
"score": item.xpath('.//span[@class="rating_nums"]/text()').extract_first(),
"link": item.xpath('.//div[@class="pl2"]/a/@href').extract_first()
}
# 翻页(爬取下一页)
next_page = response.xpath('//a[@class="next"]/@href').extract_first()
if next_page:
yield scrapy.Request(url=response.urljoin(next_page), callback=self.parse)
步骤3:配置反爬(settings.py)
# 设置User-Agent
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"
# 延迟请求(避免过快)
DOWNLOAD_DELAY = 2
# 启用Cookie保持
COOKIES_ENABLED = True
# 日志级别
LOG_LEVEL = "INFO"
步骤4:运行爬虫+存储数据
# 运行爬虫,保存为CSV
scrapy crawl book -o books.csv
# 保存为JSON
scrapy crawl book -o books.json
3. Scrapy中间件(自定义反爬策略)
示例:添加代理中间件(middlewares.py)
class ProxyMiddleware:
def process_request(self, request, spider):
# 随机添加代理
proxies = [
"http://123.45.67.89:8080",
"http://98.76.54.32:8080"
]
import random
request.meta["proxy"] = random.choice(proxies)
在settings.py启用中间件:
DOWNLOADER_MIDDLEWARES = {
"douban_spider.middlewares.ProxyMiddleware": 543,
}
五、第四部分:数据处理进阶
1. 数据去重
import pandas as pd
# 读取爬取的数据
df = pd.read_csv("books.csv")
# 按书名去重(保留第一条)
df = df.drop_duplicates(subset=["name"], keep="first")
# 重置索引
df = df.reset_index(drop=True)
# 保存去重后的数据
df.to_csv("books_unique.csv", index=False)
print(f"去重前:{len(df)+len(df[df.duplicated(subset=['name'])])} 条,去重后:{len(df)} 条")
2. 数据清洗(处理缺失值/异常值)
import pandas as pd
df = pd.read_csv("books.csv")
# 处理缺失值(删除/填充)
df = df.dropna(subset=["name", "score"]) # 删除书名/评分缺失的行
df["score"] = df["score"].fillna(0) # 填充评分缺失值为0
# 处理异常值(如评分超出0-10范围)
df = df[(df["score"] >= 0) & (df["score"] <= 10)]
# 保存清洗后的数据
df.to_csv("books_clean.csv", index=False)
3. 数据库存储(MySQL/MongoDB)
3.1 存储到MySQL(Scrapy示例)
# pipelines.py
import pymysql
class MySQLPipeline:
def open_spider(self, spider):
# 连接数据库
self.conn = pymysql.connect(
host="localhost",
user="root",
password="你的密码",
database="spider_db",
charset="utf8mb4"
)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
# 插入数据
sql = "INSERT INTO books (rank, name, score, link) VALUES (%s, %s, %s, %s)"
self.cursor.execute(sql, (item["rank"], item["name"], item["score"], item["link"]))
self.conn.commit()
return item
def close_spider(self, spider):
# 关闭连接
self.cursor.close()
self.conn.close()
3.2 存储到MongoDB(Scrapy示例)
# pipelines.py
import pymongo
class MongoPipeline:
def open_spider(self, spider):
self.client = pymongo.MongoClient("mongodb://localhost:27017/")
self.db = self.client["spider_db"]
self.collection = self.db["books"]
def process_item(self, item, spider):
self.collection.insert_one(dict(item))
return item
def close_spider(self, spider):
self.client.close()
六、核心避坑清单
- ❌ 异步爬虫未做超时控制 → ✅ 添加
timeout参数,避免请求挂起; - ❌ 代理池无验证机制 → ✅ 定期检测代理有效性,剔除失效代理;
- ❌ Scrapy爬取时忽略
allowed_domains→ ✅ 严格配置允许的域名,避免爬取无关网站; - ❌ 数据存储未做去重 → ✅ 爬取后先去重再入库,避免数据冗余;
- ❌ 高并发爬取无限流 → ✅ 设置
DOWNLOAD_DELAY或限速中间件,避免被封; - ❌ 忽略网站反爬升级 → ✅ 定期测试爬虫,及时调整反爬策略。
七、总结
- 效率提升核心:异步(aiohttp)、多线程适合大批量爬取,Scrapy框架是企业级爬虫的首选;
- 反爬突破关键:IP代理池解决IP封禁,Session保持登录状态,验证码可通过手动/第三方平台处理;
- 工程化落地:Scrapy的中间件、管道机制可实现模块化开发,适配复杂爬取场景;
- 数据处理重点:爬取后必须做去重、清洗,保证数据质量,按需选择CSV/MySQL/MongoDB存储。

7848

被折叠的 条评论
为什么被折叠?



