使用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 相关文章推荐
Get中文乱码IE浏览器Get中文乱码解决方案
Dec 26 Javascript
javascript数据结构之二叉搜索树实现方法
Nov 25 Javascript
深入浅析javascript中的作用域(推荐)
Jul 19 Javascript
解决Angular.Js与Django标签冲突的方案
Dec 20 Javascript
JavaScript仿支付宝6位数字密码输入框
Dec 29 Javascript
node.js基于express使用websocket的方法
Nov 09 Javascript
用vue2.0实现点击选中active其他选项互斥的效果
Apr 12 Javascript
小程序实现选择题选择效果
Nov 04 Javascript
灵活使用console让js调试更简单的方法步骤
Apr 23 Javascript
Python版实现微信公众号扫码登陆
May 28 Javascript
js异步接口并发数量控制的方法示例
Nov 22 Javascript
vue实现在data里引入相对路径
Jun 05 Vue.js
详解如何使用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
Dedecms V3.1 生成HTML速度的优化办法
2007/03/18 PHP
关于PHP结束标签的使用细节探讨及联想
2013/03/04 PHP
PHP实现的曲线统计图表示例
2016/11/10 PHP
php获得刚插入数据的id 的几种方法总结
2018/05/31 PHP
tp5.1 框架路由操作-URL生成实例分析
2020/05/26 PHP
escape、encodeURI、encodeURIComponent等方法的区别比较
2006/12/27 Javascript
jQuery实战之品牌展示列表效果
2011/04/10 Javascript
jquery.blockUI.js上传滚动等待效果实现思路及代码
2013/03/18 Javascript
解析Jquery中如何把一段html代码动态写入到DIV中(实例说明)
2013/07/09 Javascript
Jquery仿淘宝京东多条件筛选可自行结合ajax加载示例
2013/08/28 Javascript
一个简单的JS时间控件示例代码(JS时分秒时间控件)
2013/11/22 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
jquery队列queue与原生模仿其实现方法分享
2014/03/25 Javascript
使用JavaScript获取电池状态的方法
2014/05/03 Javascript
通过js获取上传的图片信息(临时保存路径,名称,大小)然后通过ajax传递给后端的方法
2015/10/01 Javascript
浅析创建javascript对象的方法
2016/05/13 Javascript
jQuery 获取屏幕高度、宽度的简单实现案例
2016/05/17 Javascript
vue实现点击选中,其他的不选中方法
2018/09/05 Javascript
详解在HTTPS 项目中使用百度地图 API
2019/04/26 Javascript
小程序使用wxs解决wxml保留2位小数问题
2019/12/13 Javascript
JS实现盒子拖拽效果
2020/02/06 Javascript
python简单获取本机计算机名和IP地址的方法
2015/06/03 Python
Python备份目录及目录下的全部内容的实现方法
2016/06/12 Python
Python爬取当当、京东、亚马逊图书信息代码实例
2017/12/09 Python
Python修改文件往指定行插入内容的实例
2019/01/30 Python
python远程连接MySQL数据库
2019/04/19 Python
numpy库ndarray多维数组的维度变换方法(reshape、resize、swapaxes、flatten)
2020/04/28 Python
pytorch 多分类问题,计算百分比操作
2020/07/09 Python
既然说Ruby中一切都是对象,那么Ruby中类也是对象吗
2013/01/26 面试题
幼儿园招生广告
2014/03/19 职场文书
小学生学雷锋演讲稿
2014/04/25 职场文书
2014年六一儿童节演讲稿
2014/05/23 职场文书
学习型党组织建设经验材料
2014/05/26 职场文书
2015年乡镇安全生产工作总结
2015/05/19 职场文书
房产遗嘱范本
2015/08/06 职场文书
企业法律事务工作总结
2015/08/11 职场文书