前言
- cheerio介绍
- jsdom介绍
- nock介绍
- puppeteer 介绍
一. cheerio介绍
Cheerio地址 Cheerio 是一个在 Node.js 中解析 HTML 和 XML 的工具
它快速、灵活且易于使用。由于它实现了 JQuery 的一个子集,如果你已经熟悉 JQuery,那么很容易开始使用 Cheerio
Cheerio 和 Web 浏览器之间的主要区别在于,cheerio 不生成视觉渲染、加载 CSS、加载外部资源或执行 JavaScript。 它只是解析标记并提供用于操作生成的数据结构的 API。这就解释了为什么它也非常快
1.1 简单使用
var cheerio = require('cheerio');
$ = cheerio.load("<h2 class='title'>Hello word</h2>");
$('.title').html("james.yang");
$('.title').addClass("myTitle");
// <html><head></head><body><h2 class="title myTitle">james.yang</h2></body></html>
console.log($.html());
1.2 作为爬虫
const axios = require("axios");
const cheerio = require("cheerio");
const fs = require("fs");
const getSiteData = async (url) => {
const { data } = await axios.get(url);
const ret = cheerio.load(data);
return ret;
};
async function grabClassifysData(){
const url = `https://juejin.cn/`;
const $ = await getSiteData(url);
const listItems = $(".view-nav .nav-item");
const classifys = [];
listItems.each((idx, el) => {
let content = $(el).find(".category-popover-box").text();
content = content.replace(/\s+/g,'');
classifys.push(content);
});
console.log(classifys);
fs.writeFileSync("classifys.json", JSON.stringify(classifys, null, 2));
};
grabClassifysData()
async function grabContentData(){
const url = `https://juejin.cn/`;
const $ = await getSiteData(url);
const listItems = $(".entry-list-wrap");
console.log(listItems.html());
};
grabContentData();
注意: 作为爬虫使用的时候只能抓取静态页面的数据,对于spa应用的内容没法抓取,但是可以通过puppeteer很好的解决网站动态数据的问题
二. jsdom介绍
jsdom地址 JSDOM 是一个基于 JavaScript 的无头浏览器,可用于创建真实的测试环境
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
// console.log(dom.window)
// node环境下不能直接通过document来获取DOM节点
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
const $ = require('jquery')(dom.window);
console.log($('p').text());// "Hello world"
三. nock介绍
Nock地址 Nock 是一个 HTTP 模拟和预期测试库,用于 Node.js 平台。用来测试 HTTP 请求
const nock = require('nock')
const axios = require('axios');
nock('http://localhost:3000')
.get('/user?name=james')
.reply(200, {
"name": "james2",
"age": 30,
});
let url = `http://localhost:3000/user?name=james`;
axios.get(url).then(res => {
console.log('==res===', res.data);
return res.data;
}).catch(err => {
console.error(err);
});
四. puppeteer介绍
Puppeteer 是一个 Chrome官方出品的 headless Chrome node 库(当然你也可以配置成有UI的,默认是没有的)。
Puppeteer 是一个node库,他提供了一组用来操纵Chrome的API。
既然是浏览器,那么我们手工可以在浏览器上做的事情 Puppeteer 都能胜任,
另外,Puppeteer 翻译成中文是”木偶”意思,所以听名字就知道,操纵起来很方便,你可以很方便的操纵她去实现:
1. 生成网页截图 或者 PDF
2. 作为爬虫来爬取大量异步渲染网页的内容
抓取 SPA(单页应用)并生成预渲染内容
3. 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试
创建一个实时更新的自动化测试环境。 使用最新的 JavaScript 和浏览器功能直接在最新版本的Chrome中执行测试
4. 捕获网站的时间线(timeline trace),以便追踪你的网站,帮助分析网站性能问题
5. 测试浏览器扩展
抓取掘金网站首页最新10条数据
const path = require('path');
const puppeteer = require('puppeteer');
const fs = require('fs');
const start = async () => {
const browser = await puppeteer.launch({
// 是否以”无头”的模式运行 chrome, 也就是不显示 UI, 默认为 true
headless: false,
// 使 Puppeteer 操作减速,单位是毫秒。如果你想看看 Puppeteer 的整个工作过程,这个参数将非常有用。
slowMo: 250,
// 等待 Chrome 实例启动的最长时间。默认为30000(30秒)。如果传入 0 的话则不限制时间
timeout: 0
});
// 创建新标签页并打开
let page = await browser.newPage();
// Whether or not to enable JavaScript on the page
await page.setJavaScriptEnabled(true);
// 打开新页面
await page.goto("https://juejin.cn/");
// Page.$(selector) 获取单个元素,底层是调用的是 document.querySelector()
// page.waitForSelector(selector[, options]) 等待某个选择器的元素加载之后,这个元素可以是异步加载的
// 等待元素加载之后,否则获取不到异步加载的元素
await page.waitForSelector('.entry-list-wrap .item');
// Page.$$(selector) 获取一组元素,底层调用的是 document.querySelectorAll().
// Page.$$eval(selector, Function[, …args]), 获取单个元素的属性,这里的选择器 selector 跟上面 Page.$(selector) 是一样的
const links = await page.$$eval('.entry-list-wrap .item .title', links => {
return links.slice(0, 10).map(a => {
return {
href: a.href.trim(),
title: a.title
}
});
});
// 浏览器关闭
await page.close();
await browser.close();
console.log("===links===", links);
write(links);
};
// 写入文件
const write = (links) => {
let filename = path.resolve(__dirname, `./out/contents.txt`);
fs.writeFileSync(filename, JSON.stringify(links, null, 2), 'utf-8');
};
start();