tp5.1+swoole+QueryList实现异步爬取数据功能

先讲下为什么要使用swoole异步任务,在项目中我们经常会遇到执行时间比较久的请求(上传,爬取等),让用户一直等待不是好的体验,所以我们使用swoole异步请求,先返回‘执行中’,等异步任务执行完毕再修改状态。
接下来我们来实现swoole在thinkphp 里的集成:
1.安装swoole
推荐使用官网提供的安装方式 安装swoole扩展
2.安装QueryList

composer require jaeger/querylist

文档地址 querylist
3.在Tp5里自定义一个命令行类
在application下建立一个console文件夹用来存放自定义命令文件,然后在该文件夹下新建Crawler.php文件,编辑application目录下的command.php文件
添加如下代码
return [ 'app\console\Crawler', ];

tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

编写 Crawler.php
setName('crawler:start')->setDescription('Start Crawler Server!'); }protected function execute(Input $input, Output $output) { $serv = new \swoole_server('0.0.0.0',9502); //9502为swoole监听端口,可以自行设置 $serv->set(array('task_worker_num' => 4)); //异步进程数量 根据实际情况进行配置,参照官网提供的方案 $serv->on('connect', function ($serv, $fd){}); $serv->on('receive', function($serv, $fd, $from_id,$data) { //投递异步任务 $data为接口传递的参数,接收参数做一些处理之后交给task echo'收到任务'; $serv->task($data); }); $serv->on('task', function ($serv, $task_id, $from_id, $data) { //接收receive传递的任务,进行执行 //本例中实现的是爬取京东商品任务 ,大家可以根据自身情况修改 echo'执行任务'; $this->crawler($data); }); $serv->on('finish', function ($serv, $task_id, $data) {}); $serv->start(); }/** * 采集商品数据 * @param $activity_id * @return bool */ private function crawler($activity_id) { //假设 $number 为京东活动id $number = 123456; $data = https://www.it610.com/article/[]; $limit = 1; //起始 $ql = QueryList::getInstance(); for (; ; ) { $offset = $limit * 30 + 1; //偏移量 //这个url是通过分析京东加载商品接口提取出来的,修改这几个参数就能模拟分页爬取到京东全部活动的商品 $url ='https://search.jd.com/s_new.php?activity_id=' . $number . '&vt=2&scc=1&page=' . $limit . '&s=' . $offset . '&scrolling=y&tpl=1_M'; //这里使用了代理,因为循环爬取的原因被京东检测到了封了ip,所以使用动态代理爬取,代理的使用根据代理服务商提供的api每个都不同,在本文不详细介绍 $crawler = $this->immediate($url); if ($crawler) { $query = []; //phpquery 的核心思想就是使用php像js一样通过dom操作页面 //下面代码的意思是 获取页面的html 找到class为gl-item的子元素,并遍历(就是遍历京东页面展示的商品div) $ql->html($crawler)->find('.gl-item')->children()->map(function ($item) use (&$query, $number, $activity_id) { $tags = ''; //找到标签展示规律并提取 $item->find('.p-icons')->children()->map(function ($child_tag) use (&$tags) { $tags .= $child_tag->html() . ','; }); //找到商品价格展示规律并提取 $price = $item->find('.p-price>strong>i')->html(); if (!$price) { $price = $item->find('.p-price>strong')->attrs('data-price')[0] ?? 0; } if ($price && $price > 0) { //这里通过节点找到需要的数据和数据表对应存到mysql $query[] = [ 'activity_id' => $activity_id, 'activity_number' => $number, 'goods_number' => $item->find('.p-operate>a')->attrs('data-sku')[0] ?? '', 'title' => $item->find('.p-name-type-2>a>em')->text(), 'image' => 'http:' . $item->find('.p-img>a>img')->attrs('source-data-lazy-img')[0] ?? '', 'price' => $price, 'tags' => rtrim($tags, ','), 'shop_name' => $item->find('.p-shop>span>a')->html(), 'shop_number' => $item->find('.p-img>div')->attrs('data-venid')[0] ?? '', ]; } }); if (count($query)) { foreach ($query as $k => $v) { $data[] = $v; } $limit++; } else { break; } } //尽量让爬虫等待一秒再执行,避免内存溢出 sleep(1); }; //爬虫功能结束之后及时释放内存 $ql->destruct(); //....... //接下来把数据存进mysql中就大功告成啦 }}

4.写一个接口去调用异步任务
public function swoole_task(Request $request){ $type = $request->param('type'); $client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); $ret = $client->connect("服务器ip", 9502); if(empty($ret)){ return 'FAIL'; } else { $client->send($type); //提交任务到crawler.php 处理 我是传参$type实现不同的异步任务调用 return 'SUCCESS'; } }

5.进入tp5 项目根目录执行命令
php think crawler:start//通常用于调试

让swoole监听命令以守护进程方式运行(服务器)
php think crawler:start &

6.执行上面写好的调用接口swoole_task 可以在你想用的任何地方调用
7.效果
tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

本文提供的方法仅供参考,实例并不能直接执行,需要大家理解工作原理后结合自身项目进行使用
【tp5.1+swoole+QueryList实现异步爬取数据功能】8.推荐一下本文使用技术在项目中的应用,微信搜索‘东东小卖部’,每天会爬取最新的京东满减打折活动,
通过算法凑成满减之后将商品组合返回给用户,亲身体验过非常不错,这个项目对于喜欢网购的朋友们来说绝对会带给你非常棒的体验。
大家要是觉得本文有帮助的话,帮忙关注下公众号分享给身边的人,不许白嫖哦,十分感谢
tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

tp5.1+swoole+QueryList实现异步爬取数据功能
文章图片

    推荐阅读