如何使用PHP curl获取具有无限滚动的网页?

4

我想知道如何在循环中爬取一个具有无限滚动(如imgur)的网页,例如...?

我尝试了下面的代码,但它只返回第一页。由于无限滚动模板,我该如何触发下一页?

<?php
    $mr = $maxredirect === null ? 10 : intval($maxredirect);
    if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0);
        curl_setopt($ch, CURLOPT_MAXREDIRS, $mr);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    } else {
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

        if ($mr > 0) {
            $original_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
            $newurl = $original_url;
            $rch = curl_copy_handle($ch);

            curl_setopt($rch, CURLOPT_HEADER, true);
            curl_setopt($rch, CURLOPT_NOBODY, true);
            curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
            do {
                curl_setopt($rch, CURLOPT_URL, $newurl);
                $header = curl_exec($rch);
                if (curl_errno($rch)) {
                    $code = 0;
                } else {
                    $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
                    if ($code == 301 || $code == 302) {
                        preg_match('/Location:(.*?)\n/', $header, $matches);
                        $newurl = trim(array_pop($matches));

                        // if no scheme is present then the new url is a
                        // relative path and thus needs some extra care
                        if(!preg_match("/^https?:/i", $newurl)){
                            $newurl = $original_url . $newurl;
                        }
                    } else {
                        $code = 0;
                    }
                }
            } while ($code && --$mr);
            curl_close($rch);
            if (!$mr) {
                if ($maxredirect === null)
                    trigger_error('Too many redirects.', E_USER_WARNING);
                else
                    $maxredirect = 0;
                return false;
            }
            curl_setopt($ch, CURLOPT_URL, $newurl);
        }
    }
    return curl_exec($ch);
}

$ch = curl_init('http://www.imgur.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec_follow($ch);
curl_close($ch);

echo $data;
?>
2个回答

3
通过获取网页的源代码来工作。您的代码将仅从原始网页中收集HTML。在imgur的情况下,它将包括约40张图片以及其余页面布局。

这个原始源代码在滚动时不会改变。但是,您的浏览器内部的HTML会改变。这是通过AJAX完成的。您正在查看的页面从第二个页面请求信息。

如果您使用FireFox的FireBug或Google Chrome的页面检查器,则可以通过转到Net或Network选项卡(分别)来监视这些请求。当您向下滚动时,页面将再次发出约45个请求(主要用于图像)。您还将看到它请求此页面:

http://imgur.com/gallery/hot/viral/day/page/0?scrolled&set=1

首页的JavaScript在首页底部添加了这段HTML代码。如果你想获取图片列表,你可能需要查询此页面(或API,如另一个Chris所说)。你可以尝试更改URL末尾的数字来获取更多图片。

很好的想法,使用Firebug进行检查!谢谢 - Max Sanchez

0

页面抓取很少是最好的方法,原因就像这样。Imgur提供了一个API,可以完成我假设你正在尝试的任务,而不使用任何hacky抓取。

如果你坚持要抓取,你需要做一些研究。你需要注意AJAX请求所使用的API,直接调用它并继续抓取后续页面的数据,而不仅仅是抓取主页面。考虑到已经有一个成熟的API可用,这种方法的具体细节超出了本答案的范围。

相关阅读


好的,我明白使用imgur API很方便且易于操作,但是我们如何处理其他具有无限滚动功能的网站呢?我们应该仅通过AJAX请求来处理吗? - Max Sanchez
如果没有提供公共API,则可以按照另一个Chris在他的答案中更详细地描述的方式进行操作(我在这里也提到了)。 - Chris Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接