前文
因为代理是需要拿到即可以用,所以我们必须经常去更新代理的状态保证每个都是拿到手的时候可以用,并且也可以衍生去记录代理的质量
命令行使用curl -i “访问的url” 可以打印头部信息,方便更好的查找问题
话不多说直接上代码
用的yii2,写了个方法然后通过在linux配置crontab定时跑脚本更新代理信息
这里是写了个方法批量的去拿代理去检测,我脚本一次拿的200个去检测,多了就报错,具体自己尝试几次就知道多少了
public function actionCheckAgent()
{
//需要检测的代理
$proxy = PurchaseProxyModel::find()
->select(['id','ip','host','port','proxy_user','proxy_password','agreement','address_protocol','status','updated_time'])
->asArray()
->all();
//测试的url,如果有需要获取代理的详细信息也可以自己写个接口返回当前的地址信息
//url如果返回有数据证明代理成功
$url = '检测代理的url地址';
//额,我测试本地环境一次检测超过两百个左右就不行了,所以分批一次200
for ($i=0;count($proxy)>0;$i++){
//初始化cURL批处理句柄
$mh = curl_multi_init();
//一次拿两百个去检测
$checkProxy = array_splice($proxy,0,200);
//方法
$this->batchCheckProxy($checkProxy,$url,$mh);
}
return ExitCode::OK;
}
批量检测方法
public function batchCheckProxy($proxy,$url,$mh)
{
$conn = array();
foreach ($proxy as $key => $value){
$conn[$key]['curl'] = curl_init(); //初始化各个子连接
$conn[$key]['id'] = $value['id']; //顺便加个ip的id进去,方便后面修改他的状态
$header = [
'Accept-Language: zh-C;q=0.8,en-US;q=0.6'
];
//设置url和相应的选项
curl_setopt ($conn[$key]['curl'], CURLOPT_CONNECTTIMEOUT, 1); //设置在发起连接前等待的最长时间,因为不设置是无限等待所以还是设置一下
curl_setopt ($conn[$key]['curl'], CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回,而不是直接输出
curl_setopt ($conn[$key]['curl'], CURLOPT_TIMEOUT, 1); //cURL允许执行的最长秒数
curl_setopt($conn[$key]['curl'], CURLOPT_PROXY, $value['ip']); //使用代理ip
curl_setopt($conn[$key]['curl'], CURLOPT_PROXYPORT, $value['port']); //代理ip的端口
curl_setopt($conn[$key]['curl'], CURLOPT_HTTPHEADER, $header); //设置头部信息
curl_setopt($conn[$key]['curl'], CURLOPT_PROXYUSERPWD, $value['proxy_user'].':'.$value['proxy_password']); //账号密码
curl_setopt($conn[$key]['curl'], CURLOPT_URL, $url); //需要获取的URL地址
curl_setopt($conn[$key]['curl'], CURLOPT_HEADER, 0);
curl_setopt($conn[$key]['curl'], CURLOPT_RETURNTRANSFER, 1);; //不直接输出到浏览器,而是返回字符串
curl_multi_add_handle($mh, $conn[$key]['curl']); //增加 ch 句柄到批处理会话mh
}
$active = null; //连接数
//防卡死写法:执行批处理句柄
do {
$mrc = curl_multi_exec($mh, $active);
//这个循环的目的是尽可能地读写,直到无法继续读写为止
//返回 CURLM_CALL_MULTI_PERFORM 表示还能继续向网络读写
} while($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($conn as $k => $ch) {
$result = curl_multi_getcontent($ch['curl']); //返回获取的输出的文本流
$getInfo = curl_getinfo($ch['curl']);
curl_multi_remove_handle($mh,$ch['curl']); //从给定的批处理句柄mh中移除ch句柄
curl_close($conn[$k]['curl']); //关闭cURL 会话并且释放所有资源
//返回的文本不是string0就说明连上
if (empty($result)) {
PurchaseProxyModel::updateInfo(['status'=>PurchaseProxyModel::IP_STATUS_ABNORMAL],['id'=>$ch['id']]);
}else{
$ipData = json_decode($result,true);
if (empty($ipData['data']['ip_data']['country'])){
PurchaseProxyModel::updateInfo(['status'=>PurchaseProxyModel::IP_STATUS_ABNORMAL],['id'=>$ch['id']]);
continue;
}
PurchaseProxyModel::updateInfo([
'status' => PurchaseProxyModel::IP_STATUS_NORMAL,
'country' => $ipData['data']['ip_data']['country'] ? $ipData['data']['ip_data']['country'] : '',
'region' => $ipData['data']['ip_data']['region'] ? $ipData['data']['ip_data']['region'] : '',
'city' => $ipData['data']['ip_data']['city'] ? $ipData['data']['ip_data']['city'] : '',
'ping' => $getInfo['total_time'],
'ext' => $result,
'update_time' => time(),
],['id'=>$ch['id']]);
}
}
curl_multi_close($mh); //关闭一组cURL句柄
}
有什么不足望各位补充