PHP爬虫 -- 015 应对反爬虫

什么是反爬虫?

  • 人家的服务器, 是给用户服务的, 而爬虫会占用服务器资源
  • 服务器能够获取向服务器发送请求的IP
  • 若是某个IP, 短期高频访问, 服务器就会禁掉该IP

爬虫伦理

  • 一般状况下,服务器不太会在乎小爬虫,
  • 可是,服务器会拒绝频率很高的大型爬虫和恶意爬虫,由于这会给服务器带来极大的压力或伤害
  • 服务器在一般状况下,对搜索引擎是欢迎的态度(谷歌和百度的核心技术之一就是爬虫)。
  • 固然,这是有条件的,而这些条件会写在Robots协议。
  • Robots协议是互联网爬虫的一项公认的道德规范,
  • 全称是“网络爬虫排除标准”(Robots exclusion protocol),
  • 这个协议用来告诉爬虫,哪些页面是能够抓取的,哪些不能够。
  • 如何查看网站的robots协议呢,很简单,在网站的域名后加上/robots.txt就能够了。
  • 淘宝的robots协议 ( www.taobao.com/robots.txt)。
  • 在截取的部分,能够看到淘宝对百度和谷歌这两个爬虫的访问规定,以及对其它爬虫的规定。
User-agent:  Baiduspider #百度爬虫
Allow:  /article #容许访问 /article.htm
Allow:  /oshtml #容许访问 /oshtml.htm
Allow:  /ershou #容许访问 /ershou.htm
Allow: /$ #容许访问根目录,即淘宝主页
Disallow:  /product/ #禁止访问/product/
Disallow:  / #禁止访问除 Allow 规定页面以外的其余全部页面
​
User-Agent:  Googlebot #谷歌爬虫
Allow:  /article
Allow:  /oshtml
Allow:  /product #容许访问/product/
Allow:  /spu
Allow:  /dianpu
Allow:  /oversea
Allow:  /list
Allow:  /ershou
Allow: /$
Disallow:  / #禁止访问除 Allow 规定页面以外的其余全部页面
​
…… # 文件太长,省略了对其它爬虫的规定,想看全文的话,点击上面的连接
​
User-Agent:  * #其余爬虫
Disallow:  / #禁止访问全部页面
复制代码
  • 网站的服务器被爬虫爬得多了,也会受到较大的压力,所以,各大网站也会作一些反爬虫的措施。
  • 不过呢,有反爬虫,也就有相应的反反爬虫
  • 限制好爬虫的速度,对提供数据的服务器心存感谢,避免给它形成太大压力,维持良好的互联网秩序

若是反反爬虫?

  • 有反爬虫, 就有反反爬虫
  • 既然是高频访问会受限制, 那么解决方案有两个
  • 第一, 设置sleep, 下降同一IP的访问频率
  • 第二, 使用IP代理池, 每次都用不一样的IP

选择一个靠谱的IP代理商

PHP使用阿布云建立IP代理池

须要打开curl扩展

测试是否成功, 示例代码, 输出当前IP

<?php
    // 要访问的目标页面
    $targetUrl = "http://test.abuyun.com";

    // 代理服务器
    $proxyServer = "http://http-dyn.abuyun.com:9020";

    // 隧道身份信息
    $proxyUser   = "H19D75L76VK89Q8D";
    $proxyPass   = "8C17B0A80F475BD8";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $targetUrl);

    curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    // 设置代理服务器
    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
    curl_setopt($ch, CURLOPT_PROXY, $proxyServer);

    // 设置隧道验证信息
    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$proxyUser}:{$proxyPass}");

    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727;)");

    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);

    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    //$info = curl_getinfo($ch);

    curl_close($ch);

    var_dump($result);   
复制代码

和querylist结合, 每次请求获取请求IP

<?php
require 'vendor/autoload.php';
use QL\QueryList;
// 生成一个querylist对象
$ql = new QueryList();

$data = $ql->html(get_html_source('http://ip.tool.chinaz.com/'))->rules([
    'ip'=>['#rightinfo > dl > dd.fz24','text'],
    'address'=>['#rightinfo > dl > dd:nth-child(4)','text']
])->queryData();

var_dump($data);

function get_html_source($url) {
    $result = false;
    // 加while循环, 防止有些ip不能用, 取不到html代码
    // 若是取不到代码, $result是false, 继续执行while里面的代码, 换一个新的ip再试一次
    while (!$result) {
        // 要访问的目标页面
        $targetUrl = $url;
        // 代理服务器
        $proxyServer = "http://http-dyn.abuyun.com:9020";
        // 隧道身份信息
        $proxyUser = "H19D75L76VK89Q8D";
        $proxyPass = "8C17B0A80F475BD8";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $targetUrl);
        curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        // 设置代理服务器
        curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
        curl_setopt($ch, CURLOPT_PROXY, $proxyServer);
        // 设置隧道验证信息
        curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
        curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$proxyUser}:{$proxyPass}");
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727;)");
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        // curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        // 若是请求失败, 不该该当即开始换ip, 稍等一下子, 由于每秒的请求数有限制
        if(!$result){
            sleep(2);
        }
        //$info = curl_getinfo($ch);
        curl_close($ch);
    }
    return $result;
}
复制代码

舒适提示: 动态版的一个问题...

  • 动态版是每次请求都会换一个ip
  • 可是并非每一个IP都能用
  • 因此须要写一个循环, 若是获取不到数据, 就一直换着ip访问
  • 可是还有一个细节, 若是你是每秒只能有一次请求, 那么频繁的换ip就会一直false, 死循环
  • 还须要加上sleep(2)
  • 因此仔细观察上一个代码, 咱们的函数里有while(), 也有sleep

做业, 使用ip代理, 修改以前的电子书城代码

下一节

相关文章
相关标签/搜索