Разработка веб-сканера - PullRequest
       39

Разработка веб-сканера

67 голосов
/ 29 апреля 2011

Я столкнулся с вопросом на собеседовании «Если бы вы разрабатывали веб-сканер, как бы вы не попали в бесконечные циклы?», И я пытаюсь на него ответить.

Как все это начинается с самого начала. Скажем, Google начал с некоторых хаб-страниц, скажем, сотни из них (как эти хаб-страницы были найдены в первую очередь, это другой подвопрос). Поскольку Google следует ссылкам со страницы и т. Д., Продолжает ли она создавать хеш-таблицу, чтобы убедиться, что она не следует за ранее посещенными страницами.

Что если одна и та же страница имеет 2 имени (URL), которые мы говорим в наши дни, когда у нас есть сокращатели URL и т. Д.

Я взял Google в качестве примера. Хотя Google не знает, как работают его алгоритмы поиска, ранжирования страниц и т. Д., Но есть предположения?

Ответы [ 10 ]

80 голосов
/ 29 апреля 2011

Если вы хотите получить подробный ответ, взгляните на раздел 3.8 этого документа , в котором описан тест на просмотр URL современного скребка:

В курсепри извлечении ссылок любой веб-сканер встретит несколько ссылок на один и тот же документ.Чтобы не загружать и не обрабатывать документ несколько раз, перед каждой извлеченной ссылкой необходимо выполнить проверку URL-адреса перед добавлением его к границе URL-адреса.(В качестве альтернативы можно было бы вместо этого выполнить проверку URL-адреса при удалении URL-адреса с границы, но такой подход привел бы к гораздо большей границе.)

Чтобы выполнить тест с просмотром URL-адреса, мыхранить все URL-адреса, которые Mercator просматривает в канонической форме, в большой таблице, называемой набором URL-адресов.Опять же, слишком много записей, чтобы все они поместились в памяти, поэтому, как и набор отпечатков документов, набор URL хранится в основном на диске.

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

Фактически, используя кэш в памяти из 2 ^ 18 записей и политику замены тактового генератора, подобную LRU, мы достигаем общего коэффициента попадания в кэш в памяти в 66,2% и коэффициента попадания в9,5% в таблице недавно добавленных URL, чистая доля попаданий составляет 75,7%.Более того, из 24,3% запросов, которые отсутствуют как в кеше популярных URL-адресов, так и в таблице недавно добавленных URL-адресов, около 1 = 3 производят попадания в буфер в нашей реализации файла произвольного доступа, которая также находится в пользовательском пространстве.Конечным результатом всей этой буферизации является то, что каждый тест членства, который мы выполняем на наборе URL, приводит в среднем к 0,16 запросам поиска и 0,17 вызовам ядра чтения (некоторая часть которых обслуживается из буферов файловой системы ядра).Таким образом, каждый тест на членство в наборе URL-адресов вызывает в шесть раз больше вызовов ядра, чем тест на членство в наборе отпечатков документов.Эта экономия обусловлена ​​исключительно количеством локальных URL-адресов (т. Е. Повторением популярных URL-адресов), присущих потоку URL-адресов, встречающемуся во время сканирования.

В основном они хешируют все URL-адреса с помощью функции хешированияэто гарантирует уникальные хеши для каждого URL-адреса и из-за локальности URL-адресов становится очень легко найти URL-адреса.Google даже открыл свою функцию хеширования: CityHash

ПРЕДУПРЕЖДЕНИЕ!
Они также могут говорить о ловушках ботов !!!Ловушка для бота - это раздел страницы, который продолжает генерировать новые ссылки с уникальными URL-адресами, и вы по сути попадете в «бесконечный цикл», перейдя по ссылкам, которые обслуживаются этой страницей.Это не совсем цикл, потому что цикл будет результатом посещения одного и того же URL-адреса, но это бесконечная цепочка URL-адресов, которые следует избегать сканирования.

Обновление 12/13/2012 -на следующий день после того, как мир должен был закончиться:)

За комментарий Fr0zenFyr: если кто-то использует алгоритм AOPIC для выбора страниц, тогда довольно легко избежать ловушекбесконечный циклВот краткая информация о том, как работает AOPIC:

  1. Получите набор из N начальных страниц.
  2. Выделите X сумму кредита для каждой страницы, чтобы каждая страница имела кредит X / N(т. е. равная сумма кредита) до начала сканирования.
  3. Выберите страницу P, где P имеет наибольшую сумму кредита (или, если все страницы имеют одинаковую сумму кредита, просканируйте случайную страницу).
  4. Страница сканирования C (допустим, что при сканировании у P было 100 кредитов).
  5. Извлеките все ссылки со страницы P (допустим, их 10).
  6. Установите для кредитов P значение 0.
  7. Возьмите «налог» в размере 10% и разместите его на лямбда-странице.
  8. Выделите равное количество кредитов для каждой ссылки, найденной на странице P, из исходного кредита P - налога: так (100 (P кредитов) - 10 (10% налога)) / 10 (ссылок) = 9 кредитов на каждую ссылку.
  9. Повторите с шага 3.

Поскольку страница Lambda непрерывно собирает налог, в конечном итоге это будет страница с наибольшей суммой кредита, и нам придется ее "сканировать". Я говорю «сканировать» в кавычках, потому что мы на самом деле не делаем HTTP-запрос для лямбда-страницы, мы просто берем ее кредиты и распределяем их поровну по всем страницам в нашей базе данных.

Поскольку ловушки для ботов дают кредиты только по внутренним ссылкам и редко получают кредиты извне, они будут постоянно пропускать кредиты (от налогообложения) на страницу Lambda. Лямбда-страница будет равномерно распределять кредиты по всем страницам в базе данных, и при каждом цикле страница ловушки ботов будет терять все больше и больше кредитов, пока у нее не будет так мало кредитов, что она почти никогда не будет сканироваться снова. Это не случится с хорошими страницами, потому что они часто получают кредиты от обратных ссылок, найденных на других страницах. Это также приводит к динамическому рангу страниц, и вы заметите, что каждый раз, когда вы делаете снимок своей базы данных, упорядочиваете страницы по количеству кредитов, которые они имеют, тогда они, скорее всего, будут упорядочены примерно в соответствии с их истинный рейтинг страницы .

Это позволяет избежать только ловушек для ботов типа бесконечного цикла, но есть много других ловушек для ботов , на которые следует обратить внимание, и есть способы их обойти.

7 голосов
/ 21 декабря 2011

Хотя все здесь уже предложили, как создать ваш веб-сканер, вот как Google ранжирует страницы.

Google присваивает каждой странице рейтинг в зависимости от количества обратных ссылок (сколько ссылок на других сайтах указывают на конкретный сайт / страницу). Это называется оценка релевантности. Это основано на том факте, что если на страницу ссылается много других страниц, это, вероятно, важная страница.

Каждый сайт / страница рассматривается как узел на графике. Ссылки на другие страницы являются направленными краями. Степень вершины определяется как количество входящих ребер. Узлы с большим числом входящих ребер ранжируются выше.

Вот как определяется PageRank. Предположим, что страница Pj имеет ссылки Lj. Если одна из этих ссылок ведет на страницу Pi, то Pj передаст 1 / Lj своей важности для Pi. Рейтинг важности Pi - это сумма всех вкладов, сделанных ссылками на него. Итак, если мы обозначим множество страниц, ссылающихся на Pi, через Bi, то у нас есть эта формула:

Importance(Pi)= sum( Importance(Pj)/Lj ) for all links from Pi to Bi

Ранги размещаются в матрице, называемой матрицей гиперссылки: H [i, j]

Строка в этой матрице либо 0, либо 1 / Lj, если есть ссылка от Pi до Bi. Другое свойство этой матрицы состоит в том, что если мы сложим все строки в столбце, мы получим 1.

Теперь нам нужно умножить эту матрицу на собственный вектор с именем I (с собственным значением 1), такой что:

I = H*I

Теперь мы начинаем итерацию: I H, I I H, I I I H .... I ^ k * H, пока решение не сходится , то есть мы получаем почти одинаковые числа в матрице на шаге k и k + 1.

Теперь то, что осталось в векторе I, является важностью каждой страницы.

Простой пример домашнего задания см. http://www.math.cornell.edu/~mec/Winter2009/RalucaRemus/Lecture3/lecture3.html

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

1 голос
/ 29 апреля 2011

Зависит от того, насколько глубоким должен был быть их вопрос.Если бы они просто пытались избежать перехода по одним и тем же ссылкам туда-сюда, то хэширования URL-адресов было бы достаточно.

А как насчет контента, который имеет буквально тысячи URL-адресов, ведущих к одному и тому же контенту?Как и параметр QueryString, который ни на что не влияет, но может иметь бесконечное число итераций.Я полагаю, что вы также можете хэшировать содержимое страницы и сравнивать URL-адреса, чтобы увидеть, похожи ли они на перехват содержимого, идентифицируемого несколькими URL-адресами.См., Например, Bot Traps, упомянутые в сообщении @ Lirik.

0 голосов
/ 06 мая 2019

Веб-сканер - это компьютерная программа, которая использовалась для сбора / сканирования следующих ключевых значений (ссылок HREF, ссылок изображений, метаданных и т. Д.) С заданного URL-адреса веб-сайта.Он спроектирован как интеллектуальный, чтобы переходить по различным ссылкам HREF, которые уже получены из предыдущего URL, поэтому Crawler может переходить с одного веб-сайта на другой.Обычно это называется веб-паук или веб-бот.Этот механизм всегда действует как основа поисковой системы в Интернете.

Пожалуйста, найдите исходный код из моего технического блога - http://www.algonuts.info/how-to-built-a-simple-web-crawler-in-php.html

<?php
class webCrawler
{
    public $siteURL;
    public $error;

    function __construct()
    {
        $this->siteURL = "";
        $this->error = "";
    }

    function parser()   
    {
        global $hrefTag,$hrefTagCountStart,$hrefTagCountFinal,$hrefTagLengthStart,$hrefTagLengthFinal,$hrefTagPointer;
        global $imgTag,$imgTagCountStart,$imgTagCountFinal,$imgTagLengthStart,$imgTagLengthFinal,$imgTagPointer;
        global $Url_Extensions,$Document_Extensions,$Image_Extensions,$crawlOptions;

        $dotCount = 0;
        $slashCount = 0;
        $singleSlashCount = 0;
        $doubleSlashCount = 0;
        $parentDirectoryCount = 0;

        $linkBuffer = array();

        if(($url = trim($this->siteURL)) != "")
        {
            $crawlURL = rtrim($url,"/");
            if(($directoryURL = dirname($crawlURL)) == "http:")
            {   $directoryURL = $crawlURL;  }
            $urlParser = preg_split("/\//",$crawlURL);

            //-- Curl Start --
            $curlObject = curl_init($crawlURL);
            curl_setopt_array($curlObject,$crawlOptions);
            $webPageContent = curl_exec($curlObject);
            $errorNumber = curl_errno($curlObject);
            curl_close($curlObject);
            //-- Curl End --

            if($errorNumber == 0)
            {
                $webPageCounter = 0;
                $webPageLength = strlen($webPageContent);
                while($webPageCounter < $webPageLength)
                {
                    $character = $webPageContent[$webPageCounter];
                    if($character == "")
                    {   
                        $webPageCounter++;  
                        continue;
                    }
                    $character = strtolower($character);
                    //-- Href Filter Start --
                    if($hrefTagPointer[$hrefTagLengthStart] == $character)
                    {
                        $hrefTagLengthStart++;
                        if($hrefTagLengthStart == $hrefTagLengthFinal)
                        {
                            $hrefTagCountStart++;
                            if($hrefTagCountStart == $hrefTagCountFinal)
                            {
                                if($hrefURL != "")
                                {
                                    if($parentDirectoryCount >= 1 || $singleSlashCount >= 1 || $doubleSlashCount >= 1)
                                    {
                                        if($doubleSlashCount >= 1)
                                        {   $hrefURL = "http://".$hrefURL;  }
                                        else if($parentDirectoryCount >= 1)
                                        {
                                            $tempData = 0;
                                            $tempString = "";
                                            $tempTotal = count($urlParser) - $parentDirectoryCount;
                                            while($tempData < $tempTotal)
                                            {
                                                $tempString .= $urlParser[$tempData]."/";
                                                $tempData++;
                                            }
                                            $hrefURL = $tempString."".$hrefURL;
                                        }
                                        else if($singleSlashCount >= 1)
                                        {   $hrefURL = $urlParser[0]."/".$urlParser[1]."/".$urlParser[2]."/".$hrefURL;  }
                                    }
                                    $host = "";
                                    $hrefURL = urldecode($hrefURL);
                                    $hrefURL = rtrim($hrefURL,"/");
                                    if(filter_var($hrefURL,FILTER_VALIDATE_URL) == true)
                                    {   
                                        $dump = parse_url($hrefURL);
                                        if(isset($dump["host"]))
                                        {   $host = trim(strtolower($dump["host"]));    }
                                    }
                                    else
                                    {
                                        $hrefURL = $directoryURL."/".$hrefURL;
                                        if(filter_var($hrefURL,FILTER_VALIDATE_URL) == true)
                                        {   
                                            $dump = parse_url($hrefURL);    
                                            if(isset($dump["host"]))
                                            {   $host = trim(strtolower($dump["host"]));    }
                                        }
                                    }
                                    if($host != "")
                                    {
                                        $extension = pathinfo($hrefURL,PATHINFO_EXTENSION);
                                        if($extension != "")
                                        {
                                            $tempBuffer ="";
                                            $extensionlength = strlen($extension);
                                            for($tempData = 0; $tempData < $extensionlength; $tempData++)
                                            {
                                                if($extension[$tempData] != "?")
                                                {   
                                                    $tempBuffer = $tempBuffer.$extension[$tempData];
                                                    continue;
                                                }
                                                else
                                                {
                                                    $extension = trim($tempBuffer);
                                                    break;
                                                }
                                            }
                                            if(in_array($extension,$Url_Extensions))
                                            {   $type = "domain";   }
                                            else if(in_array($extension,$Image_Extensions))
                                            {   $type = "image";    }
                                            else if(in_array($extension,$Document_Extensions))
                                            {   $type = "document"; }
                                            else
                                            {   $type = "unknown";  }
                                        }
                                        else
                                        {   $type = "domain";   }

                                        if($hrefURL != "")
                                        {
                                            if($type == "domain" && !in_array($hrefURL,$this->linkBuffer["domain"]))
                                            {   $this->linkBuffer["domain"][] = $hrefURL;   }
                                            if($type == "image" && !in_array($hrefURL,$this->linkBuffer["image"]))
                                            {   $this->linkBuffer["image"][] = $hrefURL;    }
                                            if($type == "document" && !in_array($hrefURL,$this->linkBuffer["document"]))
                                            {   $this->linkBuffer["document"][] = $hrefURL; }
                                            if($type == "unknown" && !in_array($hrefURL,$this->linkBuffer["unknown"]))
                                            {   $this->linkBuffer["unknown"][] = $hrefURL;  }
                                        }
                                    }
                                }
                                $hrefTagCountStart = 0;
                            }
                            if($hrefTagCountStart == 3)
                            {
                                $hrefURL = "";
                                $dotCount = 0;
                                $slashCount = 0;
                                $singleSlashCount = 0;
                                $doubleSlashCount = 0;
                                $parentDirectoryCount = 0;
                                $webPageCounter++;
                                while($webPageCounter < $webPageLength)
                                {
                                    $character = $webPageContent[$webPageCounter];
                                    if($character == "")
                                    {   
                                        $webPageCounter++;  
                                        continue;
                                    }
                                    if($character == "\"" || $character == "'")
                                    {
                                        $webPageCounter++;
                                        while($webPageCounter < $webPageLength)
                                        {
                                            $character = $webPageContent[$webPageCounter];
                                            if($character == "")
                                            {   
                                                $webPageCounter++;  
                                                continue;
                                            }
                                            if($character == "\"" || $character == "'" || $character == "#")
                                            {   
                                                $webPageCounter--;  
                                                break;  
                                            }
                                            else if($hrefURL != "")
                                            {   $hrefURL .= $character; }
                                            else if($character == "." || $character == "/")
                                            {
                                                if($character == ".")
                                                {
                                                    $dotCount++;
                                                    $slashCount = 0;
                                                }
                                                else if($character == "/")
                                                {
                                                    $slashCount++;
                                                    if($dotCount == 2 && $slashCount == 1)
                                                    $parentDirectoryCount++;
                                                    else if($dotCount == 0 && $slashCount == 1)
                                                    $singleSlashCount++;
                                                    else if($dotCount == 0 && $slashCount == 2)
                                                    $doubleSlashCount++;
                                                    $dotCount = 0;
                                                }
                                            }
                                            else
                                            {   $hrefURL .= $character; }
                                            $webPageCounter++;
                                        }
                                        break;
                                    }
                                    $webPageCounter++;
                                }
                            }
                            $hrefTagLengthStart = 0;
                            $hrefTagLengthFinal = strlen($hrefTag[$hrefTagCountStart]);
                            $hrefTagPointer =& $hrefTag[$hrefTagCountStart];
                        }
                    }
                    else
                    {   $hrefTagLengthStart = 0;    }
                    //-- Href Filter End --
                    //-- Image Filter Start --
                    if($imgTagPointer[$imgTagLengthStart] == $character)
                    {
                        $imgTagLengthStart++;
                        if($imgTagLengthStart == $imgTagLengthFinal)
                        {
                            $imgTagCountStart++;
                            if($imgTagCountStart == $imgTagCountFinal)
                            {
                                if($imgURL != "")
                                {
                                    if($parentDirectoryCount >= 1 || $singleSlashCount >= 1 || $doubleSlashCount >= 1)
                                    {
                                        if($doubleSlashCount >= 1)
                                        {   $imgURL = "http://".$imgURL;    }
                                        else if($parentDirectoryCount >= 1)
                                        {
                                            $tempData = 0;
                                            $tempString = "";
                                            $tempTotal = count($urlParser) - $parentDirectoryCount;
                                            while($tempData < $tempTotal)
                                            {
                                                $tempString .= $urlParser[$tempData]."/";
                                                $tempData++;
                                            }
                                            $imgURL = $tempString."".$imgURL;
                                        }
                                        else if($singleSlashCount >= 1)
                                        {   $imgURL = $urlParser[0]."/".$urlParser[1]."/".$urlParser[2]."/".$imgURL;    }
                                    }
                                    $host = "";
                                    $imgURL = urldecode($imgURL);
                                    $imgURL = rtrim($imgURL,"/");
                                    if(filter_var($imgURL,FILTER_VALIDATE_URL) == true)
                                    {   
                                        $dump = parse_url($imgURL); 
                                        $host = trim(strtolower($dump["host"]));
                                    }
                                    else
                                    {
                                        $imgURL = $directoryURL."/".$imgURL;
                                        if(filter_var($imgURL,FILTER_VALIDATE_URL) == true)
                                        {   
                                            $dump = parse_url($imgURL); 
                                            $host = trim(strtolower($dump["host"]));
                                        }   
                                    }
                                    if($host != "")
                                    {
                                        $extension = pathinfo($imgURL,PATHINFO_EXTENSION);
                                        if($extension != "")
                                        {
                                            $tempBuffer ="";
                                            $extensionlength = strlen($extension);
                                            for($tempData = 0; $tempData < $extensionlength; $tempData++)
                                            {
                                                if($extension[$tempData] != "?")
                                                {   
                                                    $tempBuffer = $tempBuffer.$extension[$tempData];
                                                    continue;
                                                }
                                                else
                                                {
                                                    $extension = trim($tempBuffer);
                                                    break;
                                                }
                                            }
                                            if(in_array($extension,$Url_Extensions))
                                            {   $type = "domain";   }
                                            else if(in_array($extension,$Image_Extensions))
                                            {   $type = "image";    }
                                            else if(in_array($extension,$Document_Extensions))
                                            {   $type = "document"; }
                                            else
                                            {   $type = "unknown";  }
                                        }
                                        else
                                        {   $type = "domain";   }

                                        if($imgURL != "")
                                        {
                                            if($type == "domain" && !in_array($imgURL,$this->linkBuffer["domain"]))
                                            {   $this->linkBuffer["domain"][] = $imgURL;    }
                                            if($type == "image" && !in_array($imgURL,$this->linkBuffer["image"]))
                                            {   $this->linkBuffer["image"][] = $imgURL; }
                                            if($type == "document" && !in_array($imgURL,$this->linkBuffer["document"]))
                                            {   $this->linkBuffer["document"][] = $imgURL;  }
                                            if($type == "unknown" && !in_array($imgURL,$this->linkBuffer["unknown"]))
                                            {   $this->linkBuffer["unknown"][] = $imgURL;   }
                                        }
                                    }
                                }
                                $imgTagCountStart = 0;
                            }
                            if($imgTagCountStart == 3)
                            {
                                $imgURL = "";
                                $dotCount = 0;
                                $slashCount = 0;
                                $singleSlashCount = 0;
                                $doubleSlashCount = 0;
                                $parentDirectoryCount = 0;
                                $webPageCounter++;
                                while($webPageCounter < $webPageLength)
                                {
                                    $character = $webPageContent[$webPageCounter];
                                    if($character == "")
                                    {   
                                        $webPageCounter++;  
                                        continue;
                                    }
                                    if($character == "\"" || $character == "'")
                                    {
                                        $webPageCounter++;
                                        while($webPageCounter < $webPageLength)
                                        {
                                            $character = $webPageContent[$webPageCounter];
                                            if($character == "")
                                            {   
                                                $webPageCounter++;  
                                                continue;
                                            }
                                            if($character == "\"" || $character == "'" || $character == "#")
                                            {   
                                                $webPageCounter--;  
                                                break;  
                                            }
                                            else if($imgURL != "")
                                            {   $imgURL .= $character;  }
                                            else if($character == "." || $character == "/")
                                            {
                                                if($character == ".")
                                                {
                                                    $dotCount++;
                                                    $slashCount = 0;
                                                }
                                                else if($character == "/")
                                                {
                                                    $slashCount++;
                                                    if($dotCount == 2 && $slashCount == 1)
                                                    $parentDirectoryCount++;
                                                    else if($dotCount == 0 && $slashCount == 1)
                                                    $singleSlashCount++;
                                                    else if($dotCount == 0 && $slashCount == 2)
                                                    $doubleSlashCount++;
                                                    $dotCount = 0;
                                                }
                                            }
                                            else
                                            {   $imgURL .= $character;  }
                                            $webPageCounter++;
                                        }
                                        break;
                                    }
                                    $webPageCounter++;
                                }
                            }
                            $imgTagLengthStart = 0;
                            $imgTagLengthFinal = strlen($imgTag[$imgTagCountStart]);
                            $imgTagPointer =& $imgTag[$imgTagCountStart];
                        }
                    }
                    else
                    {   $imgTagLengthStart = 0; }
                    //-- Image Filter End --
                    $webPageCounter++;
                }
            }
            else
            {   $this->error = "Unable to proceed, permission denied";  }
        }
        else
        {   $this->error = "Please enter url";  }

        if($this->error != "")
        {   $this->linkBuffer["error"] = $this->error;  }

        return $this->linkBuffer;
    }   
}
?>
0 голосов
/ 21 февраля 2019

Мне также потребовалось использовать сканер, и я не могу найти подходящий для моего требования, поэтому после этого я разработал базовую библиотеку сканера для реализации простых требований. Но дает возможность выполнить практически все принципы работы гусеничного хода. Вы можете проверить DotnetCrawler github repo , который реализует модули Downloader-Processor-Pipeline самостоятельно с реализацией по умолчанию, используя Entity Framework Core для сохранения данных на Sql Server.

https://github.com/mehmetozkaya/DotnetCrawler

0 голосов
/ 07 июля 2016

Искатель хранит пул URL-адресов, который содержит все URL-адреса, подлежащие обходу.Чтобы избежать «бесконечного цикла», основная идея состоит в проверке существования каждого URL-адреса перед добавлением в пул.

Однако это нелегко реализовать, когда система масштабируется до определенного уровня.Наивным подходом является сохранение всех URL-адресов в хэш-наборе и проверка существования каждого нового URL-адреса.Это не сработает, если в памяти слишком много URL-адресов.

Здесь есть несколько решений.Например, вместо того, чтобы хранить все URL-адреса в памяти, мы должны хранить их на диске.Для экономии места следует использовать хеш URL вместо необработанного URL.Также стоит отметить, что мы должны сохранить каноническую форму URL, а не исходную.Поэтому, если URL-адрес сокращается такими службами, как bit.ly, лучше получить окончательный URL-адрес.Чтобы ускорить процесс проверки, можно создать слой кеша.Или вы можете увидеть его как систему распределенного кэша, которая является отдельной темой.

В посте Создание веб-сканера содержится подробный анализ этой проблемы.

0 голосов
/ 04 июня 2015

Это пример веб-сканера. Который может быть использован для сбора адресов Mac для подмены Mac.

#!/usr/bin/env python

import sys
import os
import urlparse
import urllib
from bs4 import BeautifulSoup

def mac_addr_str(f_data):
global fptr
global mac_list
word_array = f_data.split(" ")

    for word in word_array:
        if len(word) == 17 and ':' in word[2] and ':' in word[5] and ':' in word[8] and ':' in word[11] and ':' in word[14]:
            if word not in mac_list:
                mac_list.append(word)
                fptr.writelines(word +"\n")
                print word



url = "http://stackoverflow.com/questions/tagged/mac-address"

url_list = [url]
visited = [url]
pwd = os.getcwd();
pwd = pwd + "/internet_mac.txt";

fptr = open(pwd, "a")
mac_list = []

while len(url_list) > 0:
    try:
        htmltext = urllib.urlopen(url_list[0]).read()
    except:
        url_list[0]
    mac_addr_str(htmltext)
    soup = BeautifulSoup(htmltext)
    url_list.pop(0)
    for tag in soup.findAll('a',href=True):
        tag['href'] = urlparse.urljoin(url,tag['href'])
        if url in tag['href'] and tag['href'] not in visited:
            url_list.append(tag['href'])
            visited.append(tag['href'])

Измените URL, чтобы сканировать больше сайтов ...... удачи

0 голосов
/ 19 декабря 2011

Проблема здесь не в том, чтобы сканировать дублированные URL-адреса, которые решаются с помощью индекса с использованием хэша, полученного из URL-адресов.Проблема в том, чтобы сканировать дублированный контент.Каждый URL-адрес "ловушки гусеничного устройства" различен (год, день, SessionID ...).

Не существует "идеального" решения ... но вы можете использовать некоторые из этих стратегий:

• Держите поле такого уровня, чтобы URL-адрес находился внутри веб-сайта.Для каждого цикла получения URL со страницы увеличивайте уровень.Это будет как дерево.Вы можете прекратить ползти на определенном уровне, например 10 (я думаю, Google использует это).

• Вы можете попытаться создать своего рода HASH, который можно сравнить, чтобы найти похожие документы, поскольку вы не можете сравнить каждый документ в вашей базе данных.Есть SimHash от Google, но я не мог найти какую-либо реализацию для использования.Тогда я создал свой собственный.Мой хэш подсчитывает низко и высокочастотные символы в html-коде и генерирует 20-байтовый хеш, который сравнивается с небольшим кэшем последних просканированных страниц в AVLTree с поиском NearNeighbors с некоторым допуском (около 2).Вы не можете использовать любую ссылку на расположение символов в этом хеше.После «распознавания» ловушки вы можете записать шаблон URL дублированного контента и начать игнорировать страницы с этим тоже.

• Как и в Google, вы можете создать рейтинг для каждого веб-сайта и «доверять» другимодин, чем другие.

0 голосов
/ 29 апреля 2011

Ну, в основном веб - это ориентированный граф, так что вы можете построить график из URL, а затем выполнить обход BFS или DFS, пометив посещенные узлы, чтобы не посещать одну и ту же страницу дважды.

0 голосов
/ 29 апреля 2011

Вам понадобится какая-то хеш-таблица для хранения результатов, вам просто нужно проверить ее перед каждой загрузкой страницы.

...