可以的
爬虫有什么用?先说一下爬虫是什么东西,我认为爬虫就是一个网络信息收集程序, 也许我自己的理解有错误,也请大家给我指正。既然爬虫是一个网络信息收集程序, 那就是用来收集信息,并且收集的信息是在网络上面的。如果还是不太清楚爬虫有什么用, 我就举几个爬虫应用的例子:搜索引擎就需要爬虫收集网络信息供人们去搜索;大数据的数据,数据从哪里来? 就是可以通过爬虫在网络中爬取(收集)而来。
Python 我说实话,我不会 Python。( Python 我真不会,想知道可能你要去百度一下,因为 Python 我真不会。) PHP 写东西我一直都是认为,你只要想出算法程序就已经出来了,不用考虑太多数据类型的问题。 PHP 的语法和其他编程语言差不多,就算你开始不会 PHP,你也可以马上上手。 PHP的语法和其他编程语言差不多,就算你开始不会 PHP,你也可以马上上手。的想法有错。)
PHP爬虫第一步,第一步......第一步当然就是搭建 PHP 的运行环境,没有环境PHP又怎么能运行呢? 就像鱼不能离开水一样。(我见识还不够,可能我举的鱼的例子不够好,请见谅。) 在Windows的系统下我使用 WAMP,而在Linux的系统下我使用 LNMP 或者 LAMP。
WAMP:Windows + Apache + Mysql + PHP
LAMP:Linux + Apache + Mysql + PHP
LNMP:Linux + Nginx + Mysql + PHP
Apache 和 Nginx 是 Web 服务器软件。
Apache或Nginx、Mysql 以及 PHP 这些都是 PHP Web 的基本配置环境。
网上有 PHP Web 环境的安装包,这些安装包使用很方便,不需要每给东西安装以及配置。
但如果你对这些集成安装包担心安全问题,你可以到这些程序的官网下载然后在网上找配置教程就可以了。(说真的,我真心的不会单独去弄,我觉得很麻烦。)
<?php
// 爬虫核心功能:获取网页源码
$html = file_get_contents("https://www.baidu.com/index.html");
// 通过 php 的 file_get_contents 函数获取百度首页源码,并传给 $html 变量
echo $html;
// 输出 $html
?>
爬虫网络核心功能已经写出来了,为什么说就这么几行代码就把爬虫核心功能写出来了呢? 我猜有人已经明白了吧,其实是因为爬虫是数据获取的程序,就上面几行代码其实已经能够获取数据了,所以爬虫的核心功能已经写出来了。
搜索引擎的爬虫有时候不是不能那个网站的页面获取页面源码,而是有robot.txt文件,有该文件的网站,
就代表站主不希望爬虫去爬取页面源码。(不过如果你就是想要获取的话,就算有也一样会去爬吧!)
我搜索引擎的爬虫其实还有很多不足而导致的限制,例如可能因为无法运行 JS 脚本所以无法获取页面源码。
又或者网站有反爬虫的机制导致不能获取到页面源码。
有反爬虫机制的网站就如:知乎,知乎就是有反爬虫的机制的网站。
PHP 编写基础
正则表达式
数据库的使用(本文使用 MySql 数据库)
运行环境(只要有能运行 PHP 网站的环境和数据库就OK)
<?PHP
// 通过 file_get_contents 函数获取百度页面源码
$html = file_get_contents("https://www.baidu.com/index.html");
// 通过 preg_replace 函数使页面源码由多行变单行
$htmlOneLine = preg_replace("/\r|\n|\t/","",$html);
// 通过 preg_match 函数提取获取页面的标题信息
preg_match("/<title>(.*)<\/title>/iU",$htmlOneLine,$titleArr);
// 由于 preg_match 函数的结果是数组的形式
$title = $titleArr[1];
// 通过 echo 函数输出标题信息
echo $title;
?>
报错误示例:
Warning: file_get_contents("https://https://127.0.0.1/index.php")
[function.file-get-contents]: failed to open stream: Invalid argument in E:\website\blog\test.php on line 25
https是SSL加密协议,如果出现获取页面时报上面的错误,代表你的 PHP 可能少了OpenSSL 的模块,你可以到网上查找解决办法。
虽然我没见过像“百度”,“Google”它们的爬虫,可是我自己通过猜测,以及在实际爬去过程当中遇到的一些问题,自己总结的几个特点。
通用性是因为我认为搜索引擎的爬虫一开始并不是针对哪一个网站制定的,所以要求能爬取到的网站尽可能的多,这是第一点。
而第二点,就是获取网页的信息就是那些,一开始不会因为某些个别特殊小网站而放弃某些信息不提取,
举个例子:一个小网站的一个网页meta标签里没有描述信息(description)或者关键词信息(keyword),
就直接放弃了描述信息或者关键词信息的提取,当然如果真的某一个页面没有这些信息我会提取页面里的文字内容作为填充,
反正就是尽可能达到爬取的网页信息每个网页的信息项都要一样。这是我认为的搜索引擎爬虫的通用性,当然我的想法可能是错误的。
不确定性就是我的爬虫获取什么网页我是控制不够全面的,只能控制我能想到的情况,
这也是因为我写的算法就是这样的原因,我的算法就是爬取获取到的页面里的所有链接,再去爬去获取到的这些链接,
其实是因为搜索引擎并不是搜某一些东西,而是尽可能的多,因为只有更多的信息,才能找到一个最贴切用户想要的答案。
所以我就觉得搜索引擎的爬虫就要有不确定性。
下面的视频是我的搜索网站的使用视频,而搜到的信息就是通过自己写的 PHP 爬虫获取到的。
获取的源码出现乱码
<?PHP
// 乱码解决办法,把其他编码格式通过 mb_convert_encoding 函数统一转为 UTF-8 格式
$html = mb_convert_encoding($html,'UTF-8','UTF-8,GBK,GB2312,BIG5');
// 还有一种因为gzip所以出现乱码的,我会在以后讲
?>
<?PHP
// 获取不到标题信息解决办法,首先判断是否能获取到页面源码
// 如果能获取到但还是不能获取到标题信息
// 我猜测的问题是:因为我教的是使用正则表达式获取的,源码没有变成一行,获取起来就会出现问题
$htmlOneLine=preg_replace("/\r|\n|\t/","",$html);
?>
<?PHP
// 像新浪微博你可能获取到的是“Sina Visitor System”
// 解决办法添加header信息
$opts = array(
'http'=>array(
'method'=>"GET",
"timeout"=>20,
'header'=>"User-Agent: Spider \r\n",
)
);
$context = stream_context_create($opts);
$html = file_get_contents($domain,0,$context,0,150000);
// 这样就能获取到新浪微博的页面了
?>
我们先不去想很多网页,因为很多网页也就是一个循环。
- 获取页面源码
- 通过源码提取页面的什么信息
- 提取的信息要怎么处理
- 处理后放不放进数据库
<?php
// 一、获取源码
// 假设我们要获取淘宝首页
$html = file_get_content("https://www.taobao.com");
// 二、提取标题和文本
// 三、提取信息处理
// 处理页面源码,多行变单行
$htmlOneLine = preg_replace("/\r|\n|\t/","",$html);
// 获取标题信息
preg_match("/<title>(.*)<\/title>/iU",$htmlOneLine,$titleArr);
// 保留标题信息
$titleOK = $titleArr[1];
// 获取页面中的文本信息
// 处理前面不需要的head标签
$htmlText = preg_replace("/<html>(.*)<\/head>/","",$htmlOneLine);
// 处理style和script标签及内容
$htmlText = preg_replace("/<style(.*)>(.*)</style>|<script(.*)>(.*)</script>/iU","",$htmlText);
// 处理多余标签
$htmlText = preg_replace("/<(\/)?(.+)>/","",$htmlText);
// 四、保存到数据库
// 略
?>
-
获取页面源码
-
获取页面的图片链接
-
使用函数保存图片
<?php
// 使用file_get_contents()函数获取图片
$img = file_get_contents("http://127.0.0.1/photo.jpg");
// 使用file_put_contents()函数保存图片
file_put_contents("photo.jpg",$img);
?>
本来我以为自己写的爬虫已经写得差不多了,就是除了反爬虫的网站难以爬取外,应该是都可以爬了。
但有一天我去尝试爬去bilibili的时候出现问题了,我发现怎么我数据库里面的都是乱码,而且标题什么的都没有,好奇怪!
后来我才知道原来是因为GZIP的压缩,原来我直接使用file_get_content函数获取的页面是未经过解压的页面,所有都是乱码!
好了,然后我知道问题出现在那里了,接下来就是想解决办法了。(其实那时候的我是完全不知道怎么解决解压gzip的,都靠搜索引擎)。
我得到了两个解决办法:
在 request header 那里告诉对方服务器,我这爬虫(不。。。应该是我这浏览器)不支持gzip的解压,就麻烦你不要压缩,直接把数据发给我吧!
// 这是request header(请求头)
$opts = array(
'http'=>array(
'method'=>"GET",
"timeout"=>20,
'header'=>"User-Agent: Spider \r\n".
"accept-encoding:"
)
);
// 我把accept-encodeing(能接收编码)设为空,代表不接受gzip
如果告诉了对方服务器本浏览器(爬虫)不支持解压gzip,可他还是继续发gzip的数据给你,那就没有办法了,只好默默的在搜索引擎找php解压gzip的解压函数——gzdecode()。
网页爬虫就好比自动的网页源码另存为操作,可是如果真的是一个一个网址手动输入给爬虫去爬取的话,
那还倒不如人手另存为呢!
所以在这里就得解析到那些子链接,一个网页其实会有很多的a标签,而这些a标签的href属性值就会是一个子链接。
通过很多种工具的解析得到了原始的子链接
为什么叫原始数据,
因为这些子链接有很多不是URL链接,又或者是一些不完整的链接,又或者你是要爬一个网站,不要爬虫跑出去的时候,
还得去除一些并非那个网站的链接,防止爬虫跑出去。下面我列举一些原始子链接。
http://wxample.com/
./index.html
index.html
//example.com/index.html
javascript:;
../index.html
http://example2.com/index.html
你可以看得到这里有很多种链接,有完整的绝对路径的链接,也有不完整的相对路径链接,
有的还跑来了javascript,如果是相对路径或javascript的链接,直接给爬虫去爬,肯定让爬虫一脸懵,因为不完整或根本就不是一个链接。
所以就需要对子链接补全或者丢弃。
处理其实就是去重、丢弃以及补全。
对于相同的子链接丢弃不保存
对于相对路径链接补全
对于不是链接的链接丢弃(不是链接的链接是什么东西?自己都觉得的奇怪。。。。)
对于第一种我就不多说了,相信大家都知道该怎么做。
对付第二种的方法我就写一个能够运行相对路径的方法出来就OK了,通过父链接来进行相对路径转绝对路径。
对于第三种也正则匹配一下就完了。
未完待续。。。