编程语言
首页 > 编程语言> > 关于PHP中的Web Crawler的错误

关于PHP中的Web Crawler的错误

作者:互联网

我正在尝试使用PHP创建一个简单的Web爬虫,它能够抓取.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);
                        }*/
                    }
                }
            }
        }
        }
    }   
}

现在您可以看到initiateParentCrawler函数正在调用initiateChildCrawler,该函数将父链接传递给子爬虫.父链接示例:www.berkeley.edu,爬虫将在其主页上找到所有链接并返回其所有html内容.这种情况发生在种子网址耗尽之前.

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

其他功能是不言自明的.

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

但是,如果我将爬行子链接的限制设置为10或更少(通过更改$forEachCount变量),爬虫就可以正常工作了.

请帮助我这方面.

来自CLI的消息:

Problem signature:
Problem Event Name: APPCRASH
Application Name: php-cgi.exe
Application Version: 5.3.8.0
Application Timestamp: 4e537939
Fault Module Name: php5ts.dll
Fault Module Version: 5.3.8.0
Fault Module Timestamp: 4e537a04
Exception Code: c0000005
Exception Offset: 0000c793
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 1033
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789

解决方法:

扁平环示例:

>使用包含您首先要处理的所有URL的堆栈启动循环.
>循环内部:

>您从堆栈中移动第一个URL(您获取它并将其删除).
>如果找到新URL,则在堆栈末尾添加它们(推送).

这将一直运行,直到处理堆栈中的所有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,因为它是一个更通用的工具.

标签:php,web,web-scraping,web-crawler
来源: https://codeday.me/bug/20191008/1873819.html