PHP 中有关 Web 爬虫的错误

Posted

技术标签:

【中文标题】PHP 中有关 Web 爬虫的错误【英文标题】:Errors regarding Web Crawler in PHP 【发布时间】:2012-01-31 01:46:31 【问题描述】:

我正在尝试使用 php 创建一个简单的网络爬虫,它能够爬取 .edu 域,提供父级的种子 URL。

我使用简单的html dom来实现爬虫,而一些核心逻辑由我实现。

我在下面发布代码,并会尝试解释问题。

private function initiateChildCrawler($parent_Url_Html) 

    global $CFG;
    static $foundLink;
    static $parentID;
    static $urlToCrawl_InstanceOfChildren;

    $forEachCount = 0;
    foreach($parent_Url_Html->getHTML()->find('a') as $foundLink) 
    
        $forEachCount++;
        if($forEachCount<500) 
        $foundLink->href = url_to_absolute($parent_Url_Html->getURL(), $foundLink->href);

        if($this->validateEduDomain($foundLink->href)) 
        
            //Implement else condition later on
            $parentID = $this->loadSaveInstance->parentExists_In_URL_DB_CRAWL($this->returnParentDomain($foundLink->href));
            if($parentID != FALSE) 
            
                if($this->loadSaveInstance->checkUrlDuplication_In_URL_DB_CRAWL($foundLink->href) == FALSE)
                
                    $urlToCrawl_InstanceOfChildren = new urlToCrawl($foundLink->href);
                    if($urlToCrawl_InstanceOfChildren->getSimpleDomSource($CFG->finalContext)!= FALSE)
                    
                        $this->loadSaveInstance->url_db_html($urlToCrawl_InstanceOfChildren->getURL(), $urlToCrawl_InstanceOfChildren->getHTML());
                        $this->loadSaveInstance->saveCrawled_To_URL_DB_CRAWL(NULL, $foundLink->href, "crawled", $parentID);

                        /*if($recursiveCount<1)
                        
                            $this->initiateChildCrawler($urlToCrawl_InstanceOfChildren);
                        */
                    
                
            
        
        
       

现在您可以看到initiateChildCrawler 被initialParentCrawler 函数调用,该函数将父链接传递给子爬虫。父链接示例:www.berkeley.edu,爬虫将在其主页上找到所有链接并返回其所有 html 内容。这种情况会一直发生,直到种子 URL 用尽为止。

例如: 1-harvard.edu ->>>> 将找到所有链接并返回它们的 html 内容(通过调用 childCrawler)。 移动到 parentCrawler 中的下一个父级。 2-berkeley.edu ->>>> 将找到所有链接并返回它们的 html 内容(通过调用 childCrawler)。

其他功能一目了然。

现在的问题: childCrawler 完成每个链接的 foreach 循环后,函数无法正常退出。如果我从 CLI 运行脚本,CLI 会崩溃。在浏览器中运行脚本会导致脚本终止。

但如果我将爬取子链接的限制设置为 10 个或更少(通过更改 $forEachCount 变量),爬虫就会开始正常工作。

请在这方面帮助我。

来自 CLI 的消息:

问题签名: 问题事件名称:APPRCASH 应用程序名称:php-cgi.exe 应用程序版本:5.3.8.0 申请时间戳:4e537939 故障模块名称:php5ts.dll 故障模块版本:5.3.8.0 故障模块时间戳:4e537a04 异常代码:c0000005 异常偏移量:0000c793 操作系统版本:6.1.7601.2.1.0.256.48 区域设置 ID:1033 附加信息 1:0a9e 附加信息 2:0a9e372d3b4ad19135b953a78882e789 附加信息 3:0a9e 附加信息4:0a9e372d3b4ad19135b953a78882e789

【问题讨论】:

请发布 CLI 崩溃的错误消息。 问题是你使用了太多内存而没有释放它,因为你的方法可能会递归到 $forEachCount 级别的深度,这意味着内存中的完整文档最多可达 $forEachCount。您应该将其转换为平面循环。保留 url 的主列表以及“已处理 url”的主列表,然后遍历未处理的主列表,加载每个页面一次并将链接添加到主列表。然后,您一次只能在内存中保存一个文档。当主列表达到所需长度时停止。 $Ben Lee 我明白你的意思...但是你能解释一下扁平循环这个术语吗? 好吧,现在我正在做的是拥有一组要检索 html 的绝对 URL。现在的问题是,在检索并插入大约 50-60 个 URL 及其 html 内容后,我收到“mysql 服务器已消失”错误。但是,如果我将要检索的 URL 数量限制为更少的数量,比如 10-15,错误就会消失。请在这方面帮助我。 当您将代码更改为使用平面列表时,请在解析单个 url 后尝试sleep(1)。可能你的数据库服务器很弱,不能一次处理很多查询。另外,您可以echo 各种函数中的一些调试信息来查看内存使用情况、解析的 url 数量等。 【参考方案1】:

扁平循环示例:

    您使用包含您要首先处理的所有 URL 的堆栈启动循环。 在循环内部:
      您从堆栈中转移第一个 URL(您获得它并被移除)。 如果您找到新的 URL,则将它们添加到堆栈的末尾(push)。

这将一直运行,直到堆栈中的所有 URL 都被处理,因此您添加(因为您已经以某种方式为 foreach 设置了一个计数器)以防止它运行太久:

$URLStack = (array) $parent_Url_Html->getHTML()->find('a');
$URLProcessedCount = 0;
while ($URLProcessedCount++ < 500) # this can run endless, so this saves us from processing too many URLs

    $url = array_shift($URLStack);
    if (!$url) break; # exit if the stack is empty

    # process URL

    # for each new URL:
    $URLStack[] = $newURL;

您可以通过不将 URL 添加到已经存在的堆栈中来使其更加智能,但是您只需将绝对 URL 插入堆栈。但是我强烈建议您这样做,因为不需要再次处理您已经获得的页面(例如,每个页面都可能包含指向主页的链接)。如果你想这样做,只需在循环内增加$URLProcessedCount,这样你也可以保留以前的条目:

while ($URLProcessedCount < 500) # this can run endless, so this saves us from processing too many URLs

    $url = $URLStack[$URLProcessedCount++];

另外我建议你使用 PHP DOMDocument 扩展而不是简单的 dom,因为它是一个更通用的工具。

【讨论】:

好吧,现在我正在做的是拥有一组要检索 html 的绝对 URL。现在的问题是,在检索并插入大约 50-60 个 URL 及其 html 内容后,我收到“MySQL 服务器已消失”错误。但是,如果我将要检索的 URL 的数量限制为更少的数量,比如 10-15,那么错误就会消失。请在这方面帮助我。 您的数据库拒绝使用您的脚本并已断开连接。这可能有多种原因,您应该联系您的数据库管理员以了解具体情况,您的数据库提供商可能会遇到一些限制。 我自己就是数据库管理员。代码和数据库部署在我自己的电脑上,我不知道该怎么做才能在这里做事。具有讽刺意味的是,数据库在链接数量较少(大约 40-50 个)的情况下运行良好,但在数量较多时返回错误。如果脚本是问题所在,错误就会出现在第一个链接上。 如果您是数据库管理员,请启用数据库日志记录并检查发生了什么。可能发生了一些无效的事情,可以通过重新配置 mysql(或您正在使用的任何数据库)来解决。

以上是关于PHP 中有关 Web 爬虫的错误的主要内容,如果未能解决你的问题,请参考以下文章

使用爬虫技术实现 Web 页面资源可用性检测

Laravel的Web爬虫

需要有关如何加快网络爬虫的建议

Python3爬虫——用Xpath提取网页信息

如何用PHP做网络爬虫

php中curl爬虫 怎么样通过网页获取所有链接