Как посетить все URL-адреса с веб-сайта без проблем с производительностью - PullRequest
0 голосов
/ 06 июня 2019

Я на самом деле пытаюсь создать сайт, похожий на этот: https://robhammond.co/tools/seo-crawler

Концепция проста: вы вводите URL веб-сайта, и он следует за каждой ссылкой, которая у вас есть внутри, чтобы увидеть, есть ли мертвые ссылки.

Я пытался сделать это рекурсивно: просматривая одну страницу, находя ссылки и просматривая каждую найденную ссылку, находя ссылки на каждой странице и т. Д.

Я создал массив уже посещенных ссылок, поэтому я не буду проверять страницы, которые уже проверил.

Вот мой код, я использую рекурсивный ajax-вызов PHP-файла, который использует cURL, чтобы получить код ошибки и найти все ссылки внутри него. После этого я делаю еще один вызов ajax для каждой найденной ссылки.

Вот мой код: Мой html / javascript файл:

<?php
session_start();
$_SESSION['visitedLinks'] = [];
?>

<html lang="fr">
<header>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>


    <title>Kaiman Crawler</title>
</header>
<body>
<form id="form" method="post" action="">
    <label>
        Veuillez saisir l'URL du site à scanner :
        <input type="text" id='url' value="https://php.net/" required/>
    </label>
    <input type="submit" value="Scanner"/>
</form>
<p>Attention: Les pages avec plus de 200 liens ne seront pas traitées</p>

<table class="table" hidden>
    <thead>
    <tr>
        <th scope="col"></th>
        <th scope="col">URL</th>
        <th scope="col">Titre de la page</th>
        <th scope="col">Statut</th>
        <th scope="col">Signification</th>
        <th scope="col">Nombre de liens sur la page</th>
    </tr>
    </thead>
    <tbody>

    </tbody>
</table>

<script>
    var cpt =1;
    var request = 0;
    var baseURL;
    function signification(code){
        switch (code) {
            // TODO: Continuer les codes d'erreur
            case 200:
                return "Accessible";
            case 404:
                return "Page introuvable";
        }
    }

    function scanPage(url) {
        $.ajax({
            url: 'getURLs.php',
            dataType:'json',
            type:'POST',
            data:{
                URL: url
            }
        }).done(function (data) {
            console.log(data);
            if (data['success']) {
                $('tbody').append('<tr id="' + cpt + '"></tr>');
                $('#' + cpt).append("<td>" + cpt++ + "</td>")
                    .append("<td>" + data['page'].url + "</td>")
                    .append("<td>" + data['page'].titre + "</td>")
                    .append("<td>" + data['page'].code + "</td>")
                    .append("<td>" + signification(data['page'].code) + "</td>")
                    .append("<td>" + data['page']['pages'].length + "</td>");
                for (let i = 0; i < data['page']['pages'].length; ++i) {
                    if (data['page']['pages'].length >= 200){
                        break;
                    }
                    if (!data['links'].includes(data['page']['pages'][i]) && data['links'].includes(baseURL)) {
                        console.log(++request);
                        scanPage(data['page']['pages'][i]);
                    }
                }
            }
        });
    }

    $('#form').submit(function (){
        $('table').attr('hidden',false);
        baseURL = $('#url').val();
        $('thead').empty();
        scanPage($('#url').val());
        return false;
    });

    function sleep(milliseconds) {
        var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > milliseconds){
                break;
            }
        }
    }
</script>
</body>
</html>

Мой php файл:

<?php
session_start();
require_once __DIR__ . '/Page.php';

$baseURL = $_POST['URL'];
$baseURL = explode('/',$baseURL,4);
$nomPage = $baseURL[3];
$baseURL = $baseURL[0] . "//". $baseURL[2] . '/';

$data = new stdClass();
$data->success = true;
$result = showLinks($baseURL,$nomPage);
if ($result === false){
    $data->success = false;
}
else {
    $data->page = $result;
    $data->links = $_SESSION['visitedLinks'];
}

echo json_encode($data);



function showLinks($baseURL,$nomPage = "") {
    if (!array_search($baseURL.$nomPage,$_SESSION['visitedLinks'])){

        $result = fread_url($baseURL.$nomPage);
        $var = $result[1];
        $code = curl_getinfo($result[0], CURLINFO_HTTP_CODE);
        $title = get_html_title($var);

        array_push($_SESSION['visitedLinks'],$baseURL.$nomPage);

        $page = new Page($baseURL . $nomPage, $title, $code);

        preg_match_all("/a[\s]+[^>]*?href[\s]?=[\s\"\']+" .
            "(.*?)[\"\']+.*?>" . "([^<]+|.*?)?<\/a>/",
            $var, $matches);


        $matches = $matches[1];

        foreach ($matches as $var1) {
            if (strlen($var1) >= 1) {
                // si il ne s'agit pas d'une référence sur place ou à la racine
                if ($var1[0] !== "#" && $var1 !== "/" && $var[0] !== "." && $var[0] !== "?" && $var[0] !== "%") {
                    // Si le dernier caractère n'est pas un /, l'ajouter
                    if ($var1[strlen($var1) - 1] !== "/") {
                        $var1[strlen($var1)] = "/";
                    }

                    // Si il s'agit d'un chemin absolu
                    if ($var1[0] === '/') {
                        $var1 = ltrim($var1, $var1[0]);
                        $page->addChild($baseURL . $var1);
                    } // Si il s'agit d'un chemin relatif
                    else if (strpos($var1, "http://") === false && strpos($var1, 'https://') === false && strpos($var1, 'www.') === false) {
                        $page->addChild($baseURL . $nomPage . $var1);
                    } // Sinon, si il s'agit d'une url
                    else {
                        $page->addChild($var1);
                    }
                }
            }
        }

        return $page;
    }
    else return false;
}

function fread_url($url,$ref="") {
    $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; ".
        "Windows NT 5.0)";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt( $ch, CURLOPT_HTTPGET, 1 );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_REFERER, $ref );
    curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
    $html = curl_exec($ch);
    return [$ch,$html];
}

function get_html_title($html){
    preg_match("/\<title.*\>(.*)\<\/title\>/isU", $html, $matches);
    return $matches[1];
}

И, наконец, мой класс Page

<?php

class Page implements JsonSerializable {
    private $url;
    private $titre;
    private $code;
    private $pages = array();

    public function __construct($url,$titre,$code) {
        $this->titre = $titre;
        $this->url = $url;
        $this->code = $code;
    }

    public function addChild ($child){
        array_push($this->pages,$child);
    }

    /**
     * Specify data which should be serialized to JSON
     * @link https://php.net/manual/en/jsonserializable.jsonserialize.php
     * @return mixed data which can be serialized by <b>json_encode</b>,
     * which is a value of any type other than a resource.
     * @since 5.4.0
     */
    public function jsonSerialize(){
        return [
            'url' => $this->url,
            'titre' => $this->titre,
            'code' => $this->code,
            'pages' => $this->pages
        ];
    }
}

На самом деле, это работает на Firefox, но использует много ресурсов. Кроме того, в Chrome через некоторое время на больших сайтах я получаю ERR_INSUFFICIENT_RESOURCES на консоли.

Итак, я спрашиваю вас, есть ли лучший способ оптимизировать мой код?

Спасибо за вашу помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...