Python 爬虫技巧总结
爬虫的核心思想是模拟浏览器行为,向服务器发送请求,并解析返回的数据,现代网站都有反爬机制,抓站”的技巧更多体现在如何优雅、高效、稳定地绕过这些限制。

核心策略与思想
在写代码之前,正确的策略远比代码本身重要。
-
明确目标,分析网站
- 静态 vs. 动态:网站是纯静态(HTML 直接返回)还是动态(通过 JavaScript 渲染)?
- 静态网站:直接请求 URL,解析 HTML 即可,使用
requests+BeautifulSoup或lxml。 - 动态网站:需要模拟浏览器执行 JS,才能看到最终数据,需要使用
Selenium、Playwright或Pyppeteer等工具。
- 静态网站:直接请求 URL,解析 HTML 即可,使用
- 数据接口:很多动态网站的数据是通过 AJAX 请求从后端 API 获取的,尝试找到这个 API 接口(通常在 Network 面板中),直接调用接口,效率远高于渲染整个页面。
- 网站结构:使用浏览器的“开发者工具”(F12)仔细分析网页结构,找到数据所在的 HTML 标签、CSS 类名或 ID。
- 静态 vs. 动态:网站是纯静态(HTML 直接返回)还是动态(通过 JavaScript 渲染)?
-
尊重
robots.txt- 这是一个君子协议,位于网站根目录下(如
https://www.example.com/robots.txt),它告诉爬虫哪些页面可以抓取,哪些不可以。 - 虽然不遵守不违法,但一个有道德的爬虫应该遵守它,可以使用
robotparser模块来解析。
- 这是一个君子协议,位于网站根目录下(如
-
控制请求频率,做“礼貌”的爬虫
(图片来源网络,侵删)- 设置
User-Agent:模拟真实浏览器,避免被识别为爬虫。 - 添加延迟:在两次请求之间加入随机延时(如
time.sleep(random.uniform(1, 3))),避免对服务器造成过大压力。 - 使用代理 IP:避免因高频率请求导致单个 IP 被封。
- 设置
核心库与工具选择
-
HTTP 请求库
requests:事实上的标准,简单、易用、功能强大,适合绝大多数静态页面和 API 请求。aiohttp:基于asyncio的异步 HTTP 客户端/服务器库,配合asyncio使用,可以实现高并发爬取,效率极高。
-
HTML/XML 解析库
BeautifulSoup:非常流行的解析库,API 友好,容错性强,支持多种解析器(如lxml,html.parser),适合快速定位和提取数据。lxml:性能极高,功能强大,支持 XPath 和 CSS 选择器,API 稍复杂,但效率是最大优势。pyquery:模仿 jQuery 的语法,如果你熟悉 jQuery,会非常顺手。
-
浏览器自动化工具
Selenium:老牌工具,通过驱动真实浏览器(Chrome, Firefox)来操作页面,可以处理 JS 渲染、点击、输入等复杂交互。Playwright:微软出品,新一代自动化神器,比 Selenium 更快、更稳定、API 更现代,支持异步操作,是当前的首选。Pyppeteer:非官方的 Python 对Puppeteer(Node.js 库)的移植,无头浏览器控制,功能强大。
实用技巧与代码示例
请求技巧
技巧 1:设置合理的请求头
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
}
url = 'https://example.com'
response = requests.get(url, headers=headers)
print(response.text)
技巧 2:处理会话和登录
使用 Session 对象可以跨请求保持某些参数(如 cookies),非常适合需要登录的网站。
import requests
# 创建一个 Session 对象
session = requests.Session()
# 第一次请求,获取登录所需的 cookies 或 token
# session.get('https://example.com/login')
# 第二次请求,带着 Session 的 cookies 去登录
login_data = {'username': 'user', 'password': 'pass'}
session.post('https://example.com/do_login', data=login_data)
# 之后的所有请求都会自动带上登录后的 cookies
response = session.get('https://example.com/profile')
print(response.text)
技巧 3:处理重定向
requests 默认会跟随重定向,如果你想查看重定向的中间过程或禁用重定向,可以设置 allow_redirects。
# 禁用重定向
response = requests.get('http://example.com/redirect_page', allow_redirects=False)
print(f"Status Code: {response.status_code}") # 会打印 301 或 302
print(f"Redirect URL: {response.headers['Location']}")
解析技巧
技巧 4:善用 CSS 选择器和 XPath
-
CSS 选择器:更简洁直观。
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'lxml') # 获取 class 为 'post-title' 的第一个 <a> 标签= soup.select_one('.post-title a').get_text() # 获取所有 class 为 'entry-content' 的 div contents = soup.select('.entry-content') -
XPath:功能更强大,支持复杂的路径和逻辑。
from lxml import etree html = etree.HTML(html_content) # 获取所有 href 属性以 '/post/' 开头的链接 links = html.xpath('//a[starts-with(@href, "/post/")]/@href')
技巧 5:处理动态加载(AJAX)
打开浏览器开发者工具,切换到 "Network" 标签,刷新页面,找到那些返回 JSON 数据的 XHR/Fetch 请求,分析它的 URL、请求方法、请求头和载荷,然后直接用 requests 模拟它。
# 假设通过分析发现数据是通过 POST 请求到这个 API
api_url = 'https://api.example.com/data'
params = {'page': 1, 'limit': 20}
headers = {'Referer': 'https://www.example.com'} # 可能需要伪造来源
response = requests.post(api_url, json=params, headers=headers)
data = response.json() # 直接获取 JSON 数据
for item in data['results']:
print(item['title'])
反爬虫应对技巧
技巧 6:处理验证码
- 简单图形验证码:可以使用
Tesseract(OCR) 库进行识别,但准确率不高。 - 滑动验证码:通常需要模拟滑动轨迹,可以使用
selenium或playwright拖动滑块,或者使用打码平台(如 2Captcha, Anti-Captcha)的 API。 - 点选验证码:同理,可通过自动化工具或打码平台解决。
技巧 7:使用代理 IP
import requests
proxies = {
'http': 'http://your_proxy_ip:port',
'https': 'https://your_proxy_ip:port',
}
try:
response = requests.get('http://example.com', proxies=proxies, timeout=10)
print(response.text)
except requests.exceptions.ProxyError:
print("代理连接失败!")
技巧 8:处理 IP 封禁
- IP 代理池:准备一个可用的代理 IP 列表,每次请求随机选择一个。
- 降低请求频率:这是最根本的方法。
time.sleep()是最简单的实现。 - 分布式爬虫:使用 Scrapy-Redis 等框架,将任务分发到多个机器上,用不同的 IP 进行爬取。
技巧 9:处理 JavaScript 渲染
当 requests 无法获取数据时,就该上 Playwright 或 Selenium 了。
# Playwright 示例 (推荐)
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # headless=False 可以看到浏览器界面
page = browser.new_page()
page.goto('https://example.com/some-js-page')
# 等待某个元素加载完成,确保数据已经渲染
page.wait_for_selector('.data-container')
# 获取渲染后的 HTML
html_content = page.content()
# 然后用 BeautifulSoup 解析
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_content, 'lxml')
# ...提取数据...
browser.close()
技巧 10:处理加密参数
有些请求参数(如 sign, token)是通过 JS 在前端动态生成的,这时你需要:
- 分析 JS 代码:在开发者工具中找到生成该参数的 JS 函数,尝试用 Python 重写它(通常很困难)。
- 使用 PyExecJS:在 Python 中执行这段 JS 代码,直接调用函数生成参数。
- 逆向工程:对于复杂情况,可能需要更高级的逆向工程知识。
高级与项目化技巧
-
异步爬虫 (
asyncio+aiohttp) 对于需要高并发的爬虫,异步是必经之路,它可以在等待一个网站响应的同时,去发送其他网站的请求,极大地利用 I/O 时间。import asyncio import aiohttp async def fetch(session, url): async with session.get(url) as response: return await response.text() async def main(urls): async with aiohttp.ClientSession() as session: tasks = [fetch(session, url) for url in urls] htmls = await asyncio.gather(*tasks) return htmls urls = ['http://example.com'] * 10 htmls = asyncio.run(main(urls)) -
使用 Scrapy 框架 Scrapy 是一个成熟的爬虫框架,提供了强大的功能:
- 异步架构:内置了异步请求引擎。
- 数据流管道:可以方便地定义数据的清洗、存储流程(如存入 JSON, CSV, MySQL, MongoDB)。
- 中间件:可以自定义请求头、代理、重试等逻辑。
- Spider 基类:简化了爬虫的编写。
-
数据存储
- 文本文件:
.json,.csv,.txt,适合少量数据。 - 关系型数据库:
MySQL,PostgreSQL,适合结构化数据,需要建表。 - 非关系型数据库:
MongoDB,适合存储非结构化或半结构化的数据(如抓取的整个 HTML 页面),非常灵活。
- 文本文件:
-
部署与调度
- 定时任务:使用
cron(Linux) 或任务计划程序 (Windows) 定时运行你的爬虫脚本。 - 云服务器:将爬虫部署在云服务器(如阿里云、腾讯云)上,使其 7x24 小时运行。
- Docker 容器化:将爬虫及其环境打包成 Docker 镜像,便于部署和迁移。
- 定时任务:使用
法律与道德
- 明确目的:仅用于学习和研究。
- 检查
robots.txt:遵守网站的爬取规则。 - 控制频率:不要对服务器造成过大负担。
- 声明身份:在
User-Agent中可以包含你的联系邮箱,方便网站管理员在必要时联系你。 - 尊重数据版权:不要将抓取的数据用于商业用途或侵犯他人隐私。
希望这份总结能帮助你更好地掌握 Python 爬虫技术!
