在采集大批量数据时常常会触发对方服务器的“自我保护”,请求过于频繁就限制访问。这时需要停留很长一段时间(十几分钟到几十分钟不等)才能恢复访问,这样采集数据的速度就受到非常大的限制。

同样经常会碰到需要自动换IP的需求,比方模拟点击投票,数据采集被封IP,Alexa作弊等等,也就是需要经常换IP的,我们都可以通过PHP控制路由器来换IP,这样就不需要用按键精灵搞得那么累了。呵呵。有的路由器是提供通过WEB方式管理路由器设置的,中间有一个功能就是断线和重新连接,可以利用这个功能。

解决方法有两个:

1 通过图片识别绕过验证码机制,告诉服务器:我不是蜘蛛,我是人。不信你瞧,我能看懂验证码。

2 更换IP,告诉服务器:我不是张三,我是李四。不信你瞧,我的IP地址和张三的不一样。

第一个方法难度稍高一点而且不靠谱,等哪天对方服务器升级了验证码了,这边也得跟进,麻烦多;而ISP(电信、联通、移动)那儿有很多IP,每次联网都会分配一个新的IP,因此方法二比较好。

以我的TP-LINK路由器为例,找到“网络参数”>“WAN口设置”,可以看到“自动连接”设置和“断线”按钮。每次点击“断线”按钮,就向ISP重新拨号,此时就换了一个IP。但大批量数据的采集需要的时间比较长,不可能总有人在旁边守着,最好能在PHP代码中,一旦发现被限制了就重启一次。

打开chrome浏览器的调试模式,然后点击“断线”按钮,看“Network”网络请求,可以看到实际执行的地址是:“http://192.168.1.1/userRpm/StatusRpm.htm?Disconnect=%B6%CF%20%CF%DF&wan=1”

然后模拟请求这个地址,经测试确实可以更换IP地址。接下来的就简单了:就用PHP使用Curl组件来实现这个请求的过程,我封装了一个函数resetip,具体代码如下:

ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
echo "

IP:".$_SERVER['REMOTE_ADDR']."

"; resetRouter(); function resetRouter() { $username = 'admin'; $password = '5601928'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://192.168.1.1/userRpm/StatusRpm.htm?Disconnect=%B6%CF%20%CF%DF&wan=1'); curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); print_r($ch); curl_exec($ch); curl_close($ch); }

方法二:

function router($target=´´){
$server  = '192.168.1.1';            // IP address
$host    = '192.168.1.1';            // Domain name
$port    = '80';
$referer = 'http://'.$host.$target;    // Referer
$username = 'admin';//#ADSL的路由的用户名
$password = '5601928';//#ADSL的路由的管理密码
$authorization = base64_encode($username.":".$password);
$File = fsockopen($server, $port, $errno, $errstr, 30);
if ($File) {        
$out = "GET $target HTTP/1.1rn";
$out .= "Host: $hostrn";
$out .= "Referer: $refererrn";
$out .= "Authorization: Basic $authorizationrn";
$out .= "Connection: Closernrn";
fputs($File, $out);
$makeFile = $buffer = "";
while ($buffer = fread($File,4096)){
$makeFile = $makeFile.$buffer;
}
fclose($File);
}
}
//调用方法
router("/userRpm/StatusRpm.htm?Disconnect=%B6%CF%20%CF%DF&wan=1");