PHP与正则爬虫实践

一、前言

之前听说过我们学校有一个学生信息的接口,最近这几天闲来无事,打算用PHP做一个爬虫,爬一下数据。由于我对数据的情有独钟,因此,弄完后打算写个文章记录下我的过程,也算是温习一下(这其中有个小插曲:本来我都写完了,可是因手贱原因,重新安装系统了,又手贱把D盘的一些软件全删了,重新安了一遍,结果把写好的爬虫文件删除了。。。。。。尝试用Recuva软件恢复,可是还是没恢复成功,没办法了,周六中午10点又写了一遍,两个小时吧,才弄好。。。真是累呀~~~~~)。推荐几个关于正则表达式的链接:正则表达式在线工具 ----正则表达式速查表----下载正则表达式CHM

二、正文

这里只用PHP写了爬虫,毕竟其他的我也不会。考虑到需要使用正则,因此我又去温习了一遍正则,网上有很多正则学习的地方,这里就不举例了。因为我是爬的校园内的接口,因此我会隐去网址的一部分。

首先需要获取目标网址,下面 $url 为目标地址,$num 为学号,这个接口是使用学号查询的,因此把学号弄成变量。

$html=file_get_contents($url.$num);
$html=str_replace(array("/r","/n","/t","/s"), '', $html);

为了获取该网页中的数据信息,必须对存储着网页代码的$html文件进行正则查询,因此:

preg_match_all('/<div[^>]*>(.*?)<\/div>/si',$html,$match);

然后我们通过 print_r($match); 会发现,$match 为一个二维数组,其中一个数组中存储着匹配的所有数据,包括学生姓名,性别,学号,学院,校园邮箱,其实还有一个隐藏的信息,那就是身份证号,通过查看网页源代码可以发现,但是 $match 数组中并没有这个数据,为止,我们可以使用下面的代码正则匹配身份证号码,其中$html为保存的网页源码变量,将匹配的身份证号码存入 $idcard ,但是如果想要输出身份证号码的话,要echo $idcard[0];

preg_match('/\d{18}|\d{17}[0-9Xx]/',$html,$idcard);

还有,注意看的话,$match 数组中还没有学生图片的 src 地址,为此我们需要分析网页源码,发现只有一个 img 标签,那就好办了,直接利用下面的正则代码,获取 src ,使用 echo $link[1]; 输出图片链接地址,

preg_match('/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg]))[\'|\"].*?[\/]?>/',$html,$link);

这里输出的图片地址为相对地址,为了正常访问需要在前面加上前缀,具体前缀,可以在网页源码中点击图片链接后查看。

这样,图片地址,学号,姓名,学院,年级,身份证号都可以打印出来了,为了方便建议新建数组,存放这些信息。

三、一些问题

我在爬的过程中遇到很多小问题,下面具体说一说:

  • 要看清 $match 数组中哪些是自己需要的信息,不要弄错了。

  • 这里是查询一个人的信息,如果多人可以弄个 while(1) 的循环。

  • 查询完毕后可以把数据存入数据库或者本地文件,不过建议本地文件,毕竟这样会效率快一些。为了方便导入数据库,在存入文件时需要做一些必要的格式化处理,比如,学生的各个信息之间使用 Tab 分割,一个学生数据存入后,录入文件中一个回车符,这样也可以方便导入数据库。

  • 因为学号的命名规则,前四位代表入学年份,接着两位代表学院编码,接着两位为专业编码,接着三位为专业内自己的编号,如果要是之间不作处理从最开始到最后的话,会浪费很多无用的时间,并且专业内人员的人数大多数都不会超过 500 人,这样每一千里面就会浪费 500 数据的查询时间,建议:先爬一下学院与专业的这四位数组成的学号末尾为 001 的数据,本地记录下,这样在进行爬虫时会节省不少时间,并且如果查询时连续出现 50 个空白数据,然后跳转到下一个专业或者学院代码继续爬,节省时间,等等其他方法。

  • 注意有的学生的查询页中没有隐藏的身份证信息,这样就需要自己加个判断条件,防止写入文件时格式乱了,不利于录入数据库。

  • 该接口使用了安全狗的检测功能,如果频繁查询,系统会屏蔽一段时间,不过这也就是 10 分钟左右的事,这也是需要考虑的,要知道,屏蔽后也会出现界面,这样程序在这个页面捕捉的信息也会写入文件,需要加个判断,比如,个人信息查询界面存在邮箱格式,而安全狗提示界面没有邮箱信息,可以用正则验证是否有邮箱信息,如果有的话,那就 10 分钟之后再试,并且不将获得的数据写入文件。

Author: bugwz
Link: https://bugwz.com/2016/01/26/php-regular/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.