使用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 相关文章推荐
javascript nextSibling 与 getNextElement(node) 使用介绍
Oct 13 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
May 23 Javascript
javascript改变position值实现菜单滚动至顶部后固定
Jan 18 Javascript
jquery创建表格(自动增加表格)代码分享
Dec 25 Javascript
Javascript中引用示例介绍
Feb 21 Javascript
网站接入QQ登录的两种方法
Jul 22 Javascript
Jquery插件easyUi实现表单验证示例
Dec 15 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
Mar 22 Javascript
JS基于MSClass和setInterval实现ajax定时采集信息并滚动显示的方法
Apr 18 Javascript
在vue中使用公共过滤器filter的方法
Jun 26 Javascript
JS hasOwnProperty()方法检测一个属性是否是对象的自有属性的方法
Jan 29 Javascript
动态规划之使用备忘录来改进Javascript函数
Apr 07 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
Syphon 虹吸式咖啡壶冲煮–拨动法
2021/03/03 冲泡冲煮
PHP 9 大缓存技术总结
2015/09/17 PHP
PHP7 其他语言层面的修改
2021/03/09 PHP
javascript oop开发滑动(slide)菜单控件
2010/08/25 Javascript
javascript if条件判断方法小结
2014/05/17 Javascript
JQuery中$.each 和$(selector).each()的区别详解
2015/03/13 Javascript
基于javascript实现根据身份证号码识别性别和年龄
2016/01/22 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
2016/06/23 Javascript
Bootstrap树形菜单插件TreeView.js使用方法详解
2016/11/01 Javascript
js实现界面向原生界面发消息并跳转功能
2016/11/22 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
2016/12/14 Javascript
浅析JS抽象工厂模式
2017/12/14 Javascript
微信小程序button组件使用详解
2018/01/31 Javascript
JavaScript正则表达式函数总结(常用)
2018/02/22 Javascript
jquery层次选择器的介绍
2019/01/18 jQuery
vue中动态select的使用方法示例
2019/10/28 Javascript
vue父子组件间引用之$parent、$children
2020/05/20 Javascript
简单了解前端渐进式框架VUE
2020/07/20 Javascript
vue-router 控制路由权限的实现
2020/09/24 Javascript
python将xml xsl文件生成html文件存储示例讲解
2013/12/03 Python
Python实现查找匹配项作处理后再替换回去的方法
2017/06/10 Python
Django实现组合搜索的方法示例
2018/01/23 Python
Python3 读、写Excel文件的操作方法
2018/10/20 Python
关于PyTorch源码解读之torchvision.models
2019/08/17 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
Pycharm添加虚拟解释器报错问题解决方案
2020/10/13 Python
matplotlib 画动态图以及plt.ion()和plt.ioff()的使用详解
2021/01/05 Python
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
大专计算机个人求职的自我评价
2013/10/21 职场文书
早读迟到检讨书
2014/01/24 职场文书
汽车销售员如何做职业生涯规划
2014/02/16 职场文书
初中教师个人总结
2015/02/10 职场文书
企业年会祝酒词
2015/08/11 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书
MSSQL基本语法操作
2022/04/11 SQL Server