You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyppeteer脚本点击下一页时报错,如何实现全页面机构信息采集?

解决Pyppeteer翻页爬取时的TimeoutError和NetworkError问题

我看了你爬取印度所得税局豁免机构列表时遇到的问题——翻到5-10页左右就报超时或者Target closed错误,这在爬取加载较慢的政府网站时很常见,主要是页面加载不稳定、等待逻辑不够严谨导致的,咱们来一步步修复:

错误原因分析

  • TimeoutError:点击下一页后,目标网站加载速度慢,默认30秒的等待时间不足以让元素完全显示;或者页面跳转后元素选择器的等待逻辑没有适配新页面的加载节奏。
  • NetworkError (Target closed):大多是因为页面跳转时,还没等浏览器完成上下文切换就执行了后续操作,导致连接中断;也可能是浏览器沙箱模式的稳定性问题。

修改后的稳定版代码

import asyncio
from pyppeteer import launch
from pyppeteer.errors import TimeoutError, NetworkError

url = "https://www.incometaxindia.gov.in/Pages/utilities/exempted-institutions.aspx"

async def fetch_table(link):
    # 初始化浏览器时添加稳定性配置,模拟真实浏览器环境
    browser = await launch(
        headless=False,
        args=[
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-gpu',
            '--window-size=1920,1080'
        ],
        defaultViewport=None
    )
    page = await browser.newPage()
    # 延长页面导航超时到60秒,适配慢加载网站
    await page.setDefaultNavigationTimeout(60000)
    # 等待网络空闲后再开始操作,确保页面完全加载
    await page.goto(link, waitUntil='networkidle2')

    page_number = 1
    while True:
        print(f"正在爬取第 {page_number} 页...")
        try:
            # 延长元素等待超时到60秒,确保元素加载完成
            await page.waitForSelector("h1.faqsno-heading", {'visible': True, 'timeout': 60000})
            # 用evaluate批量获取文本,比逐个查询更高效稳定
            institutions = await page.evaluate('''
                () => Array.from(document.querySelectorAll("h1.faqsno-heading div[id^='arrowex']"))
                    .map(elem => elem.innerText.trim())
            ''')
            for name in institutions:
                print(name)
            
            # 先等待下一页按钮可见且可点击,避免无效点击
            next_btn = await page.waitForSelector("[title='Next Page']", {'visible': True, 'timeout': 30000})
            # 检查按钮是否被禁用(最后一页的下一页按钮通常会禁用)
            is_disabled = await page.evaluate('btn => btn.disabled', next_btn)
            if is_disabled:
                print("已到达最后一页,停止爬取")
                break
            
            # 同时等待点击和页面跳转完成,确保页面完全切换后再继续
            await asyncio.gather(
                page.waitForNavigation(waitUntil='networkidle2'),
                next_btn.click()
            )
            page_number += 1

        except TimeoutError:
            print(f"第 {page_number} 页加载超时,尝试跳过")
            page_number += 1
            # 尝试刷新页面后继续,或者直接跳过
            try:
                await page.reload(waitUntil='networkidle2')
            except:
                pass
            continue
        except NetworkError:
            print(f"网络连接异常,重新加载当前页")
            await page.reload(waitUntil='networkidle2')
            continue
        except Exception as e:
            print(f"遇到未知错误: {str(e)}")
            break

    await browser.close()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(fetch_table(url))

关键改动说明

  1. 浏览器稳定性配置:添加--no-sandbox等参数避免沙箱模式的兼容性问题,设置完整窗口尺寸模拟真实用户访问
  2. 更合理的超时设置:把页面导航和元素等待超时延长到60秒,适配政府网站较慢的加载速度
  3. 严谨的等待逻辑:
    • 使用waitUntil='networkidle2'等待网络空闲,确保页面资源完全加载
    • 点击下一页时,用asyncio.gather同时等待点击和页面跳转,避免页面未切换就执行后续操作
    • 检查下一页按钮是否禁用,提前判断是否到达最后一页
  4. 高效的数据采集:用page.evaluate在浏览器端批量处理元素,减少Python和浏览器的通信次数,提升稳定性
  5. 针对性错误处理:对超时、网络错误分别处理,允许脚本自动恢复或跳过异常页面,保证整体爬取流程不中断

额外建议

目标网站可能有反爬机制,建议在翻页后添加短暂等待(比如await asyncio.sleep(2)),避免爬取速度过快被限制;如果还是出现问题,可以尝试切换为无头模式(headless=True),有时无头模式的稳定性更好。

内容的提问来源于stack exchange,提问作者robots.txt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:55:36