Python爬虫零基础入门【第七章:动态页面入门(Playwright)·第3节】优先 API:用 Network 找接口,回到 Requests(更稳定)!

🔥本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~持续更新中!!

全文目录:

    • [🌟 开篇语](#🌟 开篇语)
      • [📚 上期回顾](#📚 上期回顾)
      • [🎯 本篇目标](#🎯 本篇目标)
      • [💡 为什么优先找 API?](#💡 为什么优先找 API?)
        • [对比:Playwright vs Requests](#对比:Playwright vs Requests)
      • [🔍 实战:用 Network 面板找接口](#🔍 实战:用 Network 面板找接口)
        • [步骤 1:打开开发者工具](#步骤 1:打开开发者工具)
        • [步骤 2:筛选 XHR/Fetch 请求](#步骤 2:筛选 XHR/Fetch 请求)
        • [步骤 3:识别数据接口](#步骤 3:识别数据接口)
        • [步骤 4:复制接口 URL 参数)或 Form Data(POST 参数)](#步骤 4:复制接口 URL 参数)或 Form Data(POST 参数))
      • [🛠️ 实战:用 Requests 重写采集逻辑](#🛠️ 实战:用 Requests 重写采集逻辑)
      • [⚠️ 新手常见坑](#⚠️ 新手常见坑)
        • [坑 1:缺少关键 Headers](#坑 1:缺少关键 Headers)
        • [坑 2:参数加密或签名](#坑 2:参数加密或签名)
        • [坑 3:接口返回数据不完整](#坑 3:接口返回数据不完整)
      • [🚀 进阶技巧](#🚀 进阶技巧)
        • [技巧 1:用 Playwright 自动找接口](#技巧 1:用 Playwright 自动找接口)
        • [技巧 2:字段映射(接口字段 vs 页面展示)](#技巧 2:字段映射(接口字段 vs 页面展示))
        • [技巧 3:批量请求优化](#技巧 3:批量请求优化)
      • [📊 完整案例:从 Playwright 到 Requests](#📊 完整案例:从 Playwright 到 Requests)
        • [第一步:用 Playwright 找接口](#第一步:用 Playwright 找接口)
        • [第二步:用 Requests 重写](#第二步:用 Requests 重写)
      • [📝 小结](#📝 小结)
      • [🎯 下一章预告](#🎯 下一章预告)
    • [🌟 文末](#🌟 文末)
      • [📌 专栏持续更新中|建议收藏 + 订阅](#📌 专栏持续更新中|建议收藏 + 订阅)
      • [✅ 互动征集](#✅ 互动征集)

🌟 开篇语

哈喽,各位小伙伴们你们好呀~我是【喵手】。

运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO

欢迎大家常来逛逛,一起学习,一起进步~🌟

我长期专注 Python 爬虫工程化实战 ,主理专栏 👉 《Python爬虫实战》:从采集策略反爬对抗 ,从数据清洗分布式调度 ,持续输出可复用的方法论与可落地案例。内容主打一个"能跑、能用、能扩展 ",让数据价值真正做到------抓得到、洗得净、用得上

📌 专栏食用指南(建议收藏)

  • ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
  • ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
  • ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
  • ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用

📣 专栏推广时间 :如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅/关注专栏《Python爬虫实战》

订阅后更新会优先推送,按目录学习更高效~

📚 上期回顾

上一篇《Python爬虫零基础入门【第七章:动态页面入门(Playwright)·第2节】动态列表:滚动加载/点击翻页(通用套路)!》,我们搞定了动态列表采集,学会了用 Playwright 处理滚动加载和点击翻页。现在你已经能应对各种复杂的交互式页面了------滚动、点击、等待,样样精通。

但你有没有想过:Playwright 这么重,真的有必要吗?

启动浏览器要 2-3 秒,加载页面要等网络空闲,内存占用动辄几百 MB。而实际上,很多动态网站的数据都是通过 Ajax 接口 返回的 JSON------如果能直接找到这个接口,用 requests 抓取不是更快更稳?

今天,我们就来学习降维打击的终极技巧!

🎯 本篇目标

看完这篇,你能做到:

  1. 理解前后端分离架构(数据从哪来)
  2. 用浏览器 Network 面板找到数据接口(核心技能)
  3. 分析接口参数(分页、筛选、排序)
  4. 用 requests 替换 Playwright(速度提升 10 倍)

验收标准:找到一个动态网站的数据接口,用 requests 采集 200 条数据

💡 为什么优先找 API?

对比:Playwright vs Requests
维度 Playwright Requests + API
启动速度 2-3 秒 毫秒级
内存占用 200-500 MB 5-10 MB
稳定性 受页面变化影响大 接口相对稳定
数据干净度 需要解析 HTML 直接拿到 60 秒
json 复制代码
**API 方案:**

找到接口 → 循环请求 10 次(每页 20 条) → 解析 JSON
耗时:约 5 秒
效率提升 **12 倍**!

🔍 实战:用 Network 面板找接口

步骤 1:打开开发者工具

以 Chrome 为例:

  1. 打开目标网站(如某电商商品列表)
  2. F12右键 → 检查
  3. 切换到 Network(网络) 标签
  4. 勾选 Preserve log(保留日志)
  5. 刷新页面 F5
步骤 2:筛选 XHR/Fetch 请求

Network 面板会显示所有请求,我们只关心数据请求:

  1. 点击 XHRFetch 筛选器(只显示 Ajax 请求)
  2. 观察请求列表,找名字像
步骤 3:识别数据接口

点击某个请求,查看 PreviewResponse 标签:

这是数据接口的特征:

json 复制代码
{
  "code": 0,
  "data": {
    "items": [
      {
        "id": "123456",
        "title": "商品A",
        "price": 99.00
      },
      {
        "id": "123457",
        "title": "商品B",
        "price": 199.00
      }
    ],
    "total": 200
  }
}

这不是数据接口(静态资源):

json 复制代码
https://cdn.example.com/app.js
https://img.example.com/logo.png
步骤 4:复制接口 URL 参数)或 Form Data(POST 参数)

示例:

json 复制代码
Request URL: https://api.example.com/products/search
Method: GET
Query String Parameters:
  page: 1
  pageSize: 20
  keyword: 手机
  sort: price_asc

🛠️ 实战:用 Requests 重写采集逻辑

第一步:验证接口可用性

用 Postman 或 Python 测试:

python 复制代码
import requests

url = 'https://api.example.com/products/search'
params = {
    'page': 1,
    'pageSize': 20,
    'keyword': '手机'
}

resp = requests.get(url, params=params, timeout=10)
print(resp.status_code)
print(resp.json())

如果返回 200 且有数据,说明接口可用!✅

第二步:分析分页逻辑

常见分页参数:

模式 1:页码 + 每页数量

python 复制代码
params = {
    'page': 1,        # 页码(从 1 或 0 开始)
    'pageSize': 20    # 每页数量
}

模式 2:偏移量 + 限制数量

python 复制代码
params = {
    'offset': 0,      # 偏移量(page-1 * limit)
    'limit': 20       # 每次取多少条
}

模式 3:游标分页

python 复制代码
params = {
    'cursor': 'abc123',  # 上一页的最后一条 ID
    'count': 20
}
第三步:循环采集所有页
python 复制代码
class APISpider:
    """基于 API 的爬虫(比 Playwright 快 10 倍)"""
    
    def __init__(self, base_url):
        self.base_url = base_url
        self.session = requests.Session()
        
        # 设置通用 headers(模拟浏览器)
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'application/json',
            'Referer': 'https://example.com'
        })
    
    def fetch_page(self, page, page_size=20):
        """
        获取单页数据
        
        Args:
            page: 页码
            page_size: 每页数量
        
        Returns:
            dict: {'items': [...], 'has_more': True/False}
        """
        params = {
            'page': page,
            'pageSize': page_size,
            'keyword': '手机'  # 根据实际需求调整
        }
        
        try:
            resp = self.session.get(
                self.base_url,
                params=params,
                timeout=10
            )
            resp.raise_for_status()
            
            data = resp.json()
            
            # 根据实际接口结构提取数据
            items = data.get('data', {}).get('items', [])
            total = data.get('data', {}).get('total', 0)
            
            # 判断是否还有下一页
            has_more = (page * page_size) < total
            
            return {
                'items': items,
                'has_more': has_more
            }
            
        except Exception as e:
            print(f"❌ 请求失败:{e}")
            return {'items': [], 'has_more': False}
    
    def crawl_all(self, max_pages=10):
        """采集所有页"""
        all_items = []
        page = 1
        
        while page <= max_pages:
            print(f"\n📄 正在采集第 {page} 页...")
            
            result = self.fetch_page(page)
            items = result['items']
            
            if not items:
                print("🛑 没有更多数据")
                break
            
            all_items.extend(items)
            print(f"   本页获得 {len(items)} 条数据(累计 {len(all_items)} 条)")
            
            if not result['has_more']:
                print("🛑 已到最后一页")
                break
            
            page += 1
            time.sleep(1)  # 礼貌延迟
        
        print(f"\n✅ 采集完成!共获得 {len(all_items)} 条数据")
        return all_items

# 使用示例
if __name__ == '__main__':
    spider = APISpider('https://api.example.com/products/search')
    items = spider.crawl_all(max_pages=10)
    
    # 保存结果
    import json
    with open('api_items.json', 'w', encoding='utf-8') as f:
        json.dump(items, f, ensure_ascii=False, indent=2)

⚠️ 新手常见坑

坑 1:缺少关键 Headers

现象:用浏览器能请求成功,代码却返回 403 或空数据。

原因:缺少必要的请求头(如 Referer、Token)。

解决:

python 复制代码
# 在 Network 面板复制所有 Request Headers
headers = {
    'User-Agent': '...',
    'Referer': 'https://example.com/products',
    'X-Requested-With': 'XMLHttpRequest',  # 表明是 Ajax 请求
    'Authorization': 'Bearer xxx'  # 如果需要登录
}

resp = requests.get(url, headers=headers)
坑 2:参数加密或签名

现象:接口需要 sign 参数,不知道怎么生成。

示例:

json 复制代码
https://api.example.com/search?keyword=手机&sign=a3f8c9d2e1b4...

解决方案:

方案 A(推荐):在 Network 面板找到 JS 文件,搜索 sign

javascript 复制代码
// 找到生成逻辑,用 Python 重写
function generateSign(params) {
    return md5(params.keyword + params.page + 'secret_key');
}

方案 B:用 Playwright 拦截请求,获取完整 URL

python 复制代码
def handle_route(route):
    print(f"📡 拦截到请求:{route.request.url}")
    route.continue_()

page.route('**/api/**', handle_route)
page.goto('https://example.com')

方案 C:实在不行,回到 Playwright

python 复制代码
# 但至少知道数据在哪个接口了,可以针对性等待
坑 3:接口返回数据不完整

现象:网页显示 20 条,接口只返回 10 条。

原因:可能有多个接口(如基础信息 + 详情)。

解决:

python 复制代码
# 先请求列表接口拿到 ID
list_items = fetch_list()

# 再批量请求详情接口
for item in list_items:
    detail = fetch_detail(item['id'])
    item.update(detail)

🚀 进阶技巧

技巧 1:用 Playwright 自动找接口

不想手动看 Network?让代码帮你:

python 复制代码
from playwright.sync_api import sync_playwright

def find_api_requests(url):
    """自动抓取页面的所有 API 请求"""
    api_requests = []
    
    def handle_response(response):
        # 只关注 JSON 响应
        if 'application/json' in response.headers.get('content-type', ''):
            api_requests.append({
                'url': response.url,
                'method': response.request.method,
                'status': response.status
            })
    
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        
        # 监听所有响应
        page.on('response', handle_response)
        
        # 打开页面(触发接口请求)
        page.goto(url, wait_until='networkidle')
        
        browser.close()
    
    return api_requests

# 使用
apis = find_api_requests('https://example.com/products')
for api in apis:
    print(f"🔗 {api['method']} {api['url']}")
技巧 2:字段映射(接口字段 vs 页面展示)

接口返回的字段名可能和页面不一样:

python 复制代码
def normalize_item(raw_item):
    """统一字段名"""
    return {
        'title': raw_item.get('productName') or raw_item.get('title'),
        'price': raw_item.get('salePrice') or raw_item.get('price'),
        'image': raw_item.get('mainImage') or raw_item.get('picUrl'),
        'url': f"https://example.com/item/{raw_item['productId']}"
    }
技巧 3:批量请求优化
python 复制代码
import concurrent.futures

def fetch_details_batch(ids, max_workers=5):
    """批量获取详情(并发)"""
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [executor.submit(fetch_detail, id) for id in ids]
        results = [f.result() for f in concurrent.futures.as_completed(futures)]
    return results

📊 完整案例:从 Playwright 到 Requests

第一步:用 Playwright 找接口
python 复制代码
# step1_find_api.py
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    
    # 监听网络请求
    def log_request(response):
        if '/api/' in response.url and response.status == 200:
            print(f"✅ 发现接口:{response.url}")
    
    page.on('response', log_request)
    page.goto('https://example.com/products')
    
    input("👀 观察完毕后按回车...")
    browser.close()
第二步:用 Requests 重写
python 复制代码
# step2_use_requests.py
import requests

def crawl_with_api():
    items = []
    
    for page in range(1, 11):
        url = 'https://api.example.com/products/search'
        params = {'page': page, 'pageSize': 20}
        
        resp = requests.get(url, params=params, timeout=10)
        data = resp.json()
        
        items.extend(data['data']['items'])
        print(f"第 {page} 页:{len(items)} 条")
        
        if not data['data']['hasMore']:
            break
    
    return items

items = crawl_with_api()
print(f"✅ 共采集 {len(items)} 条数据")

📝 小结

今天我们学会了降维打击的终极技巧

  1. 用 Network 面板找数据接口(核心技能)
  2. 分析接口参数(分页、筛选、排序)
  3. 用 Requests 替换 Playwright(速度快 10 倍)
  4. 处理加密签名(JS 逆向或拦截)

记住核心原则:能用接口就不用浏览器,能用 Requests 就不用 Playwright。先找接口,实在找不到再上自动化浏览器。

🎯 下一章预告

恭喜你完成第 7 章!现在你已经掌握了动态页面采集的核心技能------从 Playwright 基础到接口逆向,从滚动翻页到 API 降维打击。

下一章《第 8 章:项目实战与上线》,我们将进入实战环节------用前面学到的所有技术,搞定两个完整的真实项目:RSS 聚合器和信息聚合站。不仅要能跑,还要能上线、能定时运行、能监控告警!🚀

验收作业:找一个动态网站的数据接口,用 Requests 采集 200 条数据。把接口 URL 和代码发我看看!加油!

🌟 文末

好啦~以上就是本期 《Python爬虫实战》的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持! ❤️🔥

📌 专栏持续更新中|建议收藏 + 订阅

专栏 👉 《Python爬虫实战》,我会按照"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一篇都做到:

✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)

📣 想系统提升的小伙伴:强烈建议先订阅专栏,再按目录顺序学习,效率会高很多~

✅ 互动征集

想让我把【某站点/某反爬/某验证码/某分布式方案】写成专栏实战?

评论区留言告诉我你的需求,我会优先安排更新 ✅


⭐️ 若喜欢我,就请关注我叭~(更新不迷路)

⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)

⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)


免责声明:本文仅用于学习与技术研究,请在合法合规、遵守站点规则与 Robots 协议的前提下使用相关技术。严禁将技术用于任何非法用途或侵害他人权益的行为。

相关推荐
我送炭你添花2 小时前
Pelco KBD300A 模拟器:12.设备仿真与虚拟响应生成
python·自动化·运维开发
一晌小贪欢2 小时前
深入解析 Python 3.11 版本迭代:性能飞跃与更优雅的错误处理
python·python基础·python3·python3.11·python小白
理智.6292 小时前
根据requirements.txt 完成环境中的依赖库导入
python·conda·pip
Blossom.1182 小时前
用纯 NLP 打造「零样本」时序预测模型:文本化序列 + LLM 的实战路线
人工智能·python·深度学习·机器学习·自然语言处理·架构·transformer
小二·3 小时前
Python Web 开发进阶实战:AI 编排引擎 —— 在 Flask + Vue 中构建低代码机器学习工作流平台
前端·人工智能·python
sww_10263 小时前
智能问数系统(二):数据分析师Python
java·前端·python
wm10433 小时前
代码随想录第十天 栈和队列
开发语言·python
飞Link3 小时前
PyTorch 核心 API 完全手册:从基础张量到模型部署
人工智能·pytorch·python·深度学习·机器学习
Dxy12393102163 小时前
Python使用Playwright入门教程:从环境搭建到实战应用
开发语言·python·playwright