一步步编写自己的PHP爬取代理IP项目(三)
上一章节我们讲完了自动加载,现在我们正式进入爬虫核心代码的编写中,首先我们需要先看看整个目录
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并且校验可用性了。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一个等效ping的EOS智能合约
这篇文章是为帮助EOS智能合约开发人员从初级到生产而发布的一系列帖子中的第一篇。有关本教程的完整代码,可以访问github存储库。 随着对EOS的所有兴奋而来的,对于大多数希望参与其中的开发人员仍然充满挑战的领域是开始使用智能合约。新开发人员通常需要克服两个障碍:获取工具和设置,并了解如何编写智能合约本身。 EOS智能合约是用C++编写的,并编译成Web Assembly。Dan Larimer选择C++来利用其类型和模板系统,这使得更安全的合约,并补充说,因为智能合约的运行时间很短,大多数内存问题都会消失。 配置 使用EOS的部分挑战是设置本地区块链。幸运的是,EOS为设置本地EOS环境提供了一些基础。对于本指南,我们将使用EOSIO Dawn 3.0。 该指南的摘要可以压缩为几个关键命令: $ git clone https://github.com/EOSIO/eos --recursive $ cd eos $ ./eosio_build.sh $ cd build && make install $ cd programs/nodeos $ ./nodeos ...
- 下一篇
使用KETTLE从mysql同步增量数据到oracle
初次使用ETL工具抽取并同步数据,搜索之后决定使用kettle,使用后感觉很方便。 本次是基于一个很小的需求,需要把老系统的mysql数据在一段新老系统共存时期内产生的数据实时传输到新系统oracle中,因为实时性要求不算高,所以我没有做触发器这些对接,只单纯的使用kettle做了一个抽取转换传输,定时执行。下面记录一下本次的操作,并写一下自己遇到的坑。 老系统mysql表很大,本次基于一个小的需求,只需要抽取其中的两个字段同步传输。两个字段均是varchar类型,相对比较简单。我尝试过传输mysql的int(11)和oracle的number,发现需要把oracle的number改为number(10),二者才能对的上号。 工具:kettle的pdi-ce-7.0.0.0-25,可去官网下载;mysql,oracle 思路:先将mysql老数据和oracle同步后的数据都查出来,转换字段统一整合交给kettle处理,kettle会依据关键字段和时间戳来判断来自mysql的数据对oracle来讲,是新增、更新、删除还是无任何操作,并分别标注标识位,后续一步步判断标识位,最后转换成ora...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题