一、什么是爬虫?
网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。(来自百度百科)
二、爬虫准备
(一)基础知识
1.了解CURL爬虫过程
2.了解被爬网站(以URP教务为例)数据传输过程
(1)思路解析
A 、先打开登陆页面,获取cookies
B、再访问验证码的地址,因为验证码是动态的,每次打开都是不同的,所以我们需要保存之前的cookie,保证获取的验证码和后续要提交的表单是同步的
C、构建post表单请求数据,然后将数据提交给网站
D、获取响应头信息,通过返回的网页内容来判断是否登陆成功
E、登陆成功后模拟get请求获取数据,模拟post请求进行教学评估、选课等操作
3.正则匹配知识
(二)php环境搭建
1.php开启curl
具体怎么开启CSDN等网站上很多教程,不再补充
三、开始编码
(一)分析浏览器请求网页的流程
1.在web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML发送给浏览器。但是在没有携带cookie的情况下,如果IP短时间高并发的请求网站,该IP就会被封。
这里解释一下cookie,cookie是一种回话机制,可以用来存储很多信息,也经常用于反爬。
我们一般处理cookie有两种方法:
1、cookie的保存
2、cookie的读取
然后登陆部分的处理通常采用的方法就是将爬虫模拟成浏览器:
1、通过opener添加headers
2、通过requests添加headers
3、批量添加headers
本次采用的是第二种方法。
用浏览器打开教务处系统的界面如下:
2.上面提到的headers,cookie等参数的获取,在登陆页面按F12进入开发者模式,选择network,再选中消息头,如图操作:(图片为火狐浏览器)
给大家解释下上图的主要信息,在伪装浏览器部分中,重点是获取请求的头部信息和服务器返回的响应头(response headers)。
1 request url :是浏览器真实请求的地址
2 accept :告诉浏览器自己接受什么类型
3 accept language :浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到
4 connection 表示是否是持久连接。
5 host 初始url中的主机端口
6 user-agent :浏览器类型
关于提交表单的获取,我们可以尝试故意输错账号或者密码得到提交的表单信息,即通过进入开发者工具抓包
(二)PHP爬虫代码核心部分解读
1. 验证码获取、保存、展示
//保存session会话
$id = session_id();
$_SESSION['id'] = $id;
//cookie保存
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
//模拟get请求获取验证码
$random = '0.'.mt_rand(100000,999999).mt_rand(100000,999999).mt_rand(10000,99999);
$url_img='http://zhjw.hbu.edu.cn/validateCodeAction.do?random='.$random;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_img);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($ch, CURLOPT_TIMEOUT,6);
curl_setopt($ch, CURLOPT_REFERER, 'http://zhjw.hbu.edu.cn/');
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);
$img = curl_exec($ch);
//保存验证码到本地以便展示给用户
$img_code = rand(0,500);
setcookie('img_cookie',$img_code);
$img_name = 'vcode'.$img_code.'.jpg';
$op_file = fopen('./images/'.$img_name, 'w');
fwrite($op_file,$img);
fclose($op_file);
//关闭爬虫操作
curl_close($ch);
展示:
<img src="./images/<?php echo $img_name?>" alt="">
2.处理POST表单传过来的数据进行模拟登录
以json数据返回登录信息:$result
<?php
header('Content-Type: application/json; charset=utf8');
session_start();
error_reporting(0);
class Response{
/*
* 调用登陆
*/
public function Login($post){
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$ch = curl_init("http://zhjw.hbu.edu.cn/loginAction.do");
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT,6);
curl_setopt($ch, CURLOPT_REFERER, 'http://zhjw.hbu.edu.cn/');
curl_setopt($ch, CURLOPT_POST,1) ;
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_jar);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
$data = curl_exec($ch);
$this->Result($data);
curl_close($ch);
}
/*
* 登陆结果 输出json
*/
public function Result($data) {
$data = iconv("gb2312","utf-8//IGNORE",$data);
$guize = '/<font color=\"#990000\">(.*?)<\/font/is';
preg_match_all($guize,$data,$big_class);
if(!empty($big_class[1][0])) {
//登录失败、组装数据返回
$result = array(
'Status' => 403,
'Title' => '提示:',
'Msg' => $big_class[1][0],
);
//变成json格式的
//JSON_UNESCAPED_UNICODE让中文不编码
echo json_encode($result, JSON_UNESCAPED_UNICODE);
}else{
//登录成功、组装数据返回
$result=array(
'Status'=>200,
'Title'=>'提示:',
'Msg'=>'登陆成功!',
);
//变成json格式的
//JSON_UNESCAPED_UNICODE让中文不编码
echo json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
}
$post = array(
'zjh1' => '',
'tips'=> '',
'lx' => '',
'evalue' => '',
'eflag' => '',
'fs' => '',
'dzslh' => '',
'zjh' => $_POST['zjh'],
'mm' => $_POST['mm'],
'v_yzm' => $_POST['v_yzm'],
);
$post=http_build_query($post);
$login = new Response();
$login->Login($post);
?>
3.登陆成功后模拟GET请求获取学生信息
/*
* 模拟GET
*/
session_start();
//注意修改成自己学校的教务地址,该地址为查看学籍信息显示
$url = 'http://zhjw.xxx.edu.cn/xjInfoAction.do?oper=xjxx';
//调用保存的cookies
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$ch = curl_init() ;
curl_setopt($ch, CURLOPT_URL,$url) ;
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,6);
curl_setopt($ch, CURLOPT_REFERER, 'http://zhjw.hbu.edu.cn/');
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_jar);
$data=curl_exec($ch);
curl_close($ch);
$data = iconv("GBK","utf-8//IGNORE",$data);
//var_dump($data);
//正则匹配开始
$guize = '/<td(.*?\s)width=\"275\">(.*?)<\/td>/is'
//此结果 $arr_info[2][0] 为姓名,其他数据可以自己查看
preg_match_all($guize,$data,$arr_info);
4.登陆成功后模拟POST请求进行教学评估
页面post方法将评估表中的数据传输到模拟请求的php界面
session_start();
class Response{
/*
* 模拟POST
*/
public function JXPGPost($post){
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$ch = curl_init("http://zhjw.hbu.edu.cn/jxpgXsAction.do?oper=wjpg");
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT,6);
curl_setopt($ch, CURLOPT_REFERER, 'http://zhjw.hbu.edu.cn/jxpgXsAction.do');
curl_setopt($ch, CURLOPT_POST,1) ;
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_jar);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
$data = curl_exec($ch);
curl_close($ch);
$this->Result($data);
}
/*
* 分析评教结果
*/
public function Result($data) {
$data = iconv("gb2312","utf-8//IGNORE",$data);
$guize = '/alert\(\"(.*?)\"\)/is';
preg_match_all($guize,$data,$info);
echo "<div style = 'text-align:center'>
<br><h3>".$info[1][0]."</h3><br>";
}
}
//处理post过来的数据,修改格式
$str = "";
$flag = 0;
foreach($_POST as $key=>$val) {
if($val == '')
{
$val = "";
}
if($flag == 0)
{
$str = $key."=".$val;
$flag ++;
}
else
{
$str = $str."&".$key."=".$val;
}
}
$login = new Response();
$login->JXPGPost($str);
四、说明
因为源码已经在河北大学易班学生工作站使用,产权归易班学生工作站,所以不能公开源码,核心代码只有这几行,剩下的无非就是前端框架(我用的layui)和数据处理(比如:对爬取到的数据进行正则匹配)。