请先关注 [低调大师] 公众号 优秀的自媒体个人博客,低调大师,许军

低调大师

您现在的位置是:首页>文章详情

文章详情

一步步编写自己的PHP爬取代理IP项目(三)

2018-09-29 41热度

上一章节我们讲完了自动加载,现在我们正式进入爬虫核心代码的编写中,首先我们需要先看看整个目录

config.php        这个是我们的配置文件加载文件

ProxyPool.php  这个是爬虫的核心处理文件

Queue.php       这个是队列操作的处理文件

Requests.php   这个是发起请求的处理文件

然后我们在回忆一下入口文件的代码

<?php require_once __DIR__ . '/autoloader.php'; require_once __DIR__ . '/vendor/autoload.php'; use ProxyPool\core\ProxyPool; $proxy = new ProxyPool(); $proxy->run();

通过这里可以看到我们使用了core里面ProxyPool的run方法,先来看看ProxyPool的内容吧

<?php use ProxyPool\core\Requests;  //HTTP请求文件 use ProxyPool\core\Queue;   //队列操作文件 class ProxyPool {     private $redis;     private $httpClient;         private $queueObj;              function __construct()     {         $redis = new \Redis();         $redis->connect(config("database.redis_host"), config("database.redis_port"));         $this->redis = $redis;$this->httpClient = new Requests(['timeout' => 10]);         $this->queueObj = new Queue();     }              public function run()     {          echo "start to spider ip...." . PHP_EOL;         $ip_arr = $this->get_ip(); //获取IP的具体方法         echo "select IP num: " . count($ip_arr) . PHP_EOL;                      echo "start to check ip...." . PHP_EOL;         $this->check_ip($ip_arr);  //验证IP可用性的方法         $ip_pool = $this->redis->smembers('ip_pool');  //读取redis中的ip         echo "end check ip...." . PHP_EOL;                           print_r($ip_pool);  //输出ip数组         die;     } }

其中get_ip方法会爬取两个网站的IP

//获取各大网站代理IP private function get_ip() {     $ip_arr = [];     $ip_arr = $this->get_xici_ip($ip_arr);      //西刺代理     $ip_arr = $this->get_kuaidaili_ip($ip_arr); //快代理     return $ip_arr; }

我们先来来看看西刺代理的爬取

private function get_xici_ip($ip_arr) {     for ($i = 1; $i <= config('spider.page_num'); $i++)      {         list($infoRes, $msg) = $this->httpClient ->request('GET','http://www.xicidaili.com/nn/'.$i,[]);         if (!$infoRes)          {             print_r($msg);  //输出错误信息             exit();         }         $infoContent = $infoRes->getBody();         $this->convert_encoding($infoContent);         preg_match_all('/<tr.*>[\s\S]*?<td class="country">[\s\S]*?<\/td>[\s\S]*?<td>(.*?)<\/td>[\s\S]*?<td>(.*?)<\/td>/', $infoContent, $match);                  $host_arr = $match[1];         $port_arr = $match[2];         foreach ($host_arr as $key => $value)          {             $ip_arr[] = $host_arr[$key].":".$port_arr[$key];         }     }     return $ip_arr; }

这个方法里面,我们首先使用 config('spider.page_num') 这个方法读取了配置文件里面定义的爬取页数,我这里定义的是3页,然后我们打开西刺代理的网站,会发现域名是

http://www.xicidaili.com/nn/XX      这个XX是第几页,第一页就是1,第二页就是2,以此类推

所以我们在代码里面循环访问了三次网站,获取到网页的返回值,然后用正则匹配html去获取里面的地址和端口号(具体html元素可以在网站右键点击审查元素查看)

preg_match_all('/<tr.*>[\s\S]*?<td class="country">[\s\S]*?<\/td>[\s\S]*?<td>(.*?)<\/td>[\s\S]*?<td>(.*?)<\/td>/', $infoContent, $match);

然后经过一些处理,将获取到的IP返回。这就是get_xici_ip这个方法做的事情,它就是负责爬取IP。

然后我们来看看

//检测IP可用性 private function check_ip($ip_arr) {     $this->queueObj = $this->queueObj->arr2queue($ip_arr);     $queue = $this->queueObj->getQueue();     foreach ($queue as $key => $value)      {         //用百度网和腾讯网测试IP地址的可用性         for ($i=0; $i < config('spider.examine_round'); $i++)          {             $response = $this->httpClient->test_request('GET','https://www.baidu.com', ['proxy' => 'https://'.$value]);             if (!$response)              {                 $response = $this->httpClient->test_request('GET','http://www.qq.com', ['proxy' => 'http://'.$value]);                 if ($response && $response->getStatusCode() == 200)                  {                     break;                 }             }             else if($response->getStatusCode() == 200)             {                 break;             }         }         //将结果存入redis            if ($response && $response->getStatusCode() == 200)          {             $this->set_ip2redis($value);            }             else{             echo $value . " error...  ". PHP_EOL;             }     } }

这里我们使用了https的百度和http的qq来检测,如果成功访问就把这个IP插入redis中。

这样我们就能做到爬取IP并且校验可用性了。

收藏 (0)

相关文章

    文章评论

    共有0条评论来说两句吧...