Development Tip

웹 크롤러 디자인

yourdevel 2020. 11. 8. 11:23
반응형

웹 크롤러 디자인


인터뷰 질문 "웹 크롤러를 설계하고 있다면 어떻게 무한 루프에 빠지지 않겠습니까?"라는 질문에 답을하려고합니다.

모든 것이 처음부터 어떻게 시작됩니까? Google이 일부 허브 페이지로 시작했다고 가정 해 보겠습니다 (처음에 이러한 허브 페이지가 어떻게 발견되었는지는 다른 하위 질문입니다). Google은 페이지 등의 링크를 따라갈 때 이전에 방문한 페이지를 따르지 않도록 해시 테이블을 계속 만듭니다.

URL 단축기 등이있는 요즘 같은 페이지에 2 개의 이름 (URL)이 있으면 어떨까요?

저는 Google을 예로 들었습니다. Google은 웹 크롤러 알고리즘 및 페이지 순위 등이 작동하는 방식을 유출하지는 않지만 추측이 있습니까?


자세한 답변을 얻으려면 최신 스크레이퍼의 URL로 본 테스트를 설명하는 이 문서 3.8 섹션참조하십시오 .

링크를 추출하는 과정에서 웹 크롤러는 동일한 문서에 대한 여러 링크를 보게됩니다. 문서를 여러 번 다운로드하고 처리하지 않으려면 URL 프론티어에 문서를 추가하기 전에 추출 된 각 링크에 대해 URL-seen 테스트를 수행해야합니다. (대체 디자인은 URL이 프론티어에서 제거 될 때 URL-seen 테스트를 대신 수행하는 것이지만,이 접근 방식은 훨씬 더 큰 프론티어가됩니다.)

URL-seen 테스트를 수행하기 위해 메르카토르에서 본 모든 URL을 URL 집합이라는 큰 테이블에 표준 형식으로 저장합니다. 다시 말하지만 모두 메모리에 맞추기에는 너무 많은 항목이 있으므로 문서 지문 세트와 마찬가지로 URL 세트는 대부분 디스크에 저장됩니다.

공간을 절약하기 위해 URL 집합에 각 URL의 텍스트 표현을 저장하지 않고 고정 된 크기의 체크섬을 저장합니다. Content-Seen 테스트의 문서 지문 세트에 제시된 지문과 달리 URL 세트에 대해 테스트 된 URL 스트림은 지역성이 중요하지 않습니다. 따라서 백업 디스크 파일에 대한 작업 수를 줄이기 위해 인기있는 URL의 메모리 내 캐시를 유지합니다. 이 캐시에 대한 직관은 일부 URL에 대한 링크가 매우 일반적이므로 메모리에 인기있는 URL을 캐싱하면 인 메모리 적중률이 높아진다는 것입니다.

실제로 2 ^ 18 항목의 인 메모리 캐시와 LRU와 같은 클럭 교체 정책을 사용하여 인 메모리 캐시의 전체 적중률은 66.2 %이고 적중률은 9.5 %입니다. 순 적중률이 75.7 % 인 최근 추가 된 URL 또한 인기있는 URL의 캐시와 최근에 추가 된 URL 테이블에서 누락 된 요청의 24.3 % 중 약 1 = 3이 사용자 공간에있는 랜덤 액세스 파일 구현의 버퍼에 히트를 생성합니다. 이 모든 버퍼링의 최종 결과는 URL 세트에 대해 수행하는 각 멤버십 테스트 결과 평균 0.16 개의 탐색 및 0.17 개의 읽기 커널 호출이 발생한다는 것입니다 (일부 부분은 커널의 파일 시스템 버퍼에서 제공됨). 따라서 각 URL 세트 멤버십 테스트는 문서 지문 세트에 대한 멤버십 테스트보다 1/6 많은 커널 호출을 유도합니다.

기본적으로 각 URL에 대해 고유 한 해시를 보장하는 해싱 기능으로 모든 URL을 해시하고 URL의 지역성으로 인해 URL을 찾기가 매우 쉬워집니다. 구글은 심지어 해싱 기능을 오픈 소스 화했다 : CityHash

경고!
그들은 또한 봇 트랩에 대해 이야기하고 있을지도 모릅니다 !!! 봇 트랩은 고유 한 URL이있는 새 링크를 계속 생성하는 페이지의 섹션이며 해당 페이지에서 제공하는 링크를 따라 가면 기본적으로 "무한 루프"에 갇히게됩니다. 루프는 동일한 URL을 방문한 결과이기 때문에 정확히 루프는 아니지만 크롤링을 피해야하는 무한한 URL 체인입니다.

업데이트 12/13/2012- 세계가 끝나는 다음날 :)

Fr0zenFyr의 의견에 따르면 페이지 선택에 AOPIC 알고리즘을 사용 하면 무한 루프 종류의 봇 트랩을 피하는 것이 매우 쉽습니다. 다음은 AOPIC 작동 방식에 대한 요약입니다.

  1. N 개의 시드 페이지 세트를 가져옵니다.
  2. 크롤링이 시작되기 전에 각 페이지에 X / N 크레딧 (즉, 동일한 크레딧)이 있도록 각 페이지에 X 크레딧을 할당합니다.
  3. 페이지 P를 선택합니다. 여기서 P의 크레딧이 가장 높습니다 (또는 모든 페이지의 크레딧이 동일한 경우 임의의 페이지를 크롤링).
  4. 페이지 P를 크롤링합니다 (P가 크롤링 될 때 100 크레딧이 있다고 가정 해 보겠습니다).
  5. 페이지 P에서 모든 링크를 추출합니다 (10 개가 있다고 가정 해 보겠습니다).
  6. P의 크레딧을 0으로 설정합니다.
  7. 10 %의 "세금"을 받아 Lambda 페이지에 할당합니다.
  8. P의 원래 크레딧에서 페이지 P에있는 각 링크에 동일한 금액의 크레딧을 할당합니다. 세금 : 따라서 (100 (P 크레딧)-10 (10 % 세금)) / 10 (링크) = 각 링크 당 9 크레딧.
  9. 3 단계부터 반복합니다.

Lambda 페이지는 지속적으로 세금을 징수하기 때문에 결국 가장 많은 크레딧이있는 페이지가되며이를 "크롤링"해야합니다. 실제로 Lambda 페이지에 대한 HTTP 요청을하지 않기 때문에 따옴표로 "크롤링"이라고 말합니다. 크레딧을 가져 와서 데이터베이스의 모든 페이지에 균등하게 배포합니다 .

봇 트랩은 내부 링크 크레딧 만 제공하고 외부로부터 크레딧을 거의 얻지 못하기 때문에 (과세에서) 크레딧을 Lambda 페이지로 지속적으로 유출합니다. Lambda 페이지는 해당 크레딧을 데이터베이스의 모든 페이지에 균등하게 배포하고 각주기마다 봇 트랩 페이지는 크레딧이 너무 적어서 거의 다시 크롤링되지 않을 때까지 점점 더 많은 크레딧을 잃게됩니다. 좋은 페이지에서는 종종 다른 페이지에서 발견 된 백 링크로부터 크레딧을 받기 때문에 이것은 발생하지 않습니다. 이로 인해 동적 페이지 순위가 생성되며 데이터베이스의 스냅 샷을 찍을 때마다 보유한 크레딧 양에 따라 페이지 를 정렬하면 실제 페이지 순위 에 따라 대략적으로 정렬 될 가능성이 큽니다. .

이것은 무한 루프 유형의 봇 트랩을 피할 뿐이지 만주의 해야 할 다른 봇 트랩많이 있으며이를 우회하는 방법도 있습니다.


여기에있는 모든 사람들이 이미 웹 크롤러를 만드는 방법을 제안했지만 Google이 페이지 순위를 매기는 방법은 다음과 같습니다.

Google은 콜백 링크 수 (다른 웹 사이트의 링크가 특정 웹 사이트 / 페이지를 가리키는 링크 수)에 따라 각 페이지에 순위를 부여합니다. 이를 관련성 점수라고합니다. 이것은 페이지에 링크 된 다른 페이지가 많이있는 경우 중요한 페이지 일 수 있다는 사실에 기반합니다.

각 사이트 / 페이지는 그래프에서 노드로 표시됩니다. 다른 페이지에 대한 링크는 방향이있는 가장자리입니다. 정점의 각도는 들어오는 가장자리의 수로 정의됩니다. 들어오는 에지 수가 더 많은 노드는 더 높은 순위를 갖습니다.

PageRank가 결정되는 방법은 다음과 같습니다. 페이지 Pj에 Lj 링크가 있다고 가정합니다. 이러한 링크 중 하나가 Pi 페이지에 대한 것이라면 Pj는 해당 중요도의 1 / Lj를 Pi에 전달합니다. Pi의 중요도 순위는 Pi에 연결된 페이지가 만든 모든 기여의 합계입니다. 따라서 Bi에 의해 Pi에 연결되는 페이지 집합을 표시하면 다음 공식이 있습니다.

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

순위는 하이퍼 링크 행렬이라는 행렬에 배치됩니다. H [i, j]

이 행렬의 행은 0 또는 Pi에서 Bi 로의 링크가있는 경우 1 / Lj입니다. 이 행렬의 또 다른 속성은 열의 모든 행을 합하면 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을 참조하십시오 .

인터뷰 질문의 중복 문제를 해결하려면 전체 페이지에서 체크섬을 수행하고 방문한 페이지를 추적하기 위해지도에서 해당 또는 체크섬의 bash를 키로 사용합니다.


그들의 질문이 의도 된 정도에 따라 다릅니다. 동일한 링크를 앞뒤로 따르지 않으려는 경우 URL을 해싱하면 충분합니다.

동일한 콘텐츠로 연결되는 말 그대로 수천 개의 URL이있는 콘텐츠는 어떻습니까? 아무 영향도 미치지 않지만 무한한 반복 횟수를 가질 수있는 QueryString 매개 변수와 같습니다. 페이지의 콘텐츠도 해시하고 URL을 비교하여 여러 URL로 식별되는 콘텐츠를 포착하는 것과 유사한 지 확인할 수 있다고 가정합니다. 예를 들어 @Lirik의 게시물에 언급 된 Bot Traps를 참조하십시오.


결과를 저장할 일종의 해시 테이블이 있어야하고, 각 페이지가로드되기 전에 확인해야합니다.


여기서 문제는 중복 된 URL을 크롤링하는 것이 아니라 URL에서 얻은 해시를 사용하는 색인에 의해 해결됩니다. 문제는 DUPLICATED CONTENT를 크롤링하는 것입니다. "Crawler Trap"의 각 URL은 다릅니다 (연도, 일, SessionID ...).

"완벽한"솔루션은 없지만 다음 전략 중 일부를 사용할 수 있습니다.

• URL이 웹 사이트 내부에있는 수준의 필드를 유지하십시오. 페이지에서 URL을 가져 오는 각 cicle에 대해 수준을 높입니다. 그것은 나무와 같을 것입니다. 10과 같은 특정 수준에서 크롤링을 중지 할 수 있습니다 (Google에서 사용하는 것 같습니다).

• 데이터베이스의 각 문서와 비교할 수 없기 때문에 유사한 문서를 찾기 위해 비교할 수있는 일종의 HASH를 만들 수 있습니다. Google의 SimHash가 있지만 사용할 구현을 찾을 수 없습니다. 그런 다음 내 자신을 만들었습니다. 내 해시는 html 코드 내에서 빈도가 낮은 문자와 빈도가 높은 문자를 계산하고 20 바이트 해시를 생성합니다. 이는 약간의 허용 오차 (약 2)가있는 NearNeighbors 검색이있는 AVLTree 내부의 마지막 크롤링 된 페이지의 작은 캐시와 비교됩니다. 이 해시에서 문자 위치에 대한 참조를 사용할 수 없습니다. 트랩을 "인식"한 후 중복 콘텐츠의 URL 패턴을 기록하고 해당 페이지도 무시할 수 있습니다.

• Google과 마찬가지로 각 웹 사이트에 대한 순위를 생성하고 다른 웹 사이트보다 더 많이 "신뢰"할 수 있습니다.


크롤러는 크롤링 할 모든 URL을 포함하는 URL 풀을 유지합니다. "무한 루프"를 방지하기 위해 기본 아이디어는 풀에 추가하기 전에 각 URL의 존재를 확인하는 것입니다.

그러나 시스템이 특정 수준으로 확장되면 구현하기가 쉽지 않습니다. 순진한 접근 방식은 모든 URL을 해시 세트로 유지하고 각각의 새 URL의 존재를 확인하는 것입니다. 메모리에 맞지 않는 URL이 너무 많으면 작동하지 않습니다.

여기에 몇 가지 해결책이 있습니다. 예를 들어 모든 URL을 메모리에 저장하는 대신 디스크에 보관해야합니다. 공간을 절약하려면 원시 URL 대신 URL 해시를 사용해야합니다. 또한 원래 URL이 아닌 표준 형식의 URL을 유지해야합니다. 따라서 URL이 bit.ly와 같은 서비스에 의해 단축 된 경우 최종 URL을 얻는 것이 좋습니다. 검사 프로세스의 속도를 높이기 위해 캐시 레이어를 만들 수 있습니다. 또는 별도의 주제 인 분산 캐시 시스템으로 볼 수 있습니다.

웹 크롤러 빌드 게시물 에는이 문제에 대한 자세한 분석이 있습니다.


또한 크롤러를 사용해야하는데 내 요구 사항에 적합한 크롤러를 찾을 수 없으므로 간단한 요구 사항을 구현하기 위해 기본 크롤러 라이브러리를 개발했습니다. 그러나 거의 모든 크롤러 원칙을 이행 할 수 있습니다. Sql Server에 데이터를 저장하기 위해 Entity Framework Core를 사용하는 기본 구현으로 Downloader-Processor-Pipeline 모듈을 자체적으로 구현하는 DotnetCrawler github repo확인할 수 있습니다 .

https://github.com/mehmetozkaya/DotnetCrawler


웹 크롤러는 주어진 웹 사이트 URL에서 주요 값 (HREF 링크, 이미지 링크, 메타 데이터 등)을 수집 / 크롤링하는 데 사용되는 컴퓨터 프로그램입니다. 이전 URL에서 이미 가져온 여러 HREF 링크를 따라 가도록 지능적으로 설계되었으므로 이러한 방식으로 크롤러는 한 웹 사이트에서 다른 웹 사이트로 이동할 수 있습니다. 일반적으로 웹 스파이더 또는 웹 봇이라고합니다. 이 메커니즘은 항상 웹 검색 엔진의 백본 역할을합니다.

내 기술 블로그-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;
    }   
}
?>

웹은 기본적으로 방향성 그래프이므로 URL에서 그래프를 구성한 다음 방문한 노드를 표시하는 동안 BFS 또는 DFS 순회를 수행하여 동일한 페이지를 두 번 방문하지 않도록 할 수 있습니다.


This is a web crawler example. Which can be used to collect mac Addresses for mac spoofing.

#!/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'])

Change the url to crawl more sites......good luck

참고URL : https://stackoverflow.com/questions/5834808/designing-a-web-crawler

반응형