使用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 相关文章推荐
js option删除代码集合
Nov 12 Javascript
修改file按钮的默认样式实现代码
Apr 23 Javascript
js创建元素(节点)示例
Jan 02 Javascript
JavaScript运行机制之事件循环(Event Loop)详解
Oct 10 Javascript
javascript面向对象之对象的深入理解
Jan 13 Javascript
JS基于Mootools实现的个性菜单效果代码
Oct 21 Javascript
使用JQuery实现的分页插件分享
Nov 05 Javascript
浅谈js中StringBuffer类的实现方法及使用
Sep 02 Javascript
js防阻塞加载的实现方法
Sep 09 Javascript
详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
Feb 11 Javascript
浅谈Node 调试工具入门教程
Mar 20 Javascript
代码解析React中setState同步和异步问题
Jun 03 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
php读取csv实现csv文件下载功能
2013/12/18 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
JQuery 初体验(建议学习jquery)
2009/04/25 Javascript
基于jquery ajax 用户无刷新登录方法详解
2012/04/28 Javascript
jQuery中is()方法用法实例
2015/01/06 Javascript
js限制input标签中只能输入中文
2015/06/26 Javascript
Bootstrap被封装的弹层
2016/07/20 Javascript
js模拟百度模糊搜索的实例
2017/08/04 Javascript
基于input动态模糊查询的实现方法
2017/12/12 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
2018/01/08 jQuery
vue watch监听对象及对应值的变化详解
2018/02/24 Javascript
详解JavaScript 新语法之Class 的私有属性与私有方法
2019/04/23 Javascript
微信小程序mpvue点击按钮获取button值的方法
2019/05/29 Javascript
async/await让异步操作同步执行的方法详解
2019/11/01 Javascript
详解vue高级特性
2020/06/09 Javascript
Vue项目配置跨域访问和代理proxy设置方式
2020/09/08 Javascript
js实现有趣的倒计时效果
2021/01/19 Javascript
Vue 3自定义指令开发的相关总结
2021/01/29 Vue.js
详解vite+ts快速搭建vue3项目以及介绍相关特性
2021/02/25 Vue.js
python获取文件真实链接的方法,针对于302返回码
2018/05/14 Python
Python实现模拟登录网易邮箱的方法示例
2018/07/05 Python
PyQt5 实现给窗口设置背景图片的方法
2019/06/13 Python
python 环境搭建 及python-3.4.4的下载和安装过程
2019/07/20 Python
Python for循环及基础用法详解
2019/11/08 Python
django执行数据库查询之后实现返回的结果集转json
2020/03/31 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
Python字典fromkeys()方法使用代码实例
2020/07/20 Python
Python实现LR1文法的完整实例代码
2020/10/25 Python
HTML5实现直播间评论滚动效果的代码
2020/05/27 HTML / CSS
写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔
2015/07/30 面试题
英语简历自我评价
2014/01/26 职场文书
2015年学生会部门工作总结
2015/04/21 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
五一放假通知怎么写
2015/08/18 职场文书
HAM-2000摩机图
2021/04/22 无线电
python用tkinter开发的扫雷游戏
2021/06/01 Python