闲社

标题: 【教程】Puppeteer自动化抓取实战:零代码基础也能写的网页数据采集脚本 [打印本页]

作者: kai_va    时间: 3 小时前
标题: 【教程】Puppeteer自动化抓取实战:零代码基础也能写的网页数据采集脚本
【前言】

最近 GitHub Trending 上 Puppeteer 又火了,94K+ Star 的 Chrome/Firefox 自动化神器。很多兄弟想写爬虫但怕被封、怕写代码复杂,今天这篇手把手教你用 Puppeteer 写一个零依赖、防检测、带重试的网页数据采集脚本,全程 Node.js,复制粘贴就能跑。

【前置条件】



【步骤一:安装 Puppeteer】

打开终端,一行命令搞定:
  1. npm install puppeteer
复制代码

Puppeteer 会自动下载匹配的 Chromium 浏览器,不需要你手动安装 Chrome。如果下载慢,换国内镜像:
  1. npm config set puppeteer_download_host=https://npmmirror.com/mirrors
  2. npm install puppeteer
复制代码

【步骤二:写第一个采集脚本】

新建文件
  1. scraper.js
复制代码
,内容如下:
  1. const puppeteer = require('puppeteer');
  2. (async () => {
  3.   // 1. 启动浏览器(headless: true 表示无界面,后台跑)
  4.   const browser = await puppeteer.launch({ headless: true });
  5.   const page = await browser.newPage();
  6.   // 2. 设置 User-Agent,模拟真实浏览器
  7.   await page.setUserAgent(
  8.     'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36'
  9.   );
  10.   // 3. 设置视口,避免被识别为无头浏览器
  11.   await page.setViewport({ width: 1920, height: 1080 });
  12.   // 4. 打开目标页面
  13.   await page.goto('https://news.example.com/list', {
  14.     waitUntil: 'networkidle2', // 等网络空闲再开始
  15.     timeout: 30000
  16.   });
  17.   // 5. 提取数据(用 page.evaluate 在页面上下文中执行 JS)
  18.   const articles = await page.evaluate(() => {
  19.     const items = document.querySelectorAll('.news-item');
  20.     return Array.from(items).map(item => ({
  21.       title: item.querySelector('h2')?.innerText?.trim(),
  22.       link: item.querySelector('a')?.href,
  23.       summary: item.querySelector('.summary')?.innerText?.trim(),
  24.       date: item.querySelector('.date')?.innerText?.trim()
  25.     }));
  26.   });
  27.   console.log('采集到', articles.length, '条数据');
  28.   console.log(JSON.stringify(articles, null, 2));
  29.   // 6. 关闭浏览器
  30.   await browser.close();
  31. })();
复制代码

运行:
  1. node scraper.js
复制代码

【步骤三:增强版——防检测 + 自动重试】

很多网站会检测无头浏览器,升级脚本加入反检测:
  1. const puppeteer = require('puppeteer');
  2. async function scrapeWithRetry(url, maxRetries = 3) {
  3.   for (let attempt = 1; attempt  {
  4.         Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
  5.         Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3] });
  6.       });
  7.       await page.setUserAgent(
  8.         'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36'
  9.       );
  10.       await page.setViewport({ width: 1920, height: 1080 });
  11.       // 设置更真实的请求头
  12.       await page.setExtraHTTPHeaders({
  13.         'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  14.         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
  15.       });
  16.       await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
  17.       // 等 2-5 秒随机延迟,模拟人类阅读
  18.       await page.waitForTimeout(2000 + Math.random() * 3000);
  19.       const data = await page.evaluate(() => {
  20.         const items = document.querySelectorAll('.news-item');
  21.         return Array.from(items).map(item => ({
  22.           title: item.querySelector('h2')?.innerText?.trim(),
  23.           link: item.querySelector('a')?.href,
  24.           summary: item.querySelector('.summary')?.innerText?.trim()
  25.         })).filter(i => i.title);
  26.       });
  27.       await browser.close();
  28.       return data;
  29.     } catch (err) {
  30.       console.log(`第 ${attempt} 次尝试失败: ${err.message}`);
  31.       await browser.close();
  32.       if (attempt === maxRetries) throw err;
  33.       await new Promise(r => setTimeout(r, 5000 * attempt)); // 递增延迟
  34.     }
  35.   }
  36. }
  37. (async () => {
  38.   const result = await scrapeWithRetry('https://news.example.com/list');
  39.   console.log('最终采集结果:', JSON.stringify(result, null, 2));
  40. })();
复制代码

【步骤四:保存到文件 / 数据库】

采集完的数据存到 JSON 文件:
  1. const fs = require('fs');
  2. // 在 scrapeWithRetry 返回后添加:
  3. fs.writeFileSync('data.json', JSON.stringify(result, null, 2));
  4. console.log('已保存到 data.json');
复制代码

如果要存到数据库,用 SQLite 最简单:
  1. npm install better-sqlite3
复制代码
  1. const Database = require('better-sqlite3');
  2. const db = new Database('articles.db');
  3. db.exec(`
  4.   CREATE TABLE IF NOT EXISTS articles (
  5.     id INTEGER PRIMARY KEY AUTOINCREMENT,
  6.     title TEXT,
  7.     link TEXT,
  8.     summary TEXT,
  9.     created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  10.   )
  11. `);
  12. const insert = db.prepare('INSERT INTO articles (title, link, summary) VALUES (?, ?, ?)');
  13. result.forEach(item => insert.run(item.title, item.link, item.summary));
  14. console.log('已存入数据库');
复制代码

【常见问题】



【总结】

本文从安装到实战,完整走了一遍 Puppeteer 网页采集流程:



这套代码可以直接拿去改 selector 就能采集任何公开网页。GitHub 上 Puppeteer 94K+ Star 不是白给的,自动化测试、数据采集、截图生成都能用。有问题楼下交流,代码有 bug 直接贴错误日志。

参考:GitHub Trending 今日热门项目 puppeteer/puppeteer




欢迎光临 闲社 (https://www.xianshe.com/) Powered by Discuz! X5.0