【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
//1.首先,你得创建一张表,叫采集表,,如果你只是简单地几条链接,可以手动录入,如果比较多的话,就需要自己用方法,写个for循环,匹配一些规则生成url,存储在表内.
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;
这是表数据
2.开始进入代码,首先写一个获取采集链接的方法. 将链接数据放入全局变量,好处是,当你在使用curlMulity多线程采集的时候,线程内部,唯一的判断标准是你的链接,也就是url,,然后你怎么去判断哪一次采集的数据,是属于哪一条链接的呢?如何根据链接定位到ID呢? 这个时候这个$GLOBAS就起大作用了,可以在线程内部去调用globas变量,然后字符串搜索链接,这样就找到对应的链接信息和ID了.
//获取批量的待采集列表页链接,并将连接放到全局变量$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里面的数据,也就是采集到的数据,进行入库处理..并对采集链接表,也进行处理..
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'],将这个配置去掉,不然就会报错..
至于怎么使用定时+命令行采集,可以看这一篇
https://my.oschina.net/laobia/blog/3121944
来源:oschina
链接:https://my.oschina.net/u/3360064/blog/3050371