模拟登录顾名思义,就是利于程序去模拟人工访问或登录网站的行为。要了解模拟登录我们不得不了解一下函数CURL
。
什么是CURL?
CURL是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP、FTP、TELNET等。最爽的是,PHP也支持CURL库。使用PHP的CURL库可以简单和有效地去抓网页。你只需要运行一个脚本,然后分析一下你所抓取的网页,然后就可以以程序的方式得到你想要的数据了。无论是你想从从一个链接上取部分数据,或是取一个XML文件并把其导入数据库,那怕就是简单的获取网页内容,CURL 是一个功能强大的PHP库。
建立CURL请求的基本步骤
// 第一步:初始化
curl_init();
// 第二步:设置属性
curl_setopt();
// 第三步:执行并获取结果
curl_exec();
// 第四步:捕获异常
curl_error();
// 第五步:释放句柄
curl_close();
CURL的两种请求:GET和POST
GET请求
CURL的GET请求是用来模拟HTTP的GET请求的,适应于可以通过GET方式访问的网页。代码示例如下:
// 初始化
$ch = curl_init();
// 设置抓取的url
curl_setopt($ch, CURLOPT_URL, 'http://www.baidu.com');;
// 设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 执行命令
$data = curl_exec($ch);
// 捕获异常
$err = curl_error($ch);
// 释放句柄
curl_close($ch);
// 显示数据
var_dump($err, $data);
POST请求
CURL的POST请求可以模块网页里的POST表单提交,同时也可以模拟GEt方式的请求,因此适用范围广范。代码示例如下:
// 初始化并设置抓取的url
$ch = curl_init('http://www.baidu.com/login.php');
// 设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 设置POST方式提交
curl_setopt($ch, CURLOPT_POST, 1);
// 设置POST要提交的参数
$postParam = array(
"username" => "coder",
"password" => "12345",
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postParam);
// 执行命令
$data = curl_exec($ch);
// 捕获异常
$err = curl_error($ch);
// 释放句柄
curl_close($ch);
// 显示数据
var_dump($err, $data);
常用参数
设置头文件的信息作为数据流输出
CURLOPT_HEADER
设置获取的信息以文件流的形式返回
CURLOPT_RETURNTRANSFER
当根据Location重定向时,自动设置header中的Referer信息
CURLOPT_AUTOREFERER
手动设置Referer信息
CURLOPT_REFERER
根据Location重定向地址,递归访问
CURLOPT_FOLLOWLOCATION
设定 HTTP 请求中"Cookie: "部分的内容
CURLOPT_COOKIE
添加Cookie文件,即该文件里包含cookie数据。与上面不同之处是上面设置的字符串,这个需要一下完整的文件路径
CURLOPT_COOKIEFILE
连接结束后,保存Cookie信息的文件
CURLOPT_COOKIEJAR
设置HTTP头字段的数组
CURLOPT_HTTPHEADER
设置POTS请求要提交的参数
CURLOPT_POSTFIELDS
设置模拟登录过期时间
CURLOPT_TIMEOUT
福利来了
对于经常用的操作小编对代码进行了一层封装处理,基本上能满足80%以上的网站模拟,分享给大家:
/**
* curl通用方法 <double.he@qq.com>
*
* @param string $url 地址
* @param string $refererUrl 上一级地址
* @param string $postParam 提交参数,支持字符串和数组形式
* @param string $fromCookie 要带的cookie文件
* @param string $toCookie 生成的cookie文件
* @param string $mode 模式:“phone”模拟手机端,“pc”模拟电脑端
* @param string $contentType 内容类型:“txt”数据以字符类型传递,“json”数据以json类型传递
* @return array
*/
function curl_https($url, $refererUrl = null, $postParam = null, $fromCookie = null, $toCookie = null, $mode = 'phone', $contentType='txt')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
if ($refererUrl !== null) {
curl_setopt($ch, CURLOPT_REFERER, $refererUrl);
}
if ($postParam !== null) {
if (is_string($postParam)) {
$strPost = $postParam;
} else {
$strPost = http_build_query($postParam);
}
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $strPost);
}
if ($contentType === 'json') {
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
}
if ($fromCookie !== null) {
curl_setopt($ch, CURLOPT_COOKIEFILE, $fromCookie);
}
if ($toCookie !== null) {
curl_setopt($ch, CURLOPT_COOKIEJAR, $toCookie);
}
if ($mode === 'phone') {
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1');
} else {
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36');
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$curlInfo = curl_getinfo($ch);
$errMessage = '';
if ($curlInfo['http_code'] !== 200) {
$strPost = (is_string($postParam) || $postParam === null) ? $postParam : http_build_query($postParam);
$errMessage = "Curl request failed, url: {$url} \nPost data: {$strPost} \nReferer url: {$refererUrl} \nfrom Cookie: {$fromCookie} \nTo cookie: {$toCookie} \nmode: {$mode} Content type: {$contentType}\nCurl info: " . var_export($curlInfo, true) . "\nResponse: {$response}";
}
curl_close($ch);
// 组装返回数据
$result = array(
'response' => $response,
'errMessage' => $errMessage,
);
return $result;
}
FAQ
爬取内容与想象的不一致?
答:可能是请求的Url不对或者网页里有重定向,可通过抓包来确认。如果以上两种情况都不是,那么该网页有些内容可能是通过js动态生成的,因为js是在浏览器中才能解析并生成数据,所以爬取不到由它生成的内容
POST请求模拟登录不成功?
答:这个原因有很多方面,总结下来有以下几种情况:
- post参数提交不完整,有的网站反爬策略会在隐藏标签里加入参数,可通过查看源代码确认
- post参数提交不正确,有的网站反爬策略会加入动态字段,每次访问时都会有变化
- 没有设置cookie,网页提交时在请求头里有cookie信息,而你模拟时提交相应cookie
- 有验证码校验,但你提交的验证码cookie与提交时的不一致。解决方法:先模拟请求验证码并把cookie保存下来,再带上cookie和验证码去模拟登录
- 没有设置referer,网页提交时在请求头里有referer信息,而你模拟时没有设置referer
常用工具
模拟登录的成功与否离不开对网页数据及数据的分析,能够清楚的知道整个数据的交互过程是模拟登录要走的第一步,而走好这一步当然离不开一些工具的帮忙。
- Google开发者工具,程序员必备Google浏览器,没有之一
- Fiddler,强大的数据抓包工具,不但可以抓PC端,还可以抓手机端
- 正则测试工具,对抓到的数据进行处理当然离不了它
PHP模拟登录相关的操作小编暂时只想到了这些,如果你有想补充的地方欢迎在下方留言。