上一章節咱們講完了自動加載,如今咱們正式進入爬蟲核心代碼的編寫中,首先咱們須要先看看整個目錄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而且校驗可用性了。