Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Node:使用Puppeteer完成一次复杂的爬虫

Node:使用Puppeteer完成一次复杂的爬虫

作者头像
MrTreasure
发布于 2018-05-10 03:19:03
发布于 2018-05-10 03:19:03
3.5K00
代码可运行
举报
文章被收录于专栏:不止是前端不止是前端
运行总次数:0
代码可运行

架构图

Puppeteer架构图

  • Puppeteer 通过 devTools 与 browser 通信
  • Browser 一个可以拥有多个页面的浏览器(chroium)实例
  • Page 至少含有一个 Frame 的页面
  • Frame 至少还有一个用于执行 javascript 的执行环境,也可以拓展多个执行环境

前言

最近想要入手一台台式机,笔记本的i5在打开网页和vsc的时候有明显卡顿的情况,因此打算配1台 i7 + GTX1070TI or GTX1080TI的电脑,直接在淘宝上搜需要翻页太多,并且图片太多,脑容量接受不了,因此想爬一些数据,利用图形化分析一下最近价格的走势。因此写了一个用Puppeteer写了一个爬虫爬去相关数据。

什么是Puppeteer?

Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.

简而言之,这货是一个提供高级API的node库,能够通过devtool控制headless模式的chrome或者chromium,它可以在headless模式下模拟任何的人为操作。

和cheerio的区别

cherrico本质上只是一个使用类似jquery的语法操作HTML文档的库,使用cherrico爬取数据,只是请求到静态的HTML文档,如果网页内部的数据是通过ajax动态获取的,那么便爬去不到的相应的数据。而Puppeteer能够模拟一个浏览器的运行环境,能够请求网站信息,并运行网站内部的逻辑。然后再通过WS协议动态的获取页面内部的数据,并能够进行任何模拟的操作(点击、滑动、hover等),并且支持跳转页面,多页面管理。甚至能注入node上的脚本到浏览器内部环境运行,总之,你能对一个网页做的操作它都能做,你不能做的它也能做。

开始

本文不是一个手把手教程,因此需要你有基本的Puppeteer API常识,如果不懂,请先看看官方介绍 Puppeteer官方站点 PuppeteerAPI

首先我们观察要爬去的网站信息 GTX1080 这是我们要爬取的淘宝网页,只有中间的商品项目是我们需要爬取的内容,仔细分析它的结构,相信一个前端都有这样的能力。

我使用的Typescript,能够获得完整的Puppetter及相关库的API提示,如果你不会TS,只需要将相关的代码换成ES的语法就好了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 引入一些需要用到的库以及一些声明
import * as puppeteer from 'puppeteer' // 引入Puppeteer
import mongo from '../lib/mongoDb' // 需要用到的 mongodb库,用来存取爬取的数据
import chalk from 'chalk' // 一个美化 console 输出的库

const log = console.log // 缩写 console.log
const TOTAL_PAGE = 50 // 定义需要爬取的网页数量,对应页面下部的跳转链接

// 定义要爬去的数据结构
interface IWriteData { 
  link: string // 爬取到的商品详情链接
  picture: string // 爬取到的图片链接
  price: number // 价格,number类型,需要从爬取下来的数据进行转型
  title: string // 爬取到的商品标题
}

// 格式化的进度输出 用来显示当前爬取的进度
function formatProgress (current: number): string { 
  let percent = (current / TOTAL_PAGE) * 100
  let done = ~~(current / TOTAL_PAGE * 40)
  let left = 40 - done
  let str = `当前进度:[${''.padStart(done, '=')}${''.padStart(left, '-')}]   ${percent}%`
  return str
}

接下来我们开始进入到爬虫的主要逻辑

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 因为我们需要用到大量的 await 语句,因此在外层包裹一个 async function
async function main() {
  // Do something
}
main()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 进入代码的主逻辑
async function main() {
  // 首先通过Puppeteer启动一个浏览器环境
  const browser = await puppeteer.launch()
  log(chalk.green('服务正常启动'))
  // 使用 try catch 捕获异步中的错误进行统一的错误处理
  try {
    // 打开一个新的页面
    const page = await browser.newPage()
    // 监听页面内部的console消息
    page.on('console', msg => {
      if (typeof msg === 'object') {
        console.dir(msg)
      } else {
        log(chalk.blue(msg))
      }
    })

    // 打开我们刚刚看见的淘宝页面
    await page.goto('https://s.taobao.com/search?q=gtx1080&imgfile=&js=1&stats_click=search_radio_all%3A1&initiative_id=staobaoz_20180416&ie=utf8')
    log(chalk.yellow('页面初次加载完毕'))

    // 使用一个 for await 循环,不能一个时间打开多个网络请求,这样容易因为内存过大而挂掉
    for (let i = 1; i <= TOTAL_PAGE; i++) {
      // 找到分页的输入框以及跳转按钮
      const pageInput = await page.$(`.J_Input[type='number']`)
      const submit = await page.$('.J_Submit')
      // 模拟输入要跳转的页数
      await pageInput.type('' + i)
      // 模拟点击跳转
      await submit.click()
      // 等待页面加载完毕,这里设置的是固定的时间间隔,之前使用过page.waitForNavigation(),但是因为等待的时间过久导致报错(Puppeteer默认的请求超时是30s,可以修改),因为这个页面总有一些不需要的资源要加载,而我的网络最近日了狗,会导致超时,因此我设定等待2.5s就够了
      await page.waitFor(2500)

      // 清除当前的控制台信息
      console.clear()
      // 打印当前的爬取进度
      log(chalk.yellow(formatProgress(i)))
      log(chalk.yellow('页面数据加载完毕'))

      // 处理数据,这个函数的实现在下面
      await handleData()
      // 一个页面爬取完毕以后稍微歇歇,不然太快淘宝会把你当成机器人弹出验证码(虽然我们本来就是机器人)
      await page.waitFor(2500)
    }

    // 所有的数据爬取完毕后关闭浏览器
    await browser.close()
    log(chalk.green('服务正常结束'))

    // 这是一个在内部声明的函数,之所以在内部声明而不是外部,是因为在内部可以获取相关的上下文信息,如果在外部声明我还要传入 page 这个对象
    async function handleData() {
      // 现在我们进入浏览器内部搞些事情,通过page.evaluate方法,该方法的参数是一个函数,这个函数将会在页面内部运行,这个函数的返回的数据将会以Promise的形式返回到外部 
      const list = await page.evaluate(() => {
        
        // 先声明一个用于存储爬取数据的数组
        const writeDataList: IWriteData[] = []

        // 获取到所有的商品元素
        let itemList = document.querySelectorAll('.item.J_MouserOnverReq')
        // 遍历每一个元素,整理需要爬取的数据
        for (let item of itemList) {
          // 首先声明一个爬取的数据结构
          let writeData: IWriteData = {
            picture: undefined,
            link: undefined,
            title: undefined,
            price: undefined
          }

          // 找到商品图片的地址
          let img = item.querySelector('img')
          writeData.picture = img.src

          // 找到商品的链接
          let link: HTMLAnchorElement = item.querySelector('.pic-link.J_ClickStat.J_ItemPicA')
          writeData.link = link.href

          // 找到商品的价格,默认是string类型 通过~~转换为整数number类型
          let price = item.querySelector('strong')
          writeData.price = ~~price.innerText
          
          // 找到商品的标题,淘宝的商品标题有高亮效果,里面有很多的span标签,不过一样可以通过innerText获取文本信息
          let title: HTMLAnchorElement = item.querySelector('.title>a')
  
          writeData.title = title.innerText

          // 将这个标签页的数据push进刚才声明的结果数组
          writeDataList.push(writeData)
        }
        // 当前页面所有的返回给外部环境
        return writeDataList
        
      })
      // 得到数据以后写入到mongodb
      const result = await mongo.insertMany('GTX1080', list)

      log(chalk.yellow('写入数据库完毕'))
    }

  } catch (error) {
    // 出现任何错误,打印错误消息并且关闭浏览器
    console.log(error)
    log(chalk.red('服务意外终止'))
    await browser.close()
  } finally {
    // 最后要退出进程
    process.exit(0)
  }
}

思考

  1. 为什么使用Typescript? 因为Typescript就是好用啊,我也背不住Puppeteer的全部API,也不想每一个都查,所以使用TS就能智能提醒了,也能避免因为拼写导致的低级错误。基本上用了TS以后,敲代码都能一遍过

puppeteer.png

  1. 爬虫的性能问题? 因为Puppeteer会启动一个浏览器,执行内部的逻辑,所以占用的内存是蛮多的,看了看控制台,这个node进程大概占用300MB左右的内存。 我的页面是一个个爬的,如果想更快的爬取可以启动多个进程,注意,V8是单线程的,所以在一个进程内部打开多个页面是没有意义的,需要配置不同的参数打开不同的node进程,当然也可以通过node的cluster(集群)实现,本质都是一样的 我在爬取的过程中也设置了不同的等待时间,一方面是为了等待网页的加载,一方面避免淘宝识别到我是爬虫弹验证码
  2. Puppeteer的其它功能 这里仅仅利用了Puppeteer的一些基本特性,实际上Puppeteer还有更多的功能。比如引入node上的处理函数在浏览器内部执行,将当前页面保存为pdf或者png图片。并且还可以通过const browser = await puppeteer.launch({ headless: false })启动一个带界面效果的浏览器,你可以看见你的爬虫是如何运作的。此外一些需要登录的网站,如果你不想识别验证码委托第三方进行处理,你也可以关闭headless,然后在程序中设置等待时间,手动完成一些验证从而达到登录的目的。 当然google制作了一个这么牛逼的库可不只是用来做爬虫爬取数据的,这个库也用作于一些自动化的性能分析、界面测试、前端网站监控
  3. 一些其它方面的思考 总得来说制作爬虫爬取数据是一项较为复杂并考察多项基本功的练习项目,在这个爬虫里多次使用到了async,这就需要对async、Promise等相关知识充分的了解。在分析DOM收集数据时,也多次利用了原生的方法获取DOM属性(如果网站有jquery也可以直接用,没有的话需要外部注入,在typescript下需要进行一些配置,避免报错未识别的$变量,这样就可以通过jquery语法操作DOM),考察了对DOM相关API的熟练程度。 另外这只是一个面向过程的编程,我们完全可以将它封装为一个类进行操作,这也考察了对ES的OOP理解

最后

本文的源代码Github,喜欢的朋友给个star吧

以上都是我瞎编的

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.04.16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
大众点评作为中国领先的本地生活服务平台,不仅是消费者获取商家信息和用户评价的重要工具,同时也是商家推广的关键渠道。通过优质的内容呈现和精准的用户推荐,大众点评能够为商家带来显著的流量提升和品牌曝光,成为商业竞争中不可忽视的资源。
jackcode
2024/11/25
1810
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
自动化 Web 性能分析之 Puppeteer 爬虫实践
通过上篇文章《自动化 Web 性能优化分析方案》的分享想必大家对“百策系统”有了初步的了解。本文将向大家介绍自动化性能分析使用的核心库——Puppeteer,并结合页面登录场景,介绍 Puppeteer 在百策系统中的应用。
政采云前端团队
2019/12/20
3.6K0
自动化 Web 性能分析之 Puppeteer 爬虫实践
前端开发爬虫首选puppeteer
很多前端同学可能对于爬虫不是很感冒,觉得爬虫需要用偏后端的语言,诸如 python 、php 等。当然这是在 nodejs 前了,nodejs 的出现,使得 Javascript 也可以用来写爬虫了。但这是大数据时代,数据的需求是不分前端还是后端的,既然由于 nodejs 强大的异步特性,让我们可以轻松以异步高并发去爬取网站。
小白学大数据
2023/03/13
1.4K0
如何利用 Puppeteer 的 Evaluate 函数操作网页数据
在现代的爬虫技术中,Puppeteer 因其强大的功能和灵活性而备受青睐。Puppeteer 是一个用于控制 Chromium 或 Chrome 浏览器的 Node.js 库,提供了丰富的 API 接口,能够帮助开发者高效地处理动态网页数据。本文将重点讲解 Puppeteer 的 evaluate 函数,结合代理 IP 技术,演示如何采集目标网站(如界面新闻)上的文章标题和摘要。
jackcode
2024/11/21
1660
如何利用 Puppeteer 的 Evaluate 函数操作网页数据
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
在网络数据爬取中,如何精准、有效地抓取网页中的关键元素是核心问题之一。尤其对于动态网页来说,JavaScript渲染的内容无法通过传统的静态爬虫工具(如 requests、BeautifulSoup 等)获取。因此,使用能够控制浏览器的自动化工具 Puppeteer 就成了一种理想选择。
jackcode
2024/11/19
1980
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
使用Node.js爬取任意网页资源并输出高质量PDF文件到本地~
中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。
Peter谭金杰
2019/08/02
3.3K0
TypeScript 爬虫实践:选择最适合你的爬虫工具
今天我们将探讨如何使用 TypeScript 构建网络爬虫。网络爬虫是一种强大的工具,可以帮助我们从互联网上收集数据,进行分析和挖掘。而 TypeScript,则是一种类型安全的 JavaScript 超集,它可以让我们在编写 JavaScript 代码时享受到更严格的类型检查和更好的开发体验。本文将介绍如何选择最适合你的网络爬虫工具,并分享一些实用的案例。
小白学大数据
2024/05/16
4280
Puppeteer教程:使用CSS选择器点击和爬取动态数据
在现代的网页中,许多数据是通过JavaScript动态加载的,这使得传统的爬虫工具(如requests或BeautifulSoup)无法获取到这些数据。因此,为了更好地处理动态网站的数据爬取,我们需要使用像Puppeteer这样的浏览器自动化工具。
jackcode
2024/11/14
2680
Puppeteer教程:使用CSS选择器点击和爬取动态数据
前端人的爬虫工具【Puppeteer】
Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,同时还有 Headless Chrome。用来模拟 Chrome 浏览器的运行。它提供了高级API来通过 DevTools 协议控制无头 Chrome 或 Chromium ,它也可以配置为使用完整(非无头)Chrome 或 Chromium。
Snine
2022/02/11
3.6K0
前端人的爬虫工具【Puppeteer】
写个爬虫,爬取 Boss 直聘全部前端岗位
爬取数据我们使用 Puppeteer 来做,然后用 TypeORM 把爬到的数据存到 mysql 表里。
神说要有光zxg
2024/05/10
1.2K0
写个爬虫,爬取 Boss 直聘全部前端岗位
前端工程师的一大神器——puppeteer
大家好,我是若川。欢迎加我微信 ruochuan12,长期交流学习。今天推荐神器puppeteer,我猜有挺多人不知道。文章不长,看完有空也可以试玩。
若川
2021/04/23
1.3K0
前端工程师的一大神器——puppeteer
Puppeteer 入门指引
Puppeteer 是一个 Node library,提供了一套完整的通过 DevTools 协议操纵 Chrome 或 Chromium 的 API。Puppeteer 默认以 无头(headless) 的方式运行, 也可以使用 GUI 的方式运行 Chrome 和 Chromium。
MudOnTire
2022/03/22
1.8K0
Puppeteer 入门指引
使用Puppeteer爬取地图上的用户评价和评论
在互联网时代,获取用户的反馈和意见是非常重要的,它可以帮助我们了解用户的需求和喜好,提高我们的产品和服务质量。有时候,我们需要从地图上爬取用户对某些地点或商家的评价和评论,这样我们就可以分析用户对不同地区或行业的态度和偏好。但是,如何从地图上爬取用户评价和评论呢?本文将介绍一种使用Puppeteer的方法,它是一个基于Node.js的库,可以控制Chrome或Chromium浏览器进行各种操作,包括爬虫。
jackcode
2023/09/06
5210
使用Puppeteer爬取地图上的用户评价和评论
puppeteer爬虫教程_python爬虫入门最好书籍
为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。
全栈程序员站长
2022/09/19
2K0
puppeteer爬虫教程_python爬虫入门最好书籍
Puppeteer工具简介及其在网页爬取和自动化中的应用
Puppeteer是一个流行的Node.js库,在开发者中广泛使用的用于网页爬取和自动化任务的工具。它提供两种操作模式,即headfull和headless。在headfull模式下,Puppeteer控制的Chrome或Chromium浏览器是有界面的,也就是可以看到浏览器运行的情况。在此模式下,可以使用浏览器的开发者工具进行调试。这种模式非常适合在本地进行开发和调试。而在headless模式下,它在后台运行,没有用户界面,这种模式非常适合在服务器上运行,因为没有界面,所以可以节省很多资源。该工具还提供缓存资源的选项,这可以帮助减少页面加载时间并提高性能。此外,Puppeteer允许开发人员在页面中执行JavaScript代码,并使用代理更改请求的IP地址,这对于匿名请求或从不同区域访问内容很有用。
jackcode
2023/04/06
7230
Puppeteer工具简介及其在网页爬取和自动化中的应用
上天的Node.js之爬虫篇 15行代码爬取京东淘宝资源 【深入浅出】
中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。
Peter谭金杰
2019/08/02
2.2K0
Puppeteer 初探
Puppeteer是一个Node库,它提供了一个高级API来通过DevTools协议控制无头 Chrome或Chromium ,它也可以配置为使用完整(非无头)Chrome或Chromium。
CloudCat
2022/06/15
2.8K0
Puppeteer 初探
node爬虫入门
这里只展示编写一个简单爬虫,对于爬虫的一些用处还不清楚,暂时只知道一些通用的用处:搜索引擎使用网络爬虫定向抓取网页资源、网络上面的某一类数据分析、下载很多小姐姐的图片(手动狗头)。
腾讯IVWEB团队
2020/06/29
5.4K0
node爬取新型冠状病毒的疫情实时动态
新型冠状病毒有多么可怕,我想大家都已经知道了。湖北爆发了新型冠状病毒,湖南前几天爆发了禽流感,四川发生地震,中国加油!昨天晚上我突发奇想地打算把疫情实时动态展示在自建站上,于是说干就干(先附上昨晚用puppeteer截的图片)。
喜欢ctrl的cxk
2020/02/18
1.2K0
node爬取新型冠状病毒的疫情实时动态
爬虫使用浏览器渲染的一些最佳实践
在做爬虫的时候,总会遇到一些动态网页,他们的内容是 Ajax 加载甚至是加密的。虽然说对于一些大站来说,分析接口是值得的,但是对于众多的小网站来说,一个一个分析接口太繁琐了,这时候直接使用浏览器渲染就简单得多了。
爬虫技术学习
2023/02/10
2.5K0
爬虫使用浏览器渲染的一些最佳实践
相关推荐
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验