使用puppeteer库编写的爬虫程序

Embassy是基于aiohttp的异步库,适合处理普通的HTTP请求,而Puppeteer是控制Headless Chrome的,适合需要处理JavaScript渲染的页面。用户可能遇到了需要抓取动态生成内容的情况,或者之前的Embassy示例无法获取到完整的数据,所以转向Puppeteer。

以下是一个使用 Pyppeteer (Python 版本的 Puppeteer) 编写的网络爬虫示例,用于处理需要 JavaScript 渲染的页面:

先安装依赖

bash 复制代码
pip install pyppeteer

示例代码:动态页面爬虫

python 复制代码
import asyncio
from urllib.parse import urljoin
from pyppeteer import launch
from pyppeteer.errors import TimeoutError

class PuppeteerCrawler:
    def __init__(self, headless=True, timeout=30):
        self.headless = headless  # 是否无头模式
        self.timeout = timeout    # 页面加载超时时间
        self.browser = None       # 浏览器实例
        self.visited = set()      # 已访问的URL

    async def init_browser(self):
        """启动浏览器实例"""
        self.browser = await launch(
            headless=self.headless,
            args=['--no-sandbox', '--disable-setuid-sandbox']
        )

    async def crawl(self, start_url):
        """启动爬虫"""
        if not self.browser:
            await self.init_browser()
        
        page = await self.browser.newPage()
        await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36')
        
        try:
            await self.process_page(page, start_url)
        finally:
            await page.close()
            await self.browser.close()

    async def process_page(self, page, url):
        """处理单个页面"""
        if url in self.visited:
            return
        self.visited.add(url)

        try:
            # 导航到页面
            await page.goto(url, {'timeout': self.timeout * 1000})
            await page.waitForSelector('body', timeout=self.timeout*1000)  # 等待页面加载

            # 获取页面内容
            content = await page.content()
            
            # 示例:提取标题
            title = await page.title()
            print(f'Scraped: {url}')
            print(f'Title: {title}')

            # 提取链接
            links = await self.extract_links(page, url)
            for link in links:
                if link not in self.visited:
                    new_page = await self.browser.newPage()
                    await self.process_page(new_page, link)
                    await new_page.close()

        except TimeoutError:
            print(f'Timeout loading {url}')
        except Exception as e:
            print(f'Error processing {url}: {str(e)}')

    async def extract_links(self, page, base_url):
        """提取页面中的链接"""
        return await page.evaluate('''(base_url) => {
            return Array.from(document.querySelectorAll('a'))
                .map(a => new URL(a.href, base_url).href)
                .filter(href => href.startsWith('http'));
        }''', base_url)

async def main():
    crawler = PuppeteerCrawler(headless=True)  # headless=False 可以显示浏览器
    await crawler.crawl('https://example.com')

if __name__ == '__main__':
    asyncio.run(main())

代码说明

  1. 核心功能

    • 使用 pyppeteer 控制 Chromium 浏览器
    • 支持 JavaScript 渲染的动态页面
    • 自动等待页面元素加载 (waitForSelector)
    • 支持递归爬取页面链接
  2. 关键配置

    python 复制代码
    launch(
        headless=True,  # 无头模式(不显示浏览器界面)
        args=[
            '--no-sandbox',
            '--disable-setuid-sandbox'  # Linux 系统需要
        ]
    )
  3. 优势场景

    • 需要执行 JavaScript 的 SPA (单页应用)
    • 需要处理懒加载内容
    • 需要模拟用户交互(点击、滚动等)
    • 需要生成页面截图/PDF

高级功能扩展

1. 页面截图
python 复制代码
await page.screenshot({'path': 'screenshot.png', 'fullPage': True})
2. 执行自定义 JavaScript
python 复制代码
dimensions = await page.evaluate('''() => {
    return {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
    }
}''')
3. 处理弹窗
python 复制代码
page.on('dialog', lambda dialog: dialog.dismiss())
4. 设置代理
python 复制代码
await page.authenticate({
    'username': 'proxy_user',
    'password': 'proxy_pass'
})

注意事项

  1. 性能优化

    • 复用浏览器实例 (browser.newPage() 而不是频繁启动)

    • 禁用图片加载:

      python 复制代码
      await page.setRequestInterception(True)
      page.on('request', lambda req: req.abort() 
          if req.resourceType() == 'image' else req.continue_())
  2. 反反爬策略

    • 使用随机 User-Agent
    • 添加随机延迟 (await asyncio.sleep(random.uniform(1, 3)))
    • 使用代理池
  3. 资源管理

    • 及时关闭页面 (await page.close())
    • 处理内存泄漏
    • 监控浏览器进程

如果需要处理更复杂的场景(如登录验证、验证码识别),可以结合其他库(如 python-anticaptcha)使用。

相关推荐
冷雨夜中漫步8 小时前
Python快速入门(6)——for/if/while语句
开发语言·经验分享·笔记·python
郝学胜-神的一滴8 小时前
深入解析Python字典的继承关系:从abc模块看设计之美
网络·数据结构·python·程序人生
百锦再8 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
吠品9 小时前
企业信任基石OV SSL证书
网络协议·https·ssl
暖馒10 小时前
Modbus应用层协议的深度剖析
网络·网络协议·c#·wpf·智能硬件
喵手10 小时前
Python爬虫实战:旅游数据采集实战 - 携程&去哪儿酒店机票价格监控完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集结果csv导出·旅游数据采集·携程/去哪儿酒店机票价格监控
2501_9449347310 小时前
高职大数据技术专业,CDA和Python认证优先考哪个?
大数据·开发语言·python
helloworldandy10 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
开源技术11 小时前
DNS详解——域名是如何解析的
http
肖永威12 小时前
macOS环境安装/卸载python实践笔记
笔记·python·macos