文章目录
- ==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);