使用phpQuery采集文章或者其他数据...

风格不统一 提交于 2020-01-07 18:44:02

【推荐】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

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!