Python爬虫翻页案例如何实现翻页爬取

wen python案例 24

Python爬虫翻页案例:从入门到精通,6种高效翻页策略实战详解

目录导读

  1. 翻页爬取的核心逻辑
  2. 常见翻页模式与识别技巧
  3. 基于URL参数的翻页(静态翻页)
  4. 基于AJAX请求的翻页(动态翻页)
  5. 模拟点击“加载更多”按钮翻页
  6. 处理分页中的JavaScript滚动翻页
  7. 翻页爬虫的常见错误与解决方法
  8. SEO优化与反爬策略应对
  9. 问答专区
  10. 总结与最佳实践

翻页爬取的核心逻辑

在Web数据抓取中,翻页是最常见的需求之一,无论你是抓取电商商品列表、新闻列表还是论坛帖子,几乎所有分页数据都需要通过翻页逻辑来完整获取。

Python爬虫翻页案例如何实现翻页爬取

核心流程

  1. 分析目标网站的分页机制(URL参数、POST请求、AJAX加载、滚动加载等)
  2. 构造翻页请求(拼接URL、传递参数、处理cookie)
  3. 解析每一页的HTML/JSON数据
  4. 循环执行直到最后一页或满足停止条件

与单页爬虫相比,翻页爬虫需要额外处理页数控制请求间隔去重异常重试


常见翻页模式与识别技巧

类型 特征 示例
URL参数翻页 page=1, page=2 ... 博客列表、新闻网站
表单POST翻页 提交page参数到后端 一些B2B平台
AJAX动态加载 请求JSON数据,前端渲染 电商商品列表(API)
“加载更多”按钮 点击后追加内容 社交媒体、评论区
滚动无限加载 监听滚动事件,动态追加 知乎、微博
JavaScript分页组件 复杂前端框架实现的分页 后台管理系统

识别技巧

  • 打开开发者工具(F12)→ 网络(Network)选项卡
  • 点击翻页按钮,观察请求列表
  • 查看是XHR请求(AJAX)还是文档(Document)请求
  • 提取URL或请求体中的page/offset参数

案例一:基于URL参数的翻页(静态翻页)

这是最简单、最常见的翻页模式,以抓取某个新闻网站为例,URL模式为:
https://example.com/news?page=1

Python代码示例

import requests
from bs4 import BeautifulSoup
import time
def crawl_news(base_url, max_pages=10):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    all_articles = []
    for page in range(1, max_pages + 1):
        url = f"{base_url}?page={page}"
        try:
            response = requests.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            soup = BeautifulSoup(response.text, 'html.parser')
            # 提取文章列表(根据实际网站调整选择器)
            articles = soup.select('.article-item .title a')
            for a in articles:
                all_articles.append({
                    'title': a.get_text(strip=True),
                    'link': a['href']
                })
            print(f"第{page}页完成,获取到{len(articles)}篇文章")
            time.sleep(1)  # 礼貌性延时
        except Exception as e:
            print(f"第{page}页出错: {e}")
            continue
    return all_articles

关键点

  • 使用f-string动态拼接URL
  • 设置time.sleep()避免请求过快被封
  • 使用try-except处理网络异常

案例二:基于AJAX请求的翻页(动态翻页)

现代网站常通过AJAX加载数据,打开开发者工具 → Network → XHR,找到返回JSON的请求。

识别特征:请求返回的不是HTML,而是JSON格式的数据。

示例代码(抓取某电商API)

import requests
import json
def scrape_product_api(api_url, total_pages=20):
    headers = {
        'User-Agent': 'Mozilla/5.0',
        'Accept': 'application/json',
        'Referer': 'https://example.com/'
    }
    products = []
    for page in range(1, total_pages + 1):
        params = {
            'page': page,
            'size': 20,
            'sort': 'price_asc'
        }
        try:
            response = requests.get(api_url, headers=headers, params=params, timeout=10)
            data = response.json()
            # 假设数据在data['items']中
            for item in data.get('items', []):
                products.append({
                    'id': item['id'],
                    'name': item['name'],
                    'price': item['price']
                })
            # 检查是否还有下一页(根据返回的总页数判断)
            if page >= data.get('totalPages', total_pages):
                break
            print(f"API第{page}页完成")
            time.sleep(0.5)
        except Exception as e:
            print(f"获取第{page}页失败: {e}")
            continue
    return products

注意事项

  • 需要模拟Referer和Cookies,特别是需要登录的网站
  • 解析返回的JSON结构,找到总页数、总记录数等终止条件
  • 注意分页参数可能是offsetpageNostart等不同命名

案例三:模拟点击“加载更多”按钮翻页

有些网站使用“加载更多”按钮,需要发送POST请求或使用Selenium模拟点击。

使用Selenium方案

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def scrape_load_more(url, max_clicks=50):
    driver = webdriver.Chrome()
    driver.get(url)
    all_items = []
    click_count = 0
    while True:
        # 等待内容加载
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '.item'))
        )
        # 提取当前可见的所有项
        items = driver.find_elements(By.CSS_SELECTOR, '.item')
        for item in items:
            text = item.text
            if text not in all_items:  # 去重
                all_items.append(text)
        # 查找“加载更多”按钮
        try:
            load_more_btn = driver.find_element(By.CSS_SELECTOR, '.load-more-btn')
            if load_more_btn.is_displayed():
                load_more_btn.click()
                click_count += 1
                print(f"已点击{click_count}次,获取到{len(all_items)}条数据")
                time.sleep(2)  # 等待新内容加载
            else:
                break
        except:
            print("没有更多按钮,结束")
            break
        # 安全限制,防止无限循环
        if click_count >= max_clicks:
            break
    driver.quit()
    return all_items

优缺点分析

  • 优点:能处理复杂的前端交互
  • 缺点:速度慢,消耗资源,容易被反爬

案例四:处理分页中的JavaScript滚动翻页

无限滚动翻页需要模拟滚动行为。

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
def scrape_infinite_scroll(url, max_scrolls=30):
    driver = webdriver.Chrome()
    driver.get(url)
    last_height = driver.execute_script("return document.body.scrollHeight")
    scroll_count = 0
    all_data = []
    while True:
        # 滚动到底部
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(2)  # 等待数据加载
        # 计算新高度
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            print("已滚动到底部")
            break
        last_height = new_height
        scroll_count += 1
        # 提取新加载的数据(示例选择器)
        items = driver.find_elements(By.CSS_SELECTOR, '.post-item')
        for item in items:
            title = item.find_element(By.CSS_SELECTOR, '.title').text
            all_data.append(title)
        print(f"已滚动{scroll_count}次,获取到{len(all_data)}条数据")
        if scroll_count >= max_scrolls:
            break
    driver.quit()
    return list(set(all_data))  # 去重

优化建议

  • 使用WebDriverWait等待特定元素出现,替代固定时间
  • 检测页面底部是否有“加载完成”标志

翻页爬虫的常见错误与解决方法

错误类型 现象 解决方案
参数错误 翻页后返回相同内容 检查分页参数是否正确、是否需要有数据
反爬拦截 出现验证码、503错误 添加User-Agent、Cookie、代理IP
动态页面 无法获取渲染后内容 使用Selenium/Playwright渲染JS
频率限制 请求被临时封禁 降低请求速率,使用随机延时
内存溢出 处理大量数据时崩溃 使用生成器、分批写入文件/数据库
编码问题 中文乱码 设置response.encoding='utf-8'

调试技巧

  • 先用curlPostman测试单个请求
  • 打印每次请求的URL和状态码
  • 保存中间页面HTML用于分析

SEO优化与反爬策略应对

如何让爬虫更符合SEO规范?

  • 尊重robots.txt:爬取前检查https://example.com/robots.txt
  • 设置合理延时:建议1-3秒间隔,模拟人类浏览行为
  • 标识爬虫身份:在User-Agent中添加公司名称或用途
  • 避免重复请求:记录已爬取的URL,防止循环抓取

应对常见反爬措施

  1. IP限制:使用代理池(免费/付费代理轮换)
  2. Cookie验证:使用Session对象保持会话
  3. 验证码:接入打码平台或机器学习OCR
  4. 请求头校验:模拟完整的请求头(包括Referer、Origin)

问答专区

Q1:如何判断翻页是否到了最后一页?
A:检查返回数据是否为空,或返回的JSON中包含hasNext: falsetotalPages字段,对于HTML页面,查找是否有“下一页”按钮的disabled属性或不存在。

Q2:翻页爬虫被IP封禁怎么办?
A:

  • 降低请求速率(time.sleep(3-5))
  • 使用代理IP池(推荐免费资源:爬虫代理、芝麻代理等)
  • 添加随机User-Agent
  • 改用Selenium模拟真实浏览器

Q3:遇到需要登录的翻页怎么办?
A:

  • 手动登录后获取Cookie,在请求中携带
  • 使用Selenium模拟登录,保存Session
  • 针对API请求,查看是否需要Token或Authorization头部

Q4:动态加载的翻页数据如何解析更高效?
A:优先使用API接口,直接抓取JSON数据,比Selenium快10倍以上,通过浏览器开发者工具找到真实请求的URL和参数。

Q5:翻页爬取的数据怎么存储?
A:

  • 小规模数据:CSV/Excel
  • 中规模数据:SQLite/MongoDB
  • 大规模数据:分布式存储 + MySQL + Redis缓存

总结与最佳实践

翻页爬取是Python爬虫的进阶技能,掌握不同翻页模式的识别和处理方法至关重要,以下是关键建议:

  1. 先分析,后编码:用浏览器开发者工具分析网络请求再动手
  2. 优先选择API:JSON接口比HTML解析稳定100倍
  3. 优雅地处理异常:设置重试机制,记录失败页码
  4. 尊重规则:设置合理延时,遵守robots.txt
  5. 代码模块化:将分页逻辑独立封装,便于复用和测试
  6. 数据去重:使用集合(Set)或数据库唯一索引避免重复

无论是基于URL参数的静态翻页,还是复杂的AJAX/滚动翻页,核心思想都是找到翻页规律 → 模拟请求 → 解析数据 → 循环处理,掌握了这些案例,你可以应对90%以上的翻页场景。

爬虫技术是一把双刃剑,请合法、合规地使用,不要对目标服务器造成过大压力。

抱歉,评论功能暂时关闭!