使用简单的HTML DOM Parser进行刮擦,但它会突然停止

时间:2014-10-30 16:09:07

标签: php parsing dom

我试图抓住以下页面:http://mangafox.me/manga/

我希望脚本能够点击每个链接并抓取每个漫画的细节,而且大多数情况下我的代码都是这样做的。它有效,但由于某种原因,页面中途停止加载(它甚至没有通过#列表)。

没有错误消息,所以我不知道我在寻找什么。对于我做错了什么,我会很感激。

代码:

    <?php
include('simple_html_dom.php');

set_time_limit(0);

//ini_set('max_execution_time', 300);
//Creates an instance of the simple_html_dom class
$html = new simple_html_dom();
//Loads the page from the URL entered
$html->load_file('http://mangafox.me/manga');
//Finds an element and if there is more than 1 instance the variable becomes an array
$manga_urls = $html->find('.manga_list a');


//Function which retrieves information needed to populate the DB from indiviual manga pages.
function getmanga($value, $url){ 
    $pagehtml = new simple_html_dom();
    $pagehtml->load_file($url);

    if ($value == 'desc') {
        $description = $pagehtml->find('p.summary');
        foreach($description as $d){
            //return $d->plaintext;
            return $desc = $d->plaintext;
        }
        unset($description);
    } else if ($value == 'status') {
        $status = $pagehtml->find('div[class=data] span');
        foreach ($status as $s) {
            $status = explode(",", $s->plaintext);
            return $status[0];
        }
        unset($status);
    } else if ($value == 'genre') {
        $genre = $pagehtml->find('//*[@id="title"]/table/tbody/tr[2]/td[4]');
        foreach ($genre as $g) {
            return $g->plaintext;
        }
        unset($genre);
    } else if ($value == 'author') {
        $author = $pagehtml->find('//*[@id="title"]/table/tbody/tr[2]/td[2]');
        foreach ($author as $a) {
            return $a->plaintext;
        }
        unset($author);
    } else if ($value == 'release') {
        $release = $pagehtml->find('//*[@id="title"]/table/tbody/tr[2]/td[1]');
        foreach ($release as $r) {
            return $r->plaintext;
        }
        unset($release);
    } else if ($value == 'image') {
        $image = $pagehtml->find('.cover img');
        foreach ($image as $i) {
            return $i->src;
        }
        unset($image);
    }

    $pagehtml->clear();
    unset($pagehtml);
} 

foreach($manga_urls as $url) {
    $href = $url->href;
    if (strpos($href, 'http') !== false){
        echo 'Title: ' . $url->plaintext . '<br />';
        echo 'Link: ' . $href . '<br />';
        echo 'Description: ' . getmanga('desc', $href) . '<br />';
        echo 'Status: ' . getmanga('status',$href) . '<br />';
        echo 'Genre: ' . getmanga('genre', $href) . '<br />';
        echo 'Author: ' . getmanga('author', $href) . '<br />';
        echo 'Release: ' . getmanga('release', $href) . '<br />';
        echo 'Image Link: ' . getmanga('image', $href) . '<br />';
        echo '<br /><br />';
    }
}

$html->clear();
unset($html);
?>

2 个答案:

答案 0 :(得分:0)

所以,这不是“只做这个”修复,但我做到了;)

除了导入子页面太多的事实之外,它还有一个巨大的simple_html_dom来迭代。它有13307项,而simple_html_dom不是为了提高速度或效率。它为这种情况下你不需要的东西分配了很多空间。这就是为什么我用正则表达式替换了主要的simple_html_dom。

我认为完全加载还需要很长时间,你最好使用其他语言,但这是一个有效的结果:-) https://gist.github.com/dralletje/ee996ffe4c957cdccd01

答案 1 :(得分:0)

当遇到20k次迭代的循环停止而没有任何错误消息时,我遇到了同样的问题。因此发布解决方案可能会对某人有所帮助。

问题似乎与前面所述的性能有关。因此,我决定使用curl而不是简单的html dom。下面的函数返回网站的内容:

server {
    listen 80;
    server_name myapplication.local;

    index index.php index.html manager.php;

    root /var/www;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    try_files $uri $uri/ /index.php /manager.php;

    if (!-e $request_filename){
        rewrite ^/manager.php/(.*)$ /manager.php?/$1? last;
        rewrite ^/(.*)$ /index.php?/$1? last;
    }

    location ~ /\.ht {
        deny all;
    }

    location = /favicon.ico {
        log_not_found off; access_log off;
    }
    location = /robots.txt {
        log_not_found off; access_log off; allow all;
    }
    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
    }

    sendfile off;
}

现在遍历DOM,我仍然使用简单的html dom,但是代码更改为:

function getContent($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
    curl_close($ch);

    if($result){
        return $result;
    }else{
        return "";
    }
}

在每个循环结束时,将变量unset设置为:

$content = getContent($url);

if($content){
     // Create a DOM object
     $doc = new simple_html_dom();
     // Load HTML from a string
     $doc->load($content);
}else{
     continue;
}