有没有办法使用PHP来抓取链接?

时间:2009-09-17 08:18:47

标签: php

我想使用PHP来抓取我们拥有的大约有6或7千个href链接的文档。我们需要的是链接另一端的内容,这意味着PHP必须遵循每个链接并获取链接的内容。可以这样做吗?

由于

6 个答案:

答案 0 :(得分:1)

当然,只需使用像file_get_contents(http://nl.php.net/file_get_contents)这样的函数获取起始网址的内容,使用正则表达式在此页面的内容中查找网址,抓取这些网址的内容等。

Regexp将类似于:

$regexUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";

答案 1 :(得分:0)

我只有一个SQL表,其中包含我找到的所有链接,以及它们是否已被解析。

然后我使用Simple HTML DOM来解析最旧的添加页面,虽然因为它有大页面(500kb + html)的内存耗尽,我使用正则表达式来实现其中一些*。对于每个链接,我发现我将它添加到SQL数据库中需要解析,以及我找到它的时间。

SQL数据库可以防止数据因错误而丢失,因为我有10万多个要解析的链接,我会在很长一段时间内完成。

我不确定,但你检查了file_get_contents()的useragent吗?如果它不是您的页面并且您发出了1000个请求,则可能需要更改用户代理,方法是编写自己的HTTP下载器或使用库中的一个(我使用Zend Framework中的一个)但是cURL等工作得很好。如果您使用自定义用户代理,则允许管理员查看日志以查看有关您的机器人的信息。 (我倾向于说明我爬行的原因以及我的联系方式。)

*我使用的正则表达式是:

'/<a[^>]+href="([^"]+)"[^"]*>/is'

更好的解决方案(来自Gumbo)可能是:

'/<a\s+(?:[^"'>]+|"[^"]*"|'[^']*')*href=("[^"]+"|'[^']+'|[^<>\s]+)/i'

答案 2 :(得分:0)

收获链接后,您可以使用curl或file_get_contents(在安全的环境中,file_get_contents不应允许遍历http协议)

答案 3 :(得分:0)

PHP Snoopy库有许多内置函数可以完全满足您的需求。

http://sourceforge.net/projects/snoopy/

您可以使用Snoopy下载页面本身,然后它还有另一个功能来提取该页面上的所有URL。它甚至会将链接更正为完整的URI(即它们不仅仅与页面所在的域/目录相关)。

答案 4 :(得分:0)

您可以尝试以下操作。有关详细信息,请参阅this thread

<?php
//set_time_limit (0);
function crawl_page($url, $depth = 5){
$seen = array();
if(($depth == 0) or (in_array($url, $seen))){
    return;
}   
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result = curl_exec ($ch);
curl_close ($ch);
if( $result ){
    $stripped_file = strip_tags($result, "<a>");
    preg_match_all("/<a[\s]+[^>]*?href[\s]?=[\s\"\']+"."(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/", $stripped_file, $matches, PREG_SET_ORDER ); 
    foreach($matches as $match){
        $href = $match[1];
            if (0 !== strpos($href, 'http')) {
                $path = '/' . ltrim($href, '/');
                if (extension_loaded('http')) {
                    $href = http_build_url($url, array('path' => $path));
                } else {
                    $parts = parse_url($url);
                    $href = $parts['scheme'] . '://';
                    if (isset($parts['user']) && isset($parts['pass'])) {
                        $href .= $parts['user'] . ':' . $parts['pass'] . '@';
                    }
                    $href .= $parts['host'];
                    if (isset($parts['port'])) {
                        $href .= ':' . $parts['port'];
                    }
                    $href .= $path;
                }
            }
            crawl_page($href, $depth - 1);
        }
}   
echo "Crawled {$href}";
}   
crawl_page("http://www.sitename.com/",3);
?>

答案 5 :(得分:-1)

我建议您将带有6000个URL的HTML文档,解析出来并循环显示您已获得的列表。在循环中,使用file_get_contents获取当前URL的内容(为此,在服务器上启用file_get_contents时,实际上不需要cURL),再次解析包含的URL,依此类推。

看起来像这样:

<?php
function getUrls($url) {
    $doc = file_get_contents($url);
    $pattern = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
    preg_match_all($pattern, $doc, $urls);
    return $urls;
}

$urls = getUrls("your_6k_file.html"); 
foreach($urls as $url) {
    $moreUrls = getUrls($url); 
    //do something with moreUrls
}
?>
相关问题