先講下爲何要使用swoole異步任務,在項目中咱們常常會遇到執行時間比較久的請求(上傳,爬取等),讓用戶一直等待不是好的體驗,因此咱們使用swoole異步請求,先返回‘執行中’,等異步任務執行完畢再修改狀態。 接下來咱們來實現swoole在thinkphp 裏的集成:php
1.安裝swoole 推薦使用官網提供的安裝方式 安裝swoole擴展html
2.安裝QueryListmysql
composer require jaeger/querylist
複製代碼
文檔地址 querylistgit
3.在Tp5裏自定義一個命令行類 在application下創建一個console文件夾用來存放自定義命令文件,而後在該文件夾下新建Crawler.php文件,編輯application目錄下的command.php文件 添加以下代碼github
return [
'app\console\Crawler',
];
複製代碼
編寫 Crawler.php
<?php
namespace app\Console;
use QL\QueryList;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class Ceshi extends Command{
protected $server;
protected function configure()
{
//參考tp5自定義命令行手冊
$this->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 = [];
$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 項目根目錄執行命令sql
php think crawler:start//一般用於調試
複製代碼
讓swoole監聽命令以守護進程方式運行(服務器)thinkphp
php think crawler:start &
複製代碼
6.執行上面寫好的調用接口swoole_task 能夠在你想用的任何地方調用api
7.效果 bash
本文提供的方法僅供參考,實例並不能直接執行,須要你們理解工做原理後結合自身項目進行使用
8.推薦一下本文使用技術在項目中的應用,微信搜索‘東東小賣部’,天天會爬取最新的京東滿減打折活動, 經過算法湊成滿減以後將商品組合返回給用戶,親身體驗過很是不錯,這個項目對於喜歡網購的朋友們來講絕對會帶給你很是棒的體驗。 你們要是以爲本文有幫助的話,幫忙關注下公衆號分享給身邊的人,不準白嫖哦,十分感謝