Data structures 网络爬虫的设计

Data structures 网络爬虫的设计,data-structures,search-engine,web-crawler,google-search,large-data-volumes,Data Structures,Search Engine,Web Crawler,Google Search,Large Data Volumes,我在面试中遇到了一个问题:“如果你在设计一个网络爬虫,你将如何避免陷入无限循环?”我正试图回答这个问题 这一切是如何从头开始的。 假设谷歌从一些中心页面开始,说有数百个(这些中心页面最初是如何找到的是另一个子问题)。 由于谷歌跟踪页面的链接等等,它是否一直在制作一个哈希表,以确保它不会跟踪之前访问过的页面 如果同一个页面有两个名称(URL),那么现在我们有URL缩写器等等 我以谷歌为例。虽然谷歌没有透露其网络爬虫算法和页面排名等的工作原理,但任何猜测都取决于他们的问题的深度。如果他们只是试图避免

我在面试中遇到了一个问题:“如果你在设计一个网络爬虫,你将如何避免陷入无限循环?”我正试图回答这个问题

这一切是如何从头开始的。 假设谷歌从一些中心页面开始,说有数百个(这些中心页面最初是如何找到的是另一个子问题)。 由于谷歌跟踪页面的链接等等,它是否一直在制作一个哈希表,以确保它不会跟踪之前访问过的页面

如果同一个页面有两个名称(URL),那么现在我们有URL缩写器等等


我以谷歌为例。虽然谷歌没有透露其网络爬虫算法和页面排名等的工作原理,但任何猜测都取决于他们的问题的深度。如果他们只是试图避免重复相同的链接,那么对URL进行散列就足够了


如果内容中有成千上万个URL指向相同的内容,那该怎么办?就像QueryString参数一样,它不影响任何东西,但可以有无限次的迭代。我想您也可以散列页面的内容,并比较URL,看看它们是否类似于由多个URL标识的捕获内容。例如,请参阅@Lirik的帖子中提到的Bot陷阱。

您必须有某种哈希表来存储结果,您只需在每次加载页面之前检查它

web基本上是一个有向图,因此您可以用URL构建一个图,然后在标记访问的节点时进行BFS或DFS遍历,这样您就不会访问同一页面两次

如果你想得到一个详细的答案,请看一看,它描述了现代刮板的URL测试:

在提取链接的过程中,任何 网络爬虫将遇到多个问题 指向同一文档的链接。避 下载和处理文档 多次,一个URL测试必须 将在每个提取的链接上执行 在将其添加到URL边界之前。 (另一种设计是: 而是在以下情况下执行URL测试: URL已从边界中删除, 但这种方法将导致 更大的边界。)

执行 在测试中,我们存储了所有 墨卡托在canonical中看到的URL 在一个称为URL的大表中创建表单 设置同样,条目太多 为了让他们都能留在记忆中,就像 文档指纹集、URL 集合主要存储在磁盘上

挽救 空间,我们不存储文本 URL中每个URL的表示形式 一套,但尺寸固定 校验和。不像指纹 提交给内容seen测试的 文档指纹集,流 根据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变得非常容易。谷歌甚至公开了他们的散列功能:

警告
他们可能也在谈论机器人陷阱!!!bot陷阱是页面的一部分,它不断生成具有唯一URL的新链接,通过跟踪该页面提供的链接,您将陷入“无限循环”中。这并不完全是一个循环,因为循环是访问同一个URL的结果,但它是一个无限的URL链,您应该避免爬行

2012年12月13日更新-世界末日的第二天:) 根据Fr0zenFyr的评论:如果使用该算法选择页面,那么很容易避免无限循环类型的bot陷阱。以下是AOPIC工作原理的总结:

  • 获取一组N个种子页
  • 为每个页面分配X个信用额度,以便在开始爬网之前,每个页面都有X/N信用额度(即相等的信用额度)
  • 选择一个页面P,其中P的信用额度最高(或者如果所有页面的信用额度相同,则爬网一个随机页面)
  • 爬网页面P(假设P在爬网时有100个学分)
  • 从第P页提取所有链接(假设有10个)
  • 将P的积分设置为0
  • 取10%的“税”并将其分配到Lambda页面
  • 从P的原始抵免中为P页上的每个链接分配相等数量的抵免-税:so(100(P抵免)-10(10%税))/10(链接)=每个链接9个抵免
  • 重复步骤3
  • 由于Lambda页面不断地征税,最终它将成为拥有最大信用额度的页面,我们将不得不“爬行”它。我用引号说“爬行”,因为我们实际上并没有
    Importance(Pi)= sum( Importance(Pj)/Lj ) for all links from Pi to Bi
    
    I = H*I
    
    #!/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'])
    
    <?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;
        }   
    }
    ?>