一步步編寫本身的PHP爬取代理IP項目(三)

上一章節咱們講完了自動加載,如今咱們正式進入爬蟲核心代碼的編寫中,首先咱們須要先看看整個目錄php

config.php        這個是咱們的配置文件加載文件html

ProxyPool.php  這個是爬蟲的核心處理文件redis

Queue.php       這個是隊列操做的處理文件數組

Requests.php   這個是發起請求的處理文件ide

而後咱們在回憶一下入口文件的代碼測試

<?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方法會爬取兩個網站的IPui

//獲取各大網站代理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;
}

咱們先來來看看西刺代理的爬取this

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而且校驗可用性了。

相關文章
相關標籤/搜索