简单记录thinkphp5使用Querylist插件做采集

简单记录thinkphp5使用Querylist插件做采集_第1张图片

源码地址:https://github.com/LeeToug/NewsGather

最近公司需要做一个信息发布网站,任务分配下来之后确定我来主导这个项目。由于之前做小说采集网站的时候多用的是CMS自带的采集系统,但是本人实在不怎么感冒cms,所以在网上查看了一些资料,很神奇的找到了Querylist这个东西,今天就将我昨晚这次项目的里程分享一下。

首先,querylist官网(http://www.querylist.cc),直接点击文档走起。

大概看了一下,可以满足我的需求。okay,thinkphp5框架搭起来,使用composer安装querylist,安装之后本地出现gaegar文件夹,进去之后就会看到querylist了。至此,完成了安装的步骤啦,就是这么简单!!!

接下来就是使用Querylist类啦,一步一步来走:

首先引入类

use QL\QueryList;

然后重点

        $html = "http://www.***.com";
        //选择大的区域
        $selector = "body";
        //获取当前所选区域html
        $content=QueryList::get($html)->find($selector)->html();
        //最外层规则筛选
        $rules = array(
            'plist' => ['dt','html']
        );
        //获取分类数据、处理/采集数据
        $data = $this->dealData($content,$rules);

$html是你要采集的目标站点,$content是获取到的html页面源码,$rules是即将要用的筛选规则。主要看一下处理数据的方法dealData();

public function dealData($content,$rules){
        $data = QueryList::html($content)->rules($rules)->range('')->queryData(function ($item){
            $item = QueryList::html($item)->rules(array(
                'title' => array('a','text'),
                'original_link' =>array('a','href')
            ))->range('')->queryData();
            return $item;
        });
        return $data;
    }

该方法中由于我要采集的目标站需要两层进去,所以又写了一次内部回调。将之前获取到的页面源码$content放入html()方法中去,使用rules()方法匹配dt标签中的html源码,range()方法是分片的,我这里没有用到,就留空,但是这个方法一定要写在这儿。在回调中,将之前获取到的html源码定在在$item中,然后进行二次rule规则筛选,将原站中的标题与链接采集到,此时的$item中就已经保存了我们想要的数据了,然后我们就可以将数据存库或是做其他处理了。

至此,一次简单的采集就完成了。

后附多线程采集的源码,原理与上面一样,需要注意的是,多线程采集时,需要引入对应的类,看下,如果大家有需要的话,我会再写一篇关于querylist多线程采集的文章。

use QL\QueryList;
use QL\Ext\CurlMulti;
use think\Db;

class Gather extends Admin
{
    /**
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * 采集文章信息
     * @author lyf
     * @date 2019-5-10
     */
    public function index(){
        $param=$this->request->get();
        $ql = QueryList::getInstance();
        $ql->use(CurlMulti::class);

        $htmls = array();
        $map['status'] = 0;
        $html = Db::name('city_cate_url')
            ->where($map)
            ->order("id","ASC")
            ->limit("0","10")
            ->select();
        foreach ($html as $item){
            $url = explode('/',$item['url']);
            $link = explode('.',$url[3]);
            $htmls[] = $url[0].'//'.$url[2].'/'.$link[0].'P'.$item['page'].'.'.$link[1];
        }
        $data = $this->gather($htmls,$ql);

        $ids=array_column($html,"id");
        $res_list=db("city_cate_url")
            ->where("id","in",$ids)
            ->where('status','-1')
            ->select();
        $k=0;
        if($htmls){
            $k++;
            if($res_list){
                $this->success("正在采集第{$k}次","gather/index","",60);
            }else{
                $this->success("正在采集第{$k}次","gather/index","",30);
            }
        }else{
            $this->success("采集成功");
        }

    }

    /**
     * @param $html
     * @param $city_name
     * @param $cate_name
     * @param $num
     * @return string
     * 采集列表信息
     * @author lyf
     * @date 2019-5-8
     */
    public function gather($html,$ql){
        $ql->curlMulti($html)->success(function (QueryList $ql,CurlMulti $curl,$r){
//            echo $r['info']['url'];echo "
"; //初始化 $content1 = ''; $content2 = ''; //获取城市ID $city = explode('/',$r['info']['url']); $cityId = $this->getCityId($city[0].'//'.$city[2].'/'); $msg = ''; $selector1 = "#main"; $selector2 = "tbody"; try{ $content1=$ql->get($r['info']['url'])->find($selector1)->html(); $content2=$ql->get($r['info']['url'])->find($selector2)->html(); }catch(\Exception $e) { } $rules = [ 'title' => ['.t>div>a','title'], 'original_link' => ['.t>div>a','href'], 'img' => ['.i>a>img','src'], 'brief' => ['.t>div','html','-#wrapv1'], 'price' => ['.p','text'], 'date' => ['.u','text'] ]; if($content1&&$content2){ //处理数据信息 $data = $this->dealData($content2,$rules,$ql,$cityId,$r['info']['url']); //数据入库 if($data){ $res = $this->saveData($data,$r['info']['url']); } } else if($content1&&!$content2){ $this->endNow($r['info']['url'],$status='1'); }else{ $this->endNow($r['info']['url'],$staus='-1'); } $ql->destruct(); })->start([ // 最大并发数,这个值可以运行中动态改变。 'maxThread' => 10, // 触发curl错误或用户错误之前最大重试次数,超过次数$error指定的回调会被调用。 'maxTry' => 3, // 全局CURLOPT_* 'opt' => [ CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 1, CURLOPT_RETURNTRANSFER => true ] ]); }

源码地址:git:https://github.com/LeeToug/NewsGather

第一次在这边发博客,大家有什么不满意的地方,可以随时指正,也希望大家多多包涵。有问题随时可以私我,看到的话一定会回复哒

你可能感兴趣的:(PHP)