PHP爬虫开发

文章目录

  • ==PHP爬虫开发==
    • 一、爬虫开发原理与实现
      • php爬取网页源代码
      • php爬取网页图片
    • 二、使用SimpleHtmlDom
    • 三、使用正则表达式

PHP爬虫开发

一、爬虫开发原理与实现

(1)XML和HTML本质上是相同的结构:DOMDocument可以处理XML,原则上来说也可以处理HTML。

(2)爬虫主要是爬取网页的内容(基于HTTP和HTML的内容),可以爬取一个网站上的图片,文件,页面内容等。

(3)搜索引擎的工作原理:爬取网页内容,对内容进行分词,分词后建立索引(倒排索引),进行排序后提供服务。

(4)爬取的基本过程:给定一个网址,然后解析响应的HTML页面内容,并下载保存(HTML文件),然后解析其中的超链接或其他资源(比如图片等),超链接就进行继续的访问和存档,图片就进行下载存档,给予找到的超链接,又继续解析更多的超链接。

(5)技术层面的实现要点:

  • 发送GET请求并获取响应的内容: file_get_contents
  • 解析页面中的URL地址或资源地址:DOMDocument
  • 继续访问解析出来的地址或资源:根据地址的特点分类和拼接,构建一个完整的URL地址库,继续访问,继续前面两步。(广度优先,深度优先)

php爬取网页源代码

<?php
    /**爬取页面源代码 */
    $contents = file_get_contents("http://www.woniunote.com/");
    // echo $contents;  //获取到页面的内容,其源代码和源页面源代码一致
    $html = new DOMDocument();
    $html->preserveWhiteSpace = false;

    @$html->loadHTML($contents);  //在前面加 @ 可以防止warnning警告的输出
    $links = $html->getElementsByTagName("a");
    // print_r($links);  // 输出结果 DOMNodeList Object ( [length] => 93 ) 我们可以看出这是一个链表,下面我们来遍历

    /**输出页面源代码中的超链接并存储到数组中 */
    $LinkList = array();
    foreach($links as $link) {     
        // echo $link->nodeValue."<br>";  // 这个输出的是 <a></a> 中的值
        // echo $link->attributes->item(0)->nodeValue."<br>";  // 但注意,不是所有的<a></a>节点中的第一个属性都是href  
        foreach($link->attributes as $attr) {
            if($attr->nodeName == 'href') {
                // echo $attr->nodeValue."<br>";  // 得到的结果有三个类型 分别是以 / # http 开头
                // 利用 / # http 三个特征来判断href值的类型,以此分别拼接超链接
                if($attr->nodeValue[0] == '/' || $attr->nodeValue[0] == '#') {
                //if(strpos($attr->nodeValue,'/') == 0) //用这个判断也是可以的
                    // echo $attr->nodeValue[0];
                    echo "http://www.woniunote.com/".$attr->nodeValue."<br>";
                    $link = "http://www.woniunote.com/".$attr->nodeValue;
                    array_push($LinkList,$link);
                }
                else if($attr->nodeValue[0] == 'h') {
                    echo $attr->nodeValue."<br>";
                    array_push($LinkList,$attr->nodeValue);
                }
            }
        }
    }
?>

php爬取网页图片

<?php

    $contents = file_get_contents('http://www.woniunote.com/');

    $html = new DOMDocument();
    @$html->loadHTML($contents);

    $links = $html->getElementsByTagName('img'); // $links 是链表的形式存在的

    $LinkList = array();
    foreach($links as $link) {
        // echo $link->attributes->item(0)->nodeName." ";
        // echo $link->attributes->item(0)->nodeValue."<br>";
        foreach($link->attributes as $attr) {
            if($attr->nodeName == 'src') {
                // echo "http://www.woniunote.com".$attr->nodeValue."<br>";
                // $link = "http://www.woniunote.com".$attr->nodeValue;
                // array_push($LinkList,$link);
                if(strpos($attr->nodeValue,'/') == 0) {
                    // echo "http://www.woniunote.com".$attr->nodeValue."<br>";
                    array_push($LinkList,"http://www.woniunote.com".$attr->nodeValue);
                }
                else if(strpos($attr->nodeValue,'https://') == 0) {
                    // echo $attr->nodeValue."<br>";
                    array_push($LinkList,$attr->nodeValue);
                }
            }
        }
    }

    // print_r($LinkList);

    /**将爬取到的图片保存起来 */
    foreach($LinkList as $link) {
        $content = file_get_contents($link);

        // $suffix = end(explode('.',$link));
        // echo $link."<br>";

        // 以下两个判断中,如果不使用 === 强制类型也判断相等的话,那么 http:// == 0 的判断结果 https:// 也能通过,不知道是什么bug
        if(strpos($link,'http://') === 0 ) {  
            // echo $link;

            $filename1 = str_replace('http://www.woniunote.com/','',$link);
            $filename1 = str_replace('/','-',$filename1);
            // echo $filename1."<br>";
            file_put_contents("./download/image/$filename1",$content);
            echo "下载成功:$filename1 <br>"; 
        }
        else if(strpos($link,'https://') === 0) {
            // echo $link;

            $filename2 = str_replace('https://woniuxyopenfile.oss-cn-beijing.aliyuncs.com/woniuxynote/thumb/','',$link);
            // $filename = str_replace('/','-',$filename);
            // $filename = $filename;
            file_put_contents("./download/image/$filename2",$content);
            echo "下载成功:$filename2 <br>";  
        }
        ob_flush();
        flush();
        sleep(0.5);
        
    }
?>

二、使用SimpleHtmlDom

下载地址:http://simplehtmldom.sourceforge.net/

使用教程:https://blog.csdn.net/qq_36025814/article/details/89500333

如何使用PHP的第三方库:(1)使用include或Require引用到源码中(2)Composer

<?php
    /**这把使用PHP的第三方库实现爬虫 */
    include_once('./simple_html_dom.php');
    $html = file_get_html("http://www.woniunote.com/");

    /**查找超链接 */
    // $links = $html->find('a');
    // foreach($links as $link) {
    //     echo $link->href."<br>";
    // }

    // 查找图片链接,不过该代码因为iconv() 函数的问题导致报错,这个问题一直不知道该如何解决
    // $images = $html->find('img');
    // foreach($images as $image) {
    //     // echo $image->src."<br>";
    //     $src = $image->src;
    //     if(strpos($src,'/') == 0) {
    //         $url = "http://www.woniunote.com/".$src;
    //     }
    //     else if(strpos($src,'http') == 0) {
    //         $url = $src;
    //     }
    //     $filename = end(explode('/',$url));
    //     $content = file_get_html($url);
    //     file_put_contents("./download/image/$filename",$content); 
    //     echo "下载成功:$filename <br>";
    //     ob_flush();
    //     flush();
    //     sleep(0.5);
    // } 

    /**使用其他方式定位元素 */
    // 使用类似XPath方式定位元素
    // $titles = $html->find('div[@class="title"]');  
    // $titles = $html->find('div[class="title"]');
    // $titles = $html->find('div.title');  //由于html中 class 在css样式中使用 . 表示,故在这里也可以已使用 .
    // foreach($titles as $title) {
    //     echo $title->innertext."<br>";
    //     // innertext 表示 被 <div></div> 标签包裹的所有内容,也包含 <a></a> 标签
    //     echo $title->outertext."<br>";
    //     // outertext 表示查找到的 <div></div> 标签本身,和他所包裹的所有内容
    //     echo $title->plaintext."<br>";
    //     // plaintext 表示 被 <div></div> 标签包裹的内容中 <a></a> 标签 所包裹的文本内容
    // }

    // 使用ID属性定位元素
    // $nodes = $html->find('input[@id="keyword"]');  // 这种情况返回的都是数组形式,因为simple_html_php并不知道找出的结果是多少个,于是所有返回结果都是数组
    $nodes = $html->find('input#keyword');
    foreach($nodes as $node) {
        echo $node->placeholder."<br>";  // placeholder 就是标签节点中的文本内容
    }
    // 上面代码可以优化。我们知道一份源代码中 input标签中id=keyword只有一个,那么完全可以不使用数组遍历的方式
    // 直接给定元素下标找对应的某一个元素
    $node = $html->find('input#keyword',0);
    echo $node->placeholder."<br>";
    
    /**元素之间的层次关系 */
    $nodes = $html->find('div.title');
    foreach($nodes as $node) {
        echo $node->first_child()->innertext."<br>";        
    }
    // 使用完DOM结构后,清空内存,减少内存消耗
    $html->clear();
?>

三、使用正则表达式

/**使用正则表达式如何解析页面元素 */
// 正则表达式是将一份HTML源码理解为一个长长的字符串,进而使用正则表达式进行字符串解析和匹配
// 由于超链接或一些其他元素是没有固定格式的,因此我们需要换一种方式
// 使用 设定左右边界来找超链接或其他元素 
$content = file_get_contents('http://www.woniunote.com/');
// $pattern = '/<a href="(.*)"/';  //贪婪模式
// 贪婪模式: .* 匹配除换行符之外的任意符号零次或多次,能往后匹配就往后匹配,直至匹配本行结束
$pattern = '/<a href="(.+?)"/';  // 非贪婪模式
// 非贪婪模式:.+?匹配除换行符之外的任意字符1次或多次,然后加了个 ? 表示,匹配到的字符零次或一次
// 这个 . 的前面就不需要加 \ ,因为加上 \ 表示对 . 进行转义,使得 . 变变成一个普通字符用来匹配
// 正则表达式中 . 本来表示  匹配除换行符(\n、\r)之外的任何单个字符。
preg_match_all($pattern,$content,$results);
print_r($results);
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值