使用puppeteer爬取网站并抓出404无效链接


Posted in Javascript onDecember 20, 2018

检查网页无效链接

前言

自动化技术可以帮助我们做自动化测试,同样也可以帮助我们完成别的事情,比如今天我们要做的检查网站404无效链接。

原理

使用puppeteer爬取网站并抓出404无效链接

实现这样的功能,大致分为以下步骤: 1.打开官网首页,获取页面上所有的链接。 2.添加规则对这些链接过滤,把外链去掉。 3.遍历访问这些链接,打开打开其中的每一个链接,检查是否为404,如果是距离下来。 4.重复执行1,2,3。直到把整个网站所有的链接都遍历完。

准备

CukeTest 一款可以专业的编辑自动化脚本的工具。cuketest.com/

puppeteer 一个非常流行自动化库。https://github.com/GoogleChrome/puppeteer

实现

CukeTest中新建一个项目。

使用puppeteer爬取网站并抓出404无效链接

删掉features目录。新建一个demo.js文件。

使用puppeteer爬取网站并抓出404无效链接

安装puppeteer

npm install puppeteer --save

主要方法讲解

pupputeer内置监听事件,可以很快拿到每个请求的响应结果。

puppeteer可以创建Chromium实例。创建方式如下:

let puppeteer = require('puppeteer'); 
browser = await puppeteer.launch({ headless: true });
page = await browser.newPage();
await browser.close();

puppeteer 提供事件监听,可以监听到每个页面的响应状态,为每个请求添加响应事件,如果响应状态码为404,记录到文件中。

page.on('response',(res)=>{
 // console.log("res.url", res.url(), res.status())
 let url = res.url();
 if(res.status()==404){
  linktoFile(url, brokenlinkFile);
 }else{
  if(isvaildUrl(url)){
   linktoFile(url,validUrlFilePath);
  }
  
 } 
})

puppeteer抓取页面上所有的链接

await page.goto(url);
//获取所有的link
const hrefs = await page.evaluate(
 () => Array.from(document.body.querySelectorAll('a[href]'), ({ href }) => href)
);

将链接记录到文件或者从文件读取链接的方法

let filetoLinks = function (filepath) {
 if (!fs.existsSync(filepath)) {
  fs.writeFileSync(filepath);
 }
 let data = fs.readFileSync(filepath, 'utf-8')
 let links = data.trim().split('\n');
 return links;
}

let linktoFile = function (link, filepath) {
 let foundLinks = filetoLinks(filepath);
 if (!foundLinks.includes(link)) {
  fs.appendFileSync(filepath, link + '\n');
 }
}

最终代码

let puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');


const host = 'http://www.xxxx.cn/'; // 被测网站
const visitedFile = 'visitedUrl.txt'; //浏览过的页面
const visitedFilePath = path.join(__dirname, visitedFile);
const brokenlinkFile = 'brokenLink.txt'; //404链接
const brokenlinkFilePath = path.join(__dirname, brokenlinkFile);

const validUrlFile = 'validUrlFile.txt'; //可用的链接
const validUrlFilePath = path.join(__dirname,validUrlFile);

let browser;
let page;

function isvaildUrl(url){
 return url.startsWith(host) && !url.includes('/#');
}

async function run() {
 browser = await puppeteer.launch({ headless: true });

 page = await browser.newPage();
 page.on('response',(res)=>{
  // console.log("res.url", res.url(), res.status())
  let url = res.url();
  let currenturl = page.url()
  if(res.status()==404){
   linktoFile(currenturl+"=="+url, brokenlinkFilePath);
  }else{
   if(isvaildUrl(url)){
    linktoFile(url,validUrlFilePath);
   }
   
  } 
 })

 await visitPage(browser,page, host);

 await browser.close();

}

async function visitPage(browser,page, url) {
 // if (!isvaildUrl(url)) return;
 await page.goto(url);
 //获取所有的link
 const hrefs = await page.evaluate(
  () => Array.from(document.body.querySelectorAll('a[href]'), ({ href }) => href)
 );

 for (const href of hrefs) {
  //数据清洗
  if (isvaildUrl(href) && href !== host) {
   
   //符合条件的link
   // linktoFile(href, visitedFilePath);
   let res = await page.goto(href);
   
   if (res && res.status() == 404) {
    linktoFile(href, brokenlinkFilePath);
   } else {
    let visitedlinks = filetoLinks(visitedFilePath);
    if(!visitedlinks.includes(href)){
     linktoFile(href, visitedFilePath);
     await visitPage(browser,page,href);
     
    }
    
   }

   let links = filetoLinks(visitedFilePath);
   if (!links.includes(href)) {
    await visitPage(browser,page, href);
   }
  }
 }
}

let filetoLinks = function (filepath) {
 if (!fs.existsSync(filepath)) {
  fs.writeFileSync(filepath);
 }
 let data = fs.readFileSync(filepath, 'utf-8')
 let links = data.trim().split('\n');
 return links;
}

let linktoFile = function (link, filepath) {
 let foundLinks = filetoLinks(filepath);
 if (!foundLinks.includes(link)) {
  fs.appendFileSync(filepath, link + '\n');
 }
}

run();

运行

点击 【运行】按钮即可运行。 同样,在CukeTest中也支持命令行执行,执行命令为

cuke --runjs demo.js

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery的气泡提示效果
May 31 Javascript
jqGrid jQuery 表格插件测试代码
Aug 23 Javascript
JavaScript利用构造函数和原型的方式模拟C#类的功能
Mar 06 Javascript
Jquery焦点与失去焦点示例应用
Jun 10 Javascript
Vue实现购物车场景下的应用
Nov 27 Javascript
Dropify.js图片宽高自适应的方法
Nov 27 Javascript
图片懒加载imgLazyLoading.js使用详解
Sep 15 Javascript
新手快速上手webpack4打包工具的使用详解
Jan 28 Javascript
javascript验证form表单数据的案例详解
Mar 25 Javascript
js 实现ajax发送步骤过程详解
Jul 25 Javascript
jQuery实现的记住帐号密码功能完整示例
Aug 03 jQuery
微信小程序基于高德地图查找位置并显示文字
Oct 30 Javascript
详解如何使用node.js的开发框架express创建一个web应用
Dec 20 #Javascript
js canvas实现橡皮擦效果
Dec 20 #Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
Dec 20 #Javascript
Cocos2d实现刮刮卡效果
Dec 20 #Javascript
浅谈Fetch 数据交互方式
Dec 20 #Javascript
cocos2dx+lua实现橡皮擦功能
Dec 20 #Javascript
element-ui table span-method(行合并)的实现代码
Dec 20 #Javascript
You might like
Windows下利用Gvim写PHP产生中文乱码问题解决方法
2011/04/20 PHP
PHP中的use关键字概述
2014/07/23 PHP
PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
2015/03/10 PHP
浅析Yii2集成富文本编辑器redactor实例教程
2016/04/25 PHP
PHP实现的字符串匹配算法示例【sunday算法】
2017/12/19 PHP
JavaScript 验证浏览器是否支持javascript的方法小结
2009/05/17 Javascript
一款Jquery 分页插件的改造方法(服务器端分页)
2011/07/11 Javascript
jQuery父级以及同级元素查找介绍
2013/09/04 Javascript
js使下拉列表框可编辑不止是选择
2013/12/12 Javascript
jquery中的工具使用方法$.isFunction, $.isArray(), $.isWindow()
2015/08/09 Javascript
jquery mobile开发常见问题分析
2016/01/21 Javascript
JS跨域解决方案之使用CORS实现跨域
2016/04/14 Javascript
JS获取鼠标坐标并且根据鼠标位置不同弹出不同内容
2017/06/12 Javascript
Javascript快速实现浏览器系统通知
2017/08/26 Javascript
在vue中使用setInterval的方法示例
2019/04/16 Javascript
JS阻止事件冒泡的方法详解
2019/08/26 Javascript
解决layui的input独占一行的问题
2019/09/10 Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
2019/12/17 Javascript
VUE实时监听元素距离顶部高度的操作
2020/07/29 Javascript
使用js获取身份证年龄的示例代码
2020/12/11 Javascript
python flask 多对多表查询功能
2017/06/25 Python
Python基于回溯法子集树模板解决马踏棋盘问题示例
2017/09/11 Python
HTML5地理定位_动力节点Java学院整理
2017/07/12 HTML / CSS
欧洲著名的二手奢侈品网站:Vestiaire Collective
2020/03/07 全球购物
线程的基本概念、线程的基本状态以及状态之间的关系
2012/10/26 面试题
我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。 为什么如下的代码((int *)p)++; 不行?
2013/05/09 面试题
物流业务员岗位职责
2014/02/08 职场文书
2014年3.15团委活动总结
2014/03/16 职场文书
三严三实学习心得体会
2014/10/13 职场文书
售房协议书范本2014
2014/10/23 职场文书
2015年新教师个人工作总结
2015/10/14 职场文书
导游词之沈阳植物园
2019/11/30 职场文书
导游词之青岛崂山
2019/12/27 职场文书
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript
Python机器学习应用之工业蒸汽数据分析篇详解
2022/01/18 Python
Django + Taro 前后端分离项目实现企业微信登录功能
2022/04/07 Python