使用puppeteer爬取網站,抓出404無效連接

檢查網頁無效連接

前言

自動化技術能夠幫助咱們作自動化測試,一樣也能夠幫助咱們完成別的事情,好比今天咱們要作的檢查網站404無效連接。javascript

原理

網站檢查是否有404頁面.png | left | 746x631

實現這樣的功能,大體分爲如下步驟: 1.打開官網首頁,獲取頁面上全部的連接。 2.添加規則對這些連接過濾,把外鏈去掉。 3.遍歷訪問這些連接,打開打開其中的每個連接,檢查是否爲404,若是是距離下來。 4.重複執行1,2,3。直到把整個網站全部的連接都遍歷完。java

準備

實現

CukeTest中新建一個項目。git

image.png | left | 525x254.06091370558377

刪掉features目錄。新建一個demo.js文件。github

image.png | left | 483x296

安裝puppeteer

npm install puppeteer --save
複製代碼

主要方法講解

pupputeer內置監聽事件,能夠很快拿到每一個請求的響應結果。npm

puppeteer能夠建立Chromium實例。建立方式以下:app

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

puppeteer 提供事件監聽,能夠監聽到每一個頁面的響應狀態,爲每一個請求添加響應事件,若是響應狀態碼爲404,記錄到文件中。less

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抓取頁面上全部的連接async

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
複製代碼

獲取更多相關知識,歡迎關注公衆號

相關文章
相關標籤/搜索