//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'],将这个配置去掉,否则就会报错..
至于怎么使用定时+命令行采集,能够看这一篇