如何在php中创建一个有效的网络爬虫


How to create an effective web crawler in php

我正在尝试创建一个网络爬虫。我发现了一个非常有用的网站,但有一个问题。它只在一个页面中找到链接,而我想在整个网站中找到所有的链接,子链接,而不仅仅是一个页面。经过一段时间的研究,我在一些网站上看到有人建议创建循环函数,调用过程中的过程。

在我这样做之后,又出现了另一个问题,有太多重复的链接,php代码因为没有分配足够的内存而出错。我尝试了几种方法来消除重复链接,但都不起作用。我最好的方法是使用这个数组,不在数组中的链接将被保留,而已经在数组中中的链接则将被忽略。但到目前为止,情况仍然不好。

可能有人能帮我吗?这是我的密码。

    ini_set('memory_limit','1024M');
    include_once('simple_html_dom.php');
    $urlarray = array();
    $a=0;
    function crawl_page($target_url, $urlarray){
    $html = new simple_html_dom();
    $html->load_file($target_url);
    foreach($html->find('a') as $link)
    {   
        if (!in_array($link->href, $urlarray)) {
             $arraysize = sizeof($urlarray);
             echo $link->href."<br />";
             $urlarray[$arraysize] = $link->href;
             crawl_page($link->href, $urlarray);
          }
        }
     }
     $url[0]= "http://www.lazada.co.id";
     crawl_page("http://www.lazada.co.id", $url);

结果是:

(!)致命错误:第555 行的C:''wamp''www''testcrawler''simple_html_dom.php中超过了120秒的最长执行时间

更新:

我已经解决了。我在stackoverflow的某个地方找到了有同样问题的链接。有人建议不要使用递归模型,而是使用队列模型。所以我将代码修改为队列模型,它就起作用了。现在我写这篇文章的时候,我的网络爬虫运行得很好。

Web爬网不仅仅是从网页中提取数据。。但正如你在问题中提到的,我想你只是想从网页中提取一些元素

因此,PHP有phpQuery库来交互提取网页。。它不是php中唯一的库,但却是最受欢迎的

我希望能帮助你

在速度方面,我想没有什么能比得上旧的strpossubstr组合。

这基本上很不方便,但我已经用这种方法编写了几个爬网程序,我怀疑它在技术上是否能比PHP更快。

这里有一个简单的例子:

function extractVideoURL(&$html,$start)
{
    $value = strpos($html,'meta name="twitter:player:stream" content="',$start)+strlen('meta name="twitter:player:stream" content="');
    $end = strpos($html,'"',$value);
    $URL = substr($html,$value,$end-$value);
    return $URL;    
}

此外,内存开销相当低,因为您不需要将HTML解析为另一个结构。

以下是PHP Web爬网程序的完整代码和解释,让我们开始吧:

    <?php
    // set user agent 
      ini_set('user_agent', 'NameOfAgent (http://www.example.net)');
    //initializing url to crawl
      $url = "http://www.example.net/somepage.html";
     //checking robots.txt and extracting more links, sublinks from url
 if(robots_allowed($url, "NameOfAgent")) {
        $input = @file_get_contents($url) or die("Could not access file: $url");
        $regexp = "<a's[^>]*href=('"??)([^'" >]*?)''1[^>]*>(.*)<'/a>";
        if(preg_match_all("/$regexp/siU", $input, $matches, PREG_SET_ORDER)) {
          foreach($matches as $match) {
            // $match[2] = link address it means that will show you link title
            // $match[3] = link text it means that will show you link title
          }
        }
      } else {
        die('Access denied by robots.txt');
      }
   
//function for extracting title, keywords, description from url
    function file_get_contents_curl($url)
    {
    $ch = curl_init();
        curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_URL, $url);
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
                        $data = curl_exec($ch);
                            curl_close($ch);
                                return $data;
                                }
                                $html = file_get_contents_curl($url);
                                //parsing begins here:
                                $doc = new DOMDocument();
                                @$doc->loadHTML($html);
                                $nodes = $doc->getElementsByTagName('title');
                                //get and display what you need:
                                $title = $nodes->item(0)->nodeValue;

                       $metas = $doc->getElementsByTagName('meta');
                                for ($i = 0; $i < $metas->length; $i++)
                                {
                                    $meta = $metas->item($i);
                                        if($meta->getAttribute('name') == 'description')
                                                $description = $meta->getAttribute('content');
                                                    if($meta->getAttribute('name') == 'keywords')
                                                            $keywords = $meta->getAttribute('content');
                                } 
}

希望能有所帮助。