使用easyswoole开发多进程多协程队列式爬虫
爬虫步骤
我们先说一下一个完整的爬虫步骤。
爬虫步骤分为2个阶段:
1:根据初始页面,获取更多的待爬取页面
2:根据页面,获取到自己想要的东西
更多待爬取页面获取
当我们填入一个初始页面时,我们需要通过某一个特定的逻辑,进行获取更多的页面
例如:
爬取百度页面,我们可以通过页码按钮,获取更多页面的html源码:
爬取知乎用户,我们可以通过该用户的关注者,和粉丝爬取更多用户界面:
结果获取
获取到了页面html代码之后,我们就可以根据相应的规则,获取到自己想要的东西了。
这里我推荐http://www.querylist.cc/ 可使用jq的语法选择html页面的元素,非常好用
使用消息队列
我们现在已经知道了整个爬虫的步骤了,下一步是如何运行这个代码。
在上一步我们可以看出,一个页面,可能有多个待爬取页面,如果我们每次都是取一个页面,然后分析结果,然后再取一个页面,分析结果
这样会造成代码逻辑的难以掌控。
例如:
1:分析页面1,假设页面1有5个待爬取页面链接
2:分析页面1结果,存储
3:分析页面1的第一个结果待爬取页面2,页面2有5个待爬取页面链接
4:分析页面2的结果,存储
5:分析页面1的第二个待爬取页面3,页面3有5个待爬取页面链接。。。。。。
。。。。
这样会造成代码的难以控制,不好维护待爬取页面,我们可以使用队列的形式进行处理
1:初始页面存入分析队列
2:分析初始页面1,获取5个待爬取页面链接,存入分析队列
3:分析页面1的结果,存入结果队列
4:分析队列出列页面2,获取5个待爬取页面链接,存入分析队列
5:分析页面2的结果,存入结果队列
使用队列的情况下,逻辑将会非常的清晰,只需要每次将分析的页面出入队列,然后取出继续分析即可
同样,结果队列只需要新增一个结果消费进程,进行处理结果数据即可
实战
本人已经写好了基础的爬虫框架,基于easyswoole,使用redis队列进行消费。
github地址:https://github.com/tioncico/ESSpider
首先进行composer安装
composer up
复制
复制produce.php命名为dev.php,增加redis配置:
<?php
/**
* Created by PhpStorm.
* User: yf
* Date: 2019-01-01
* Time: 20:06
*/
return [
'SERVER_NAME' => "EasySwoole",
'MAIN_SERVER' => [
'LISTEN_ADDRESS' => '0.0.0.0',
'PORT' => 9501,
'SERVER_TYPE' => EASYSWOOLE_WEB_SERVER, //可选为 EASYSWOOLE_SERVER EASYSWOOLE_WEB_SERVER EASYSWOOLE_WEB_SOCKET_SERVER,EASYSWOOLE_REDIS_SERVER
'SOCK_TYPE' => SWOOLE_TCP,
'RUN_MODEL' => SWOOLE_PROCESS,
'SETTING' => [
'worker_num' => 8,
'task_worker_num' => 8,
'reload_async' => true,
'task_enable_coroutine' => true,
'max_wait_time' => 3
],
],
'TEMP_DIR' => null,
'LOG_DIR' => null,
/*################ REDIS CONFIG ##################*/
'REDIS' => [
'host' => '127.0.0.1',
'port' => '6379',
'auth' => '',
'serialize'=>true
],
];
复制
本身自带了某网站的爬取逻辑,直接运行即可看到:
php easyswoole start
复制
现在我们说下如何爬取其他网站的步骤
爬取http://moe.005.tv/moeimg/动漫图片网站
清空/App/Spider/Event.php的方法逻辑
<?php
namespace App\Spider;
use EasySwoole\Utility\File;
use QL\QueryList;
/**
* Created by PhpStorm.
* User: tioncico
* Date: 19-6-16
* Time: 上午9:53
*/
class Event
{
static function consume($data, $html)
{
}
static function produce($data, $html)
{
}
}
复制
编写生产代码(获取更多待爬取页面逻辑):
首先,我们要确定,我们的初始页面是http://moe.005.tv/moeimg/,然后我们可以根据下一页按钮获取更多的页面
static function produce($data, $html)
{
//获得一个queryList对象,并且防止报错
libxml_use_internal_errors(true);
@$ql = QueryList::html($html);
//查询下一页链接,用于继续爬取数据
$nextLink = $ql->find('.pagelist .n')->attr('href');
RedisLogic::addProduce($nextLink);
//查询所有需要爬取的数据,用于爬取里面的图片
$imgConsumeList = $ql->find('.zhuti_w_list li a')->attrs('href')->all();
foreach ($imgConsumeList as $value) {
RedisLogic::addConsume([
'type' => 1,//消费标识
'url' => $value,
]);
}
return true;
}
复制
编写消费代码
现在我们需要点击一个图片进入,可以发现很多图片,例如:http://moe.005.tv/78243.html
现在,我们编写消费代码:
static function consume($data, $html)
{
//获得一个queryList对象,并且防止报错
libxml_use_internal_errors(true);
if ($data['type'] == 1) {
//消费类型为1,则代表还不是下载图片,需要进行二次消费
//查询下一页链接,用于继续爬取数据
@$ql = QueryList::html($html);
$nextLink = $ql->find('.pagelist .n')->attr('href');
$nextLink = HttpClientLogic::getTrueUrl($data['url'],$nextLink);
if ($nextLink) {
RedisLogic::addConsume([
'type' => 1,//消费标识
'url' => $nextLink,
]);
}
$imgList = $ql->find('.content_nr img')->attrs('src')->all();
// var_dump($img);
foreach ($imgList as $img) {
RedisLogic::addConsume([
'type' => 2,//消费标识
'url' => $img,
]);
}
} elseif ($data['type'] == 2) {
$urlInfo = parse_url($data['url']);
$filePath = EASYSWOOLE_ROOT . '/Temp/' . $urlInfo['host'] . $urlInfo['path'];
// var_dump($filePath);
File::createFile($filePath, $html);
// var_dump($data['url']);
}
}
复制
初始页面链接可通过协程调用进行增加:
<?php
/**
* Created by PhpStorm.
* User: tioncico
* Date: 19-6-16
* Time: 下午5:35
*/
include "./vendor/autoload.php";
\EasySwoole\EasySwoole\Core::getInstance()->initialize();
go(function (){
\App\Spider\RedisLogic::clearConsumeMap();//清除消费map
\App\Spider\RedisLogic::clearProduceMap();//清除生产map
\App\Spider\RedisLogic::clearConsumeList();//清除消费队列
\App\Spider\RedisLogic::clearProduceList();//清除生产队列
//新增默认队列
\App\Spider\RedisLogic::addProduce('http://moe.005.tv/moeimg/');
});
复制
直接运行
php easyswoole start
复制
即可实现爬虫爬取页面
爬虫框架补充
github地址:https://github.com/tioncico/ESSpider
1:可通过EasySwooleEvent.php 文件,进行配置爬取的协程数,不建议太大
2:本爬虫没有做ip池,需要的可自行实现
3:本爬虫框架只适用于学习,请不要用于违法用途
- 点赞
- 收藏
- 关注作者
评论(0)