前端开发爬虫首选puppeteer

文章介绍了在大数据时代,前端开发者如何利用Node.js的Puppeteer库进行爬虫开发,以获取微博热搜为例,展示了如何设置代理、处理请求事件以及截图。提到Puppeteer作为前端友好的工具,可替代Python的Selenium,用于快速构建爬虫,同时建议对于复杂的反爬策略,可以结合Python的深度学习能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多前端同学可能对于爬虫不是很感冒,觉得爬虫需要用偏后端的语言,诸如 python 、php 等。当然这是在 nodejs 前了,nodejs 的出现,使得 Javascript 也可以用来写爬虫了。但这是大数据时代,数据的需求是不分前端还是后端的,既然由于 nodejs 强大的异步特性,让我们可以轻松以异步高并发去爬取网站。

img

这里会有一个问题吗,那就是前端程序员如果要开发爬虫是使用python还是使用puppeteer呢?如果想快速开发爬虫,还是驱动浏览器的方式比较好,我推荐用puppeteer,纯js环境,上手快,puppeteer直接驱动无头浏览器速度并不算慢。但是现在目标网站爬虫策略多种多样,即使是使用最简单的方式也要学习反爬策略的应对。如果遇到验证码识别等需要深度学习的,可以用python写这部分,然后nodejs和python进程间通信。

这里我们可以使用puppeteer简单的实现下爬虫,就以获取微博热搜为例子进行实践。

// 引入process和puppeteer模块
const process = require("process");
const puppeteer = require("puppeteer");

// 定义代理地址、延时时间和延时函数
const PROXY = "http://www.16yun.cn:80"; // 代理服务器(产品 www.16yun.cn)可以修改这个代理地址
const SLEEP = 5000; // 你可以修改这个延时时间(毫秒)
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// 定义一个异步函数view,接受一个URL和一个代理地址作为参数
async function view(url, proxy) {
  // 在view函数中,使用puppeteer.launch方法启动一个浏览器实例,并设置一些参数,如headless、ignoreHTTPSErrors、defaultViewport和args
  const browser = await puppeteer.launch({
    headless: true, // 设置为无头模式(不显示浏览器窗口)
    ignoreHTTPSErrors: true, // 忽略HTTPS错误
    defaultViewport: { width: 1280, height: 800 }, // 设置默认视口大小
    args: [`--proxy-server=${proxy}`], // 设置代理服务器地址
  });

  // 使用browser.newPage方法创建一个新的页面实例,并设置视口大小
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800 });

  // 使用page.on方法监听request事件,如果请求的资源类型是media,并且请求的URL以https://video.twimg.com/开头,则打印出请求的URL
  page.on("request", (request) => {
    if (
      request.resourceType() === "media" &&
      request.url().startsWith("https://weibo.com//")
    ) {
      console.log(request.url());
    }
  });

  // 使用page.goto方法访问传入的URL
  await page.goto(url);

  // 使用page.click方法点击页面上选择器为.r-1ndi9ce > div:nth-child(1) > div:nth-child(1) > span:nth-child(1) > span:nth-child(1) 的元素
  await page.click(
    ".r-1ndi9ce > div:nth-child(1) > div:nth-child(1) > span:nth-child(1) > span:nth-child(1)"
  );

  // 使用sleep函数等待一段时间(SLEEP)
  await sleep(SLEEP);

  // 使用page.screenshot方法截取页面图片并保存为debug.png文件
  await page.screenshot({ path: "debug.png" });

  // 使用browser.close方法关闭浏览器实例
  await browser.close();
}

// 最后,在主程序中,获取命令行参数中的第一个参数作为URL,并调用view函数。
const url = process.argv[2]; // 获取命令行参数中的第一个参数作为URL

if (url) {
  view(url, PROXY); 
} else {
  console.log("请输入一个有效的URL"); 
}

puppeteer相当于python selenium 控制无头Chrome,作为前端程序员,那python虽然语法容易但毕竟学的也比较多,所以建议可以试试puppeteer。

### 如何使用 Puppeteer 设置浏览器默认下载路径 在 Puppeteer 中,默认情况下无法直接通过 API 配置文件的下载路径,因为 Chromium 的设计不支持直接修改下载目录。然而,可以通过设置实验性的 Chrome 标志 `--download-path` 或者监听页面事件并手动处理下载行为来间接实现这一目标。 以下是具体实现方式: #### 使用实验性标志配置下载路径 可以尝试通过启动选项中的 `args` 参数指定自定义的命令行标志来更改下载路径。虽然这种方法并非完全可靠,但在某些场景下可能有效。 ```javascript const puppeteer = require('puppeteer'); (async () => { const downloadPath = '/custom/path/to/downloads'; // 自定义下载路径 const browser = await puppeteer.launch({ headless: false, args: [ `--download-path=${downloadPath}` // 尝试设置下载路径 ] }); const page = await browser.newPage(); await page.goto('https://example.com/file-to-download'); console.log(`File will be downloaded to ${downloadPath}`); await browser.close(); })(); ``` 需要注意的是,上述方法依赖于特定版本的 Chromium 支持,并且不一定适用于所有环境[^1]。 --- #### 手动捕获下载链接并保存到指定位置 更可靠的解决方案是拦截下载请求并将文件保存到期望的位置。这通常涉及以下几个步骤: 1. 捕获页面上的点击或其他触发下载的行为。 2. 获取下载 URL 并通过 Node.js 文件系统模块 (`fs`) 下载文件。 3. 将文件存储至指定路径。 下面是一个完整的示例代码: ```javascript const fs = require('fs'); const axios = require('axios'); // 用于发起 HTTP 请求 const puppeteer = require('puppeteer'); (async () => { const customDownloadDir = './downloads'; if (!fs.existsSync(customDownloadDir)) { fs.mkdirSync(customDownloadDir); } const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); // 跳转到包含下载按钮的目标网页 await page.goto('https://example.com/page-with-file-link'); // 监听 "response" 事件以检测下载资源 page.on('response', async response => { const url = response.url(); // 判断是否为要下载的内容(可以根据 MIME 类型判断) if (url.includes('.pdf') || url.includes('.zip')) { // 假设我们要下载 PDF 和 ZIP 文件 try { const fileStream = fs.createWriteStream(`${customDownloadDir}/${new Date().getTime()}-${url.split('/').pop()}`); const writer = new Promise((resolve, reject) => { fileStream.on('finish', resolve); fileStream.on('error', reject); }); const responsePromise = axios({ method: 'GET', url, responseType: 'stream' }).then(response => { response.data.pipe(fileStream); return response; }); await Promise.all([writer, responsePromise]); console.log(`File saved successfully at: ${fileStream.path}`); } catch (err) { console.error('Error downloading the file:', err.message); } } }); // 触发下载操作(例如模拟点击某个按钮) await page.click('#downloadButton'); await new Promise(resolve => setTimeout(resolve, 5000)); // 等待几秒确保完成下载 await browser.close(); })(); ``` 在此示例中,通过监听响应事件以及结合 Axios 库实现了对文件的手动管理[^4]。 --- ### 注意事项 - 如果需要更高的兼容性和稳定性,建议采用第二种方案(即手动控制下载流程),因为它不受制于底层浏览器的具体实现细节。 - 对于生产环境中运行的任务,请务必验证所使用的 Chromium 版本及其特性支持情况[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值