//1.首先,你得建立一張表,叫採集表,,若是你只是簡單地幾條連接,能夠手動錄入,若是比較多的話,就須要本身用方法,寫個for循環,匹配一些規則生成url,存儲在表內.php
CREATE TABLE `cp_lottery_articles_gather_list` ( `id` int(11) NOT NULL AUTO_INCREMENT, `site_id` int(11) NOT NULL COMMENT '站點id', `lottery_id` int(11) DEFAULT NULL COMMENT '彩票id', `type_id` int(11) DEFAULT NULL COMMENT '文章欄目類型id', `category_id` int(11) DEFAULT NULL COMMENT '資訊欄目ID', `lottery_name` varchar(255) DEFAULT NULL COMMENT '關聯彩票名稱', `type_name` varchar(255) DEFAULT NULL COMMENT '類型名稱', `link` varchar(255) NOT NULL COMMENT '採集連接', `total_page` int(11) DEFAULT '1' COMMENT '總採集頁數', `now_page` int(11) DEFAULT '1' COMMENT '最大頁數', `error` int(11) DEFAULT '0' COMMENT '錯誤次數', `del` int(11) DEFAULT '0' COMMENT '是否刪除(-1爲刪除,0爲默認)', `status` int(11) DEFAULT '1' COMMENT '狀態值(1爲待採集,2爲採集ok)', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=147 DEFAULT CHARSET=utf8;
這是表數據html
2.開始進入代碼,首先寫一個獲取採集連接的方法. 將連接數據放入全局變量,好處是,當你在使用curlMulity多線程採集的時候,線程內部,惟一的判斷標準是你的連接,也就是url,,而後你怎麼去判斷哪一次採集的數據,是屬於哪一條連接的呢?如何根據連接定位到ID呢? 這個時候這個$GLOBAS就起大做用了,能夠在線程內部去調用globas變量,而後字符串搜索連接,這樣就找到對應的連接信息和ID了.sql
//獲取批量的待採集列表頁連接,並將鏈接放到全局變量$GLOBALS private function get_list_links(){ //條件:站點ID爲500彩票網,狀態爲1(待採集) $where=[ "site_id"=>$this->site_id, "status"=>1 ]; $list=db("lottery_articles_gather_list") ->where($where) ->order("id","asc") ->limit(0,10) ->select(); if(empty($list)){ return false; } //對後綴進行拼接.若是nowpage爲1,則爲index.shtml foreach ($list as $k=>$v){ $suffix="index".$v['now_page'].".shtml"; if($v['now_page']=="1"){ $suffix="index.shtml"; } $list[$k]["link"]=$v["link"].$suffix; } //放到全局變量裏面去 $GLOBALS['wubai_gather_list']=$list; return $list; }
3.(重要)採集方法.數組
大體過程就是:瀏覽器
3.1.先將globas裏面的連接二維數據取出來,而後經過array_column,只去其中的link字段,獲取到10條只包含連接字符串的一維數組緩存
3.2 初始化queryList插件,而後使用curlMulity,進行採集.網絡
3.3 在內部,每次採集,根據規則,獲取到你想要的數據,對數據進行處理後.一樣放到$globas全局變量中多線程
3.4 對於沒采集到的,就不用管了..併發
//採集列表開始 private function gather_list_do(){ //獲取採集列表 $link_list=$GLOBALS["wubai_gather_list"]; //得到一維數組 $links=array_column($link_list,"link"); //執行採集 $ql=QueryList::getInstance(); $ql->use(CurlMulti::class); $opt=[ CURLOPT_TIMEOUT=> 5, CURLOPT_CONNECTTIMEOUT=>5, CURLOPT_RETURNTRANSFER=>1,//不輸出數據 CURLOPT_SSL_VERIFYPEER=>0,//https驗證 CURLOPT_FOLLOWLOCATION=>0,//不重定向 CURLOPT_USERAGENT=>$_SERVER['HTTP_USER_AGENT'], CURLOPT_AUTOREFERER=>0, CURLOPT_ENCODING=>'gzip,deflate', CURLOPT_HEADER=>0, ]; $GLOBALS['all_data']=[]; $ql->curlMulti($links) ->success(function (QueryList $ql,CurlMulti $curl,$r){ //開始獲取數據 echo $r['info']['url'].'採集數據中<br/>'; //分片規則 $range="#news_list>ul li"; //採集元素規則 $rules=[ "date"=>[".newsdate","text"], "title"=>["a","text"], "link"=>["a","href"], ]; $data=$ql ->rules($rules) ->encoding('UTF-8','GB2312')->removeHead() ->range($range) ->queryData(); echo "採集完成<br/>"; if(!empty($data)){ echo $r['info']['url'].'成功獲取數據<br/>'; //成功採集的數據,及其連接 放入到公共變量內 $GLOBALS['all_data'][]=[ "link"=>$r['info']['url'], "data"=>$data ]; } echo "釋放內存----------------<br/>"; //釋放內存 $ql->destruct(); })->error(function ($errorInfo,CurlMulti $curl,$r){ //跳過 })->start([ // 最大併發數,這個值能夠運行中動態改變。 'maxThread' => 5, // 觸發curl錯誤或用戶錯誤以前最大重試次數,超過次數$error指定的回調會被調用。 'maxTry' => 1, // 全局CURLOPT_* 'opt' =>$opt, // 緩存選項很容易被理解,緩存使用url來識別。若是使用緩存類庫不會訪問網絡而是直接返回緩存。 'cache' => ['enable' => false, 'compress' => false, 'dir' => null, 'expire' =>86400, 'verifyPost' => false] ]); }
4.最後將$globas裏面的數據,也就是採集到的數據,進行入庫處理..並對採集連接表,也進行處理..curl
4.1若是全鏈爲空,那麼將全部的連接now_page(當前採集頁碼),進一位..
4.2循環數據,定位連接,插入文章詳情表,,更新採集連接表
//設置文章列表數據 private function set_arc_detail(){ $all_data=$GLOBALS['all_data']; //若是是空數組,將全部的當前page+1,跳過 if(empty($all_data)){ foreach ($GLOBALS['wubai_gather_list'] as $k=>$v){ $now_page=$v['now_page']+1; db("lottery_articles_gather_list") ->where(["id"=>$v['id']]) ->update(['now_page'=>$now_page]); } return true; } //採集連接列表 $gather_links=array_column($GLOBALS["wubai_gather_list"],"link"); //1.定義變量接受數據 $articles_save_data=[]; $gather_links_save_data=[]; foreach ($all_data as $k=>$v){ //2.查詢當前的每個url在原始採集鏈中的定位 $key=array_search($v['link'],$gather_links); //找到這個url->對應的lottery_articles_gather_list對應的數據 $link_info=$GLOBALS['wubai_gather_list'][$key]; //3.準備lottery_articles表須要的保存的數據 foreach ($v["data"] as $k2=>$v2){ //若是標題或者連接爲空,跳過本次數據. if(strlen($v2["title"])==""||$v2["link"]==""){ continue; } //組裝數據 $data=[ "site_id"=>$this->site_id, "lottery_id"=>$link_info["lottery_id"], "category_id"=>$link_info["category_id"], "type_id"=>$link_info["type_id"], "type_name"=>$link_info["type_name"], "category_name"=>db("lottery_articles_category")->where(["id"=>$link_info['category_id']])->cache()->value("name"), "arc_link"=>$v2['link'], "title"=>$v2["title"], "keywords"=>"", "description"=>"", "content"=>"", "create_time"=>strtotime($v2["date"]), "create_time_html"=>$v2["date"], "post_time"=>$_SERVER['REQUEST_TIME'], "order"=>"0", "hot"=>"0", "status"=>"1" ]; $articles_save_data[]=$data; } //4.準備lottery_articles_gather_list採集連接表,須要更新的數據 $gather_links_data=[ "id"=>$link_info['id'], "now_page"=>$link_info["now_page"]+1, ]; //若是當前採集頁>=總頁碼,此條連接採集結束 if($link_info['now_page']>=$link_info['total_page']){ $gather_links_data["status"]=2; } $gather_links_save_data[]=$gather_links_data; } //5.執行插入,和更新操做. $arc_res_count=model("LotteryArticles")->insert_all_data($articles_save_data); $lists_up_count=0; if($arc_res_count>0){ $lists_up_res=model("LotteryArticlesGatherList")->saveAll($gather_links_save_data); $lists_up_count=count($lists_up_res); } //6.輸出結果 echo "總採集文章數量成功插入條數爲:{$arc_res_count}條<br/>"; echo "總採集連接修改數量爲:{$lists_up_count}條<br/>"; } //處理字符串,只獲取字符串裏面的數字 private function get_number($str){ return preg_replace('/([\x80-\xff]*)/i','',$str); }
5.最後用一個方法,對這幾個方法,進行調用,循環....就這樣,打開瀏覽器,就讓他一直採集成功,跳轉....就行了..雖然方法比較笨拙..
也能夠採用定時任務,去用命令行執行php文件的方式,定時採集..
private $site_id=2; //採集全部列表頁 public function gather_all_list(){ //獲取採集的url列表 $link_list=$this->get_list_links(); //獲取採集的數據集 $this->gather_list_do(); //處理採集的數據集合 $this->set_arc_detail(); $this->success("wubai_arc/gather_all_list"); }
//11.7日補充更新
能夠採用命令行的形式先跑一遍
而後若是須要天天都採集,可使用定時任務+php命令行採集
注意:命令行採集的時候,將 CURLOPT_USERAGENT=>$_SERVER['HTTP_USER_AGENT'],將這個配置去掉,否則就會報錯..
至於怎麼使用定時+命令行採集,能夠看這一篇