如何在PHP中创建一个简单的爬虫

我想写一个脚本,将包含在这些链接中的所有数据转储到本地文件中。

我想写一个脚本,将包含在这些链接中的所有数据转储到本地文件中。

有人用 PHP 做了吗?一般准则和 gotchas 足以作为答案。

89

嗯。不要parse HTML with regexes

这是一个受 Tatu 启发的 DOM 版本:

<?php
function crawl_page($url, $depth = 5)
{
    static $seen = array();
    if (isset($seen[$url]) || $depth === 0) {
        return;
    }
    $seen[$url] = true;
    $dom = new DOMDocument('1.0');
    @$dom->loadHTMLFile($url);
    $anchors = $dom->getElementsByTagName('a');
    foreach ($anchors as $element) {
        $href = $element->getAttribute('href');
        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 .= dirname($parts['path'], 1).$path;
            }
        }
        crawl_page($href, $depth - 1);
    }
    echo "URL:",$url,PHP_EOL,"CONTENT:",PHP_EOL,$dom->saveHTML(),PHP_EOL,PHP_EOL;
}
crawl_page("http://hobodave.com", 2);

编辑:我修复了 Tatu 版本中的一些错误(现在使用相对 URL)。

编辑:我添加了一点新功能,可以防止它两次跟随相同的 URL。

编辑:现在将输出回显到 STDOUT,以便您可以将其重定向到所需的任何文件

编辑:修复了 George 在他的答案中指出的错误。相对 url 将不再附加到 url 路径的末尾,而是覆盖它。感谢 George 为此。请注意,George 的答案不包含任何内容:https,user,pass 或 port。如果您加载了httpGeorge 扩展,则可以使用http_build_url手动完成。

15

这里我的实现基于上面的例子 / 答案。

它是基于类

使用 Curl

支持 HTTP Auth

跳过不属于基本域的 URL

返回每个页面的 Http 标头响应代码

每页的返回时间

裂纹类:

class crawler
{
    protected $_url;
    protected $_depth;
    protected $_host;
    protected $_useHttpAuth = false;
    protected $_user;
    protected $_pass;
    protected $_seen = array();
    protected $_filter = array();
    public function __construct($url, $depth = 5)
    {
        $this->_url = $url;
        $this->_depth = $depth;
        $parse = parse_url($url);
        $this->_host = $parse['host'];
    }
    protected function _processAnchors($content, $url, $depth)
    {
        $dom = new DOMDocument('1.0');
        @$dom->loadHTML($content);
        $anchors = $dom->getElementsByTagName('a');
        foreach ($anchors as $element) {
            $href = $element->getAttribute('href');
            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 only link that belongs to the start domain
            $this->crawl_page($href, $depth - 1);
        }
    }
    protected function _getContent($url)
    {
        $handle = curl_init($url);
        if ($this->_useHttpAuth) {
            curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
            curl_setopt($handle, CURLOPT_USERPWD, $this->_user . ":" . $this->_pass);
        }
        // follows 302 redirect, creates problem wiht authentication
//        curl_setopt($handle, CURLOPT_FOLLOWLOCATION, TRUE);
        // return the content
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
        /* Get the HTML or whatever is linked in $url. */
        $response = curl_exec($handle);
        // response total time
        $time = curl_getinfo($handle, CURLINFO_TOTAL_TIME);
        /* Check for 404 (file not found). */
        $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
        curl_close($handle);
        return array($response, $httpCode, $time);
    }
    protected function _printResult($url, $depth, $httpcode, $time)
    {
        ob_end_flush();
        $currentDepth = $this->_depth - $depth;
        $count = count($this->_seen);
        echo "N::$count,CODE::$httpcode,TIME::$time,DEPTH::$currentDepth URL::$url <br>";
        ob_start();
        flush();
    }
    protected function isValid($url, $depth)
    {
        if (strpos($url, $this->_host) === false
            || $depth === 0
            || isset($this->_seen[$url])
        ) {
            return false;
        }
        foreach ($this->_filter as $excludePath) {
            if (strpos($url, $excludePath) !== false) {
                return false;
            }
        }
        return true;
    }
    public function crawl_page($url, $depth)
    {
        if (!$this->isValid($url, $depth)) {
            return;
        }
        // add to the seen URL
        $this->_seen[$url] = true;
        // get Content and Return Code
        list($content, $httpcode, $time) = $this->_getContent($url);
        // print Result for current Page
        $this->_printResult($url, $depth, $httpcode, $time);
        // process subPages
        $this->_processAnchors($content, $url, $depth);
    }
    public function setHttpAuth($user, $pass)
    {
        $this->_useHttpAuth = true;
        $this->_user = $user;
        $this->_pass = $pass;
    }
    public function addFilterPath($path)
    {
        $this->_filter[] = $path;
    }
    public function run()
    {
        $this->crawl_page($this->_url, $this->_depth);
    }
}

用法:

// USAGE
$startURL = 'http://YOUR_URL/';
$depth = 6;
$username = 'YOURUSER';
$password = 'YOURPASS';
$crawler = new crawler($startURL, $depth);
$crawler->setHttpAuth($username, $password);
// Exclude path with the following structure to be processed 
$crawler->addFilterPath('customer/account/login/referer');
$crawler->run();
11

查看 PHP Crawler

http://sourceforge.net/projects/php-crawler/

看看是否有帮助。

9

在它的最简单的形式:

function crawl_page($url, $depth = 5) {
    if($depth > 0) {
        $html = file_get_contents($url);
        preg_match_all('~<a.*?href="(.*?)".*?>~', $html, $matches);
        foreach($matches[1] as $newurl) {
            crawl_page($newurl, $depth - 1);
        }
        file_put_contents('results.txt', $newurl."\n\n".$html."\n\n", FILE_APPEND);
    }
}
crawl_page('http://www.domain.com/index.php', 5);

该函数将从页面获取内容,然后抓取所有找到的链接并将内容保存到“results.txt”。这些函数接受第二个参数,深度,它定义了链接应该遵循的长度。如果你只想解析给定页面的链接,请在那里传递 1。

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(149)
如何使用powershell遍历远程注册表项
上一篇
在文本框中显示增值税值(vat box)
下一篇

相关推荐

  • php数组最后一个元素:利用php数组最后一个元素实现新的功能

    示例示例PHP数组最后一个元素可以使用end()函数获取。end()函数将会返回数组中的最后一个元素的值。下面是一个代码示例:…

    2023-01-21 05:01:41
    0 88 50
  • php二维数组转一维数组:数组

    示例示例PHP 二维数组转一维数组可以使用 array_merge() 函数来实现,具体代码示例如下:…

    2023-01-05 00:20:40
    0 52 43
  • php播放器源码让你的音乐播放更加简单、快捷

    PHP播放器源码是一段用于在网页中播放视频的代码,它可以播放多种格式的视频,如MP4、FLV、WMV等。下面是一段PHP播放器源码:…

    2023-01-20 15:57:04
    0 52 10
  • php语言培训班:学习PHP,让你的编程技能达到新高度!

    示例示例PHP语言培训班是一种专门针对PHP语言的培训课程,旨在帮助学习者掌握和深入了解PHP语言的基础知识和编程技能。课程内容包括:PHP语言的基本概念:介绍PHP语言的历史、特点、优势、应用领域等。…

    2023-01-07 02:31:55
    0 76 31
  • php字符串函数大全实现字符串的操作和处理

    示例示例PHP字符串函数大全)函数:该函数返回在预定义的字符前添加反斜杠的字符串。…

    2023-01-31 14:17:08
    0 88 89
  • php课程培训班学习PHP课程培训班,提升你的技能

    PHP课程培训班是一种专业的课程,旨在帮助学习者掌握PHP编程技术。该课程将教授学员如何使用PHP来开发功能丰富的网站和应用程序。…

    2023-01-31 10:03:55
    0 69 16
  • php中文网培训怎么样学习php,提升技能,获得成功!

    PHP中文网培训是一家专注于提供PHP培训的网站,它拥有丰富的课程内容,从基础课程到高级课程,涵盖了整个PHP编程领域。它的课程内容由资深的PHP程序员组成,涵盖了PHP语言的基础知识、PHP开发技术、MySQL数据库技术、Apache Web服务器技术、Linux操作系统技术、HTML5技术、CSS3技术、JavaScript技术等。此外,它还提供了实时在线课程,可以帮助学生快速掌握PHP编程技能。…

    2023-01-26 02:35:59
    0 18 58
  • php项目管理:如何使用PHP项目管理来提高开发效率

    示例示例php项目管理是指在开发php应用程序时,使用一些工具来管理项目的过程。主要包括以下几个步骤:项目规划:在开始项目之前,需要先制定项目的目标,定义项目的功能,确定开发周期和人员安排,并制定一个详细的项目计划,以便更好地管理项目。…

    2023-01-27 05:33:29
    0 50 61

发表评论

登录 后才能评论

评论列表(19条)