别再手动抓数据了!Python+XHR轻松搞定AJAX网页爬取(新手友好版)
·
Python+XHR爬虫实战:零基础破解AJAX动态加载难题
每次看到心仪的数据却只能对着动态加载的网页干瞪眼?作为爬虫新手,你可能遇到过这样的场景:明明浏览器里能看到完整内容,但用传统requests库抓取时却只能得到空荡荡的HTML骨架。别担心,今天我们就用Python+XHR组合拳,带你轻松攻克这个技术痛点。
1. 为什么传统爬虫对AJAX网页失效?
打开开发者工具(F12),切换到Network面板刷新页面,你会看到瀑布流般的数据请求——这就是现代网页的"秘密"。传统服务端渲染的网页像一份完整外卖,HTML里已经包含所有"食材";而AJAX动态加载的网页则像火锅店,HTML只是锅底,真正的"配菜"是通过XHR请求陆续上桌的。
典型特征识别:
- 页面内容分批加载(如滚动加载更多)
- 网址不变但内容变化
- 网页源代码与显示内容不匹配
提示:Chrome开发者工具的"Preserve log"选项可以防止页面跳转时请求记录被清除
2. XHR请求逆向工程实战
2.1 定位关键数据请求
以某电商网站为例,按F12打开开发者工具:
- 切换到Network面板
- 勾选"XHR"过滤器
- 触发数据加载动作(如点击"加载更多")
- 观察新出现的请求列表
关键识别技巧:
- 查看Preview选项卡预览响应数据
- 按响应体积排序(大体积更可能是主体数据)
- 关注包含"api"、"data"等字样的请求路径
# 请求示例分析
{
"method": "GET",
"url": "https://api.example.com/products?page=2",
"headers": {
"X-Requested-With": "XMLHttpRequest"
}
}
2.2 解密请求参数
常见的参数传递方式:
| 参数类型 | 示例 | 处理方式 |
|---|---|---|
| 查询字符串 | ?page=2&size=20 | 直接拼接URL |
| 表单数据 | form-data格式 | requests.post()的data参数 |
| JSON载荷 | {"page":2,"size":20} | requests.post()的json参数 |
# 带查询参数的请求示例
import requests
params = {
'page': 2,
'size': 20,
'sort': 'price,desc'
}
response = requests.get('https://api.example.com/products', params=params)
3. 构建健壮的XHR爬虫
3.1 请求头伪装艺术
反爬机制常会检查这些关键头信息:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Referer': 'https://www.example.com/products',
'X-Requested-With': 'XMLHttpRequest'
}
注意:某些API会验证Origin或Cookie,需要从浏览器请求中复制完整headers
3.2 分页逻辑自动化
动态加载的分页通常有三种模式:
- 页码递增:page=1 → page=2
- 偏移量控制:offset=0 → offset=20
- 游标标记:after=last_item_id
# 自动翻页实现示例
def scrape_all_pages(base_url):
page = 1
while True:
data = get_page_data(base_url, page)
if not data['items']:
break
process_data(data)
page += 1
time.sleep(1) # 礼貌性延迟
4. 数据清洗与存储方案
4.1 JSON数据精加工
从API获取的数据通常需要二次处理:
# 数据清洗示例
def clean_product(raw):
return {
'title': raw['name'].strip(),
'price': float(raw['price']['amount']),
'stock': raw['inventory']['available'],
'specs': {k: v for k, v in raw['attributes'].items()
if k in ['color', 'size']}
}
4.2 多格式存储方案
根据数据量选择存储方式:
- 小型数据集:CSV(pandas.to_csv)
- 关系型数据:SQLite(内置sqlite3模块)
- 文档型数据:MongoDB(PyMongo库)
- 快速查询:Elasticsearch(elasticsearch-py)
# SQLite存储示例
import sqlite3
conn = sqlite3.connect('products.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS products
(id TEXT PRIMARY KEY, title TEXT, price REAL)''')
c.executemany('INSERT OR IGNORE INTO products VALUES (?,?,?)',
[(p['id'], p['title'], p['price']) for p in products])
conn.commit()
最近在帮朋友抓取某设计平台作品数据时,发现他们的API响应里竟然藏着设计师的地理位置坐标。这种意外收获正是XHR爬虫的魅力所在——你永远不知道下一个请求会解锁什么隐藏数据维度。建议新手从简单的API入手,比如天气预报或电影评分接口,等熟悉了请求规律再挑战更复杂的商业网站。
更多推荐


所有评论(0)