【PhpSelenium】3.定時(shí)爬蟲+多任務(wù)爬蟲+代理池

僅用于交流和學(xué)習(xí),禁止利用本資源從事任何違反本國(地區(qū))法律法規(guī)的活動(dòng)策严,一切遵守《網(wǎng)絡(luò)安全法》

Tips:只是提供一個(gè)思路庇麦,實(shí)際項(xiàng)目中還需維護(hù)代理池可用性等細(xì)節(jié)部分

實(shí)戰(zhàn)步驟

  1. 框架及核心庫部署
  2. 定時(shí)更新代理池進(jìn)程
  3. 定時(shí)爬取列表頁進(jìn)程
  4. 主進(jìn)程定時(shí)從Redis中讀取列表頁任務(wù),有則將每一項(xiàng)丟給異步任務(wù)執(zhí)行

環(huán)境

  • CentOS 7.2
  • PHP7.2
  • Swoole 4.3.5
  • Google Chrome 78.0.3904.108
  • ChromeDriver 78.0.3904.105

Composer

  • facebook/webdriver=1.7
  • easyswoole/easyswoole=3.1.18
  • easyswoole/curl=1.0.1

框架及核心庫部署

1晒衩、安裝EasySwoole 3.1.18版本

[root@ar414.com phpseleniumdemo] composer require easyswoole/easyswoole=3.1.18
[root@ar414.com phpseleniumdemo] php vendor/easyswoole/easyswoole/bin/easyswoole install
______                          _____                              _
 |  ____|                        / ____|                            | |
| |__      __ _   ___   _   _  | (___   __      __   ___     ___   | |   ___
 |  __|    / _` | / __| | | | |  \___ \  \ \ /\ / /  / _ \   / _ \  | |  / _ \
| |____  | (_| | \__ \ | |_| |  ____) |  \ V  V /  | (_) | | (_) | | | |  __/
|______|  \__,_| |___/  \__, | |_____/    \_/\_/    \___/   \___/  |_|  \___|
                          __/ |
                        |___/
install success,enjoy!

2.安裝核心庫facebook/webdriver嗤瞎、easyswoole/curl

[root@ar414.com phpseleniumdemo]# composer require facebook/webdriver=1.7  
[root@ar414.com phpseleniumdemo]# composer require easyswoole/curl=1.0.1  

3、確認(rèn)運(yùn)行沒報(bào)錯(cuò)

[root@ar414.com phpseleniumdemo]# php easyswoole  start
|  ____|                        / ____|                            | |
 | |__      __ _   ___   _   _  | (___   __      __   ___     ___   | |   ___
>|  __|    / _` | / __| | | | |  \___ \  \ \ /\ / /  / _ \   / _ \  | |  / _ \
>| |____  | (_| | \__ \ | |_| |  ____) |  \ V  V /  | (_) | | (_) | | | |  __/
>|______|  \__,_| |___/  \__, | |_____/    \_/\_/    \___/   \___/  |_|  \___|
>                         __/ |
>                        |___/
main server                   SWOOLE_WEB
listen address                0.0.0.0
listen port                   9501
sub server1                   CONSOLE => SWOOLE_TCP@127.0.0.1:9500
....

定時(shí)更新代理池進(jìn)程

Tips:代理資源請自行解決听系,這里只提供例子贝奇,實(shí)際是用不了的

1、 創(chuàng)建項(xiàng)目主目錄

[root@ar414.com phpseleniumdemo]# mkdir App  
#composer 指定App作用域  
[root@ar414.com phpseleniumdemo]# cat composer.json  
{  
    "autoload": { 
        "psr-4": { "App\\": "App/" 
        } 
    },
    "require": { 
        "easyswoole/easyswoole": "3.1.18",    
        "facebook/webdriver": "^1.7",
        "easyswoole/curl": "1.0.1" 
    }
}
#更新composer autoload
[root@ar414.com phpseleniumdemo]# composer dump-autoload

2靠胜、創(chuàng)建進(jìn)程目錄(將代理池更新作為一個(gè)子進(jìn)程隨項(xiàng)目啟動(dòng)運(yùn)行)

[root@ar414.com phpseleniumdemo]# mkdir App/Process  

3弃秆、代理池定時(shí)爬冉焱铩(使用Redis List類型保證最新代理IP在頭部,爬蟲邏輯每次從頭部獲取菠赚,一個(gè)代理IP只用一次)

Tips:代理資源請自行解決脑豹,這里只提供例子,實(shí)際是用不了的

完整代碼鏈接

<?php
/**
 * Created by PhpStorm.
 * User: ar414.com@gmail.com
 * Date: 2019/12/7
 * Time: 21:00
 */
namespace App\Process;
use App\Lib\Curl;
use App\Lib\Kv;
use EasySwoole\Component\Process\AbstractProcess;
class UpdateProxyPool extends AbstractProcess
{
    //這里的代理IP都只支持socks5協(xié)議
    private $proxyListApi = "http://www.zdopen.com/ShortS5Proxy/GetIP/?api=%s&akey=%s&order=2&type=3";
    const PROXY_KV_KEY = 'spider:proxy:list';
    const TIMER = 15;
    protected function initProxyListApi()
    {
//        $this->proxyListApi = sprintf($this->proxyListApi,$_ENV['PROXY_LIST_API'],$_ENV['PROXY_LIST_KEY']);
        $this->proxyListApi = sprintf($this->proxyListApi,20191231231237085,'72axxxae0fe34');
    }
    public function run($arg)
    {
        $this->initProxyListApi();
        //依賴 composer require easyswoole/curl=1.0.1
        while (true)
        {
            $ret = Curl::get($this->proxyListApi);
            var_dump($ret);
            if($ret) {
                $ret = json_decode($ret,true);
                if($ret['code'] == 10001 && isset($ret['data']['proxy_list']) && !empty($ret['data']['proxy_list']) ) {
                    foreach($ret['data']['proxy_list'] as $proxy) {
                        $proxyItem = $proxy['ip'] . ':'.$proxy['port'];
                        Kv::redis()->lPush(self::PROXY_KV_KEY,$proxyItem);
                    }
                }
            }
            sleep(self::TIMER);
        }
    }
}

4衡查、配置代理池更新進(jìn)程隨項(xiàng)目啟動(dòng)時(shí)啟動(dòng)(完整代碼鏈接

public static function mainServerCreate(EventRegister $register)
{
        //更新代理池進(jìn)程
        ServerManager::getInstance()->getSwooleServer()->addProcess((new \App\Process\UpdateProxyPool('UpdateProxyPool', []))->getProcess());
}

定時(shí)爬取列表頁進(jìn)程

爬取列表頁進(jìn)程(完整代碼鏈接

<?php
/**
 * Created by PhpStorm.
 * User: ar414.com@gmail.com
 * Date: 2019/12/7
 * Time: 22:01
 */

namespace App\Process;

use App\Lib\ChromeDriver;
use App\Lib\Kv;
use EasySwoole\Component\Process\AbstractProcess;
use EasySwoole\EasySwoole\Logger;

class ListSpider extends AbstractProcess
{
    const API = 'https://www.188-sb.com/SportsBook.API/web?lid=1&zid=3&pd=%23AC%23B151%23C1%23D50%23E10%23F163%23&cid=42&ctid=42';

    const LIST_KV_KEY = 'spider:list';
    const TIMER = 20; //20秒執(zhí)行一次

    public function run($arg)
    {
        while (true)
        {
            try
            {
                $driver = (new ChromeDriver(true))->getDriver();
                $driver->get(self::API);
                $listStr = $driver->getPageSource();
                var_dump($listStr);
                file_put_contents("/www/wwwroot/blog/phpseleniumdemo/listStr.html",$listStr);
                preg_match_all("/PD=(.*);/U",$listStr,$list);
                $list = array_unique($list[1]);
                if($list)
                {
                    Kv::redis()->set(self::LIST_KV_KEY,json_encode($list));
                }
                var_dump('done');
                $driver->close();
                $driver->quit();
            }
            catch (\Throwable $throwable)
            {
                $driver->close();
                $driver->quit();
                Logger::getInstance()->log($throwable->getMessage(),'ListSpiderError');
                var_dump($throwable->getMessage());
            }
            sleep(self::TIMER);
        }

    }
}

主進(jìn)程定時(shí)從Redis中讀取列表頁任務(wù)瘩欺,有則將每一項(xiàng)丟給異步任務(wù)執(zhí)行

1、完整代碼鏈接

public static function mainServerCreate(EventRegister $register)
    {
        //更新代理池進(jìn)程
        ServerManager::getInstance()->getSwooleServer()->addProcess((new \App\Process\UpdateProxyPool('UpdateProxyPool', []))->getProcess());
        //列表爬取進(jìn)程
        ServerManager::getInstance()->getSwooleServer()->addProcess((new \App\Process\ListSpider('ListSpider', []))->getProcess());

        $register->set($register::onWorkerStart,function(\swoole_server $server,$workerId){
            if($workerId == 0)
            {
                Timer::getInstance()->loop(30000, function () {
                    $ret = Kv::redis()->get(ListSpider::LIST_KV_KEY);
                    if($ret){
                        $ret = json_decode($ret,true);
                        foreach($ret as $item) {
                            TaskManager::async(function () use($item){
                                (new ItemSpider(true))->run($item);
                                return true;
                            }, function () use($item){
                                var_dump("{$item} Done");
                            });
                        }
                    }
                });
            }
        });

    }

2拌牲、ItemSpider邏輯代碼(完整代碼鏈接

<?php
/**
 * Created by PhpStorm.
 * User: ar414.com@gmail.com
 * Date: 2019/12/7
 * Time: 22:35
 */

namespace App\Spider;


use App\Lib\ChromeDriver;
use EasySwoole\EasySwoole\Logger;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;

class ItemSpider
{
    public function run($itemPath)
    {
        $driver = (new ChromeDriver(true))->getDriver();
        $itemPath = str_replace('#','/',$itemPath);
        $url = "https://www.188-sb.com/#{$itemPath}";
        var_dump($url);
        try
        {
            $driver->get($url);
            $driver->wait(ChromeDriver::WAIT_SECONDS)->until(
                WebDriverExpectedCondition::visibilityOfElementLocated(
                    WebDriverBy::className('gl-MarketGroupButton_Text')
                )
            );
            Logger::getInstance()->console("The title is '" . $driver->getTitle() . "'\n");
            Logger::getInstance()->console("The current URI is '" . $driver->getCurrentURL() . "'\n");
            $body = $driver->getPageSource();
            var_dump($body);
            $driver->close();
            $driver->quit();
            //TODO 清洗數(shù)據(jù) 入庫
        }
        catch (\Throwable $throwable)
        {
            Logger::getInstance()->log($throwable->getMessage(),'Bet365ApiRun');
            $driver->close();
            $driver->quit();
        }
        return;
    }
}

3俱饿、運(yùn)行

[root@ar414.com phpseleniumdemo]# php easyswoole start
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市塌忽,隨后出現(xiàn)的幾起案子拍埠,更是在濱河造成了極大的恐慌,老刑警劉巖土居,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣购,死亡現(xiàn)場離奇詭異,居然都是意外死亡擦耀,警方通過查閱死者的電腦和手機(jī)棉圈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眷蜓,“玉大人分瘾,你說我怎么就攤上這事∮跸担” “怎么了德召?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長汽纤。 經(jīng)常有香客問我上岗,道長,這世上最難降的妖魔是什么冒版? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮逞姿,結(jié)果婚禮上辞嗡,老公的妹妹穿的比我還像新娘。我一直安慰自己滞造,他們只是感情好续室,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谒养,像睡著了一般挺狰。 火紅的嫁衣襯著肌膚如雪明郭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天丰泊,我揣著相機(jī)與錄音薯定,去河邊找鬼。 笑死瞳购,一個(gè)胖子當(dāng)著我的面吹牛话侄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播学赛,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼年堆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盏浇?” 一聲冷哼從身側(cè)響起变丧,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绢掰,沒想到半個(gè)月后痒蓬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曼月,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年谊却,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哑芹。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炎辨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出聪姿,到底是詐尸還是另有隱情碴萧,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布末购,位于F島的核電站破喻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盟榴。R本人自食惡果不足惜曹质,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望擎场。 院中可真熱鬧羽德,春花似錦、人聲如沸迅办。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽站欺。三九已至姨夹,卻和暖如春纤垂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背磷账。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工峭沦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人够颠。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓熙侍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親履磨。 傳聞我的和親對象是個(gè)殘疾皇子蛉抓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 上網(wǎng)原理 1、爬蟲概念 爬蟲是什麼剃诅? 蜘蛛巷送,蛆,代碼中矛辕,就是寫了一段代碼笑跛,代碼的功能從互聯(lián)網(wǎng)中提取數(shù)據(jù) 互聯(lián)網(wǎng): ...
    riverstation閱讀 8,056評(píng)論 1 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,101評(píng)論 1 32
  • 包含的重點(diǎn)內(nèi)容:JAVA基礎(chǔ)JVM 知識(shí)開源框架知識(shí)操作系統(tǒng)多線程TCP 與 HTTP架構(gòu)設(shè)計(jì)與分布式算法數(shù)據(jù)庫知...
    消失er閱讀 4,325評(píng)論 1 10
  • 1.內(nèi)存的頁面置換算法 (1)最佳置換算法(OPT)(理想置換算法):從主存中移出永遠(yuǎn)不再需要的頁面翻屈;如無這樣的...
    杰倫哎呦哎呦閱讀 3,249評(píng)論 1 9
  • 身為會(huì)計(jì)人界酒,這些場景你經(jīng)歷過嗎? 大家認(rèn)為的“會(huì)計(jì)” 應(yīng)該是老板超級(jí)心腹嘴秸,實(shí)際上多半是計(jì)算器毁欣; 應(yīng)該掌握著錢財(cái)大權(quán)...
    jerry媽咪媽咪閱讀 546評(píng)論 0 0