第一弹:puppeteer爬虫小demo —— 网易云音乐

上一篇文章主要介绍了一些puppeteer爬虫api,本文是实战篇第一弹,爬取网易云音乐某个页面板块

出发点

  1. 首先我不是要爬歌词,我只是想结合上一篇文章写一个练手小demo,内容随意。
  2. 这个demo最好可以涉及多媒体保存。
  3. 尽可能简单,不涉及数据库操作、删除文件操作。
  4. 限定网站是传统异步获取分页数据,没有分页参数在地址栏url上。

解决点

  1. 图片下载

    之前写项目的时候习惯用axios,本文也是使用axios。axios(url, {responseType: "stream"})这样初始化axios就可以下载图片了。

  2. 图片位置

    新建一个image文件夹来存储下载的图片 fs.mkdirSync("image");

  3. 分析网站结构

    • 网易云音乐的主体由一个iframe包裹,iframe有name和id,用iframe.name()Array.find可以匹配单个Frame对象。
    • 每一行都是由一个tr组成
    • 获取新数据可以模拟点击下一页实现

下面直接放代码

const fs = require("fs");
const puppeteer = require("puppeteer");
const axios = require("axios");
console.time("ssr"); //开始计时
if (!fs.existsSync("image")) {
//新建image文件夹
  fs.mkdirSync("image");
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    devtools: true
  });
  const page = (await browser.pages())[0];
  await page.setViewport({
    width: 1280,
    height: 800
  });
  //为了简化,我直接跳到想爬的地址了。当然你也可以打开网易云一步一步操作,注意规律就好了。
  await page.goto(
    "http://music.163.com/#/search/m/?id=9605&s=%E5%8D%AB%E5%85%B0&type=1000"
  );
  //Frame对象有一个获取name的方法
  let iframe = await page.frames().find(f => f.name() === "contentFrame");
  //这里我只获取前五页的数据,当然你也可以获取下一页的前一个元素的innerText来确认总数
  for (let i = 1; i <= 5; i++) {
    fs.mkdirSync(`image/${i}`); //页码作为文件夹名
    // await iframe.waitFor(".m-table td .s-fc3");
    // 等待分页数据。本来想通过上面的方式来等待的,但是貌似是因为上一个页面".m-table td .s-fc3"的节点已经加载
    //按下一页的时候这个选择器的节点还在,导致这个方式失效?请大佬解惑
    await iframe.waitFor(2000) //ps:少于2s,有时会出现图片重复,原因是dom仍未更新导致
    const te = await iframe.$$eval(".m-table tbody tr", list => {
    //请注意已经进入浏览器环境了
      return new Promise(resolve => {
        let arr = [];
        list.map((item, index) => {
          let temp = {};
          const str = item.querySelector(".w7 img").src;
          temp.img = str.slice(0, str.lastIndexOf("?")); //获取最大尺寸的图片
          temp.title = item.querySelector(".txt").innerText;
          temp.author = item.querySelector(".w4 a.s-fc3").title;
          temp.count = item.querySelector(".w6.s-fc4").innerText;
          //因为这是浏览器的环境,我在node依赖的axios是无法在这里下载文件的,只能先保存数据再回到node中下载
          // axios(temp.img,{responseType:'stream'}).then(response => response.data.pipe(fs.createWriteStream(`./image/${temp.author.jpg}`)))
          arr.push(temp);
        });
        resolve(arr);
      });
    });
    //回到node的环境,可以放心下载了。
    te.map(async (item, index) => {
      const result = await axios(item.img, {
        responseType: "stream"
      });
      result.data.pipe(fs.createWriteStream(`./image/${i}/${item.author}.jpg`)); //管道真好使
    });
    // 下载完图片进入下一页,如果有页码直接用goto跳转
    iframe.click('.u-page a:last-child')
  }

  console.timeEnd("ssr"); //计时结束
  })();
复制代码

本文内容不多,把传统异步分页的爬取流程以代码形式写了一遍。小弟不才,第一次接触爬虫,并不了解其他工具是怎样爬取,如有错希望大家指正。

另外想问个问题,为什么<div tabindex="0"></div>这样写,点击div的时候:focus会生效。

起因:在一个div上,借助f12调试勾选:focus:focus会生效,用鼠标点击就没效果。But在div加上tabindex="0"后,鼠标点击:focus生效


小弟不才,17年软件工程毕业生,熟悉vue写过两个公司项目。目前已离职,坐标广州,求大佬们收留。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值