php使用redis异步队列爬取网站图片的教程(1)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: php使用redis异步队列爬取网站图片的教程

相信大家都很想取爬取某些网站的内容,图片,但是不知道怎么动手,以下的教程就是从0开始教大家爬取某个网站图片


准备工作:

curl封装类(需要curl扩展);

php redis扩展(用于使用redis)

redis服务器(用于队列)

QueryList插件:https://querylist.cc/  实现php选择html DOM

运行环境:本文在php-cli模式下运行,不需要考虑超时时间

首先,建立个爬取的目录(Queue)


增加Mycurl.php

<?php

/**

 * Created by PhpStorm.

 * User: tioncico

 * Date: 2018/2/26 0026

 * Time: 21:34

 */

 

namespaceQueue;

 

classMyCurl

{

    privatestatic$url    ''// 访问的url

    privatestatic$oriUrl''// referer url

    privatestatic$data   array(); // 可能发出的数据 post,put

    privatestatic$method// 访问方式,默认是GET请求

 

    publicstaticfunctionsend($url$dataarray(), $method'get')

    {

        if(!$urlexit('url can not be null');

        self::$url    $url;

        self::$method$method;

        $urlArr       parse_url($url);

        self::$oriUrl$urlArr['scheme'] . '://'$urlArr['host'];

        self::$data   $data;

        if(!in_array(

            self::$method,

            array(

                'get',

                'post',

                'put',

                'delete'

            )

        )

        ) {

            exit('error request method type!');

        }

 

        $func= self::$method'Request';

        returnself::$func(self::$url);

    }

 

    /**

     * 基础发起curl请求函数

     * @param int $is_post 是否是post请求

     */

    privatestaticfunctiondoRequest($is_post= 0)

    {

        $ch= curl_init();//初始化curl

        curl_setopt($ch, CURLOPT_URL, self::$url);//抓取指定网页

        curl_setopt($ch, CURLOPT_AUTOREFERER, true);

        // 来源一定要设置成来自本站

        curl_setopt($ch, CURLOPT_REFERER, self::$oriUrl);

 

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上

        if($is_post== 1) curl_setopt($ch, CURLOPT_POST, $is_post);//post提交方式

        if(!empty(self::$data)) {

            self::$data= self::dealPostData(self::$data);

            curl_setopt($ch, CURLOPT_POSTFIELDS, self::$data);

        }

 

        $data= curl_exec($ch);//运行curl

        curl_close($ch);

        return$data;

    }

 

    /**

     * 发起get请求

     */

    publicstaticfunctiongetRequest()

    {

        returnself::doRequest(0);

    }

 

    /**

     * 发起post请求

     */

    publicstaticfunctionpostRequest()

    {

        returnself::doRequest(1);

    }

 

    /**

     * 处理发起非get请求的传输数据

     *

     * @param array $postData

     */

    publicstaticfunctiondealPostData($postData)

    {

        if(!is_array($postData)) exit('post data should be array');

        foreach($postDataas$k=> $v) {

            $o.= "$k=". urlencode($v) . "&";

        }

        $postDatasubstr($o, 0, -1);

        return$postData;

    }

 

    /**

     * 发起put请求

     */

    publicstaticfunctionputRequest($param)

    {

        returnself::doRequest(2);

    }

 

    /**

     * 发起delete请求

     */

    publicstaticfunctiondeleteRequest($param)

    {

        returnself::doRequest(3);

    }

}

下载图片类Down.php(看完下面的教程再看这个类说明)

<?php

 

/**

 * Created by PhpStorm.

 * User: tioncico

 * Date: 2018/2/28 0028

 * Time: 19:54

 */

namespaceQueue;

useQL\QueryList;

 

classDown

{

    privatestatic$instance;

    publicfunction__construct() {

 

    }

 

    staticfunctiongetInstance(){

        if(is_object(self::$instance)){

            returnself::$instance;

        }else{

            self::$instancenewDown();

            returnself::$instance;

        }

    }

 

    publicstaticfunctionadd_img($str){//这里进来的是详情,每个详情有n页,每页一张高清大图

        $idsubstr($str,strripos($str,'/')+1);//截取出id

        $res   = \Queue\MyCurl::send($strarray('ip'=>'127.0.0.1'), 'get');

//        var_dump($res);

        $rulesarray(

            //采集id为one这个元素里面的纯文本内容

            'page'=> array(

                '.pagenavi span',

                'html'

            ),

        );

        $hj    = QueryList::Query($res$rules);

        $data$hj->getData(function($x) {//总页数

            return$x;

        });

        //获取到了页面元素

        $count$data[count($data)-2]['page'];//这个是获取倒数第2个,倒数第2个是总页数

        echo'共有'.$count."张图\n";

        for($i=1;$i<=$count;$i++){

            $url$str.'/'.$i;

            self::add_img_file($id,$url);//开始保存图片

            echo"{$i}/$count\n";

        }

    }

 

    publicstaticfunctionadd_img_file($id,$url){

        $res   = \Queue\MyCurl::send($urlarray('ip'=>'127.0.0.1','Referer'=>'http://www.mzitu.com/116663/2'), 'get');

        $rulesarray(

            //采集id为one这个元素里面的纯文本内容

            'img_url'=> array(

                '.main-image img',

                'src'

            ),

        );//获取到了高清图片链接

        $hj    = QueryList::Query($res$rules);

        $data$hj->getData(function($x) {//总页数

            return$x;

        });

        $img_url$data[0]['img_url'];

        $path= BASE_DIR.'/img/'.$id.'/';

        @mkdir($path,0777);//新建文件夹存取图片TODO缺少存进数据库

        chmod($path,0777);

        $file_path$path.substr($img_url,strripos($img_url,'/')+1);

//        var_dump($file_path);

        $data= MyCurl::send($img_url);

        $write= @fopen($file_path"w+");

        fwrite($write$data);

        fclose($write);//存取图片

    }

 

}


封装redis.php类

<?php

namespaceQueue;

classRedis

{

    private$con;

    protectedstatic$instance;

    protected$tryConnectTimes= 0;

    protected$maxTryConnectTimes= 3;

    function__construct()

    {

        $this->connect();

    }

    functionconnect(){

        $this->tryConnectTimes++;

        $confarray(

            "HOST"=>'127.0.0.1',

            "PORT"=>6379,

            "AUTH"=>""

        );

        $this->con = new\Redis();

        $this->con->connect($conf['HOST'], $conf['PORT'],2);

        $this->con->auth($conf['AUTH']);

        if(!$this->ping()){

            if($this->tryConnectTimes <= $this->maxTryConnectTimes){

                return$this->connect();

            }else{

                trigger_error("redis connect fail");

                returnnull;

            }

        }

        $this->con->setOption(\Redis::OPT_SERIALIZER,\Redis::SERIALIZER_PHP);

    }

    staticfunctiongetInstance(){

        if(is_object(self::$instance)){

            returnself::$instance;

        }else{

            self::$instancenewRedis();

            returnself::$instance;

        }

    }

    functionrPush($key,$val){

        try{

            return$this->con->rpush($key,$val);

//            return $ret;

        }catch(\Exception $e){

            $this->connect();

            if($this->tryConnectTimes <= $this->maxTryConnectTimes){

                return$this->rPush($key,$val);

            }else{

                returnfalse;

            }

 

        }

 

    }

    functionlPop($key){

        try{

            return$this->con->lPop($key);

        }catch(\Exception $e){

            $this->connect();

            if($this->tryConnectTimes <= $this->maxTryConnectTimes){

                return$this->lPop($key);

            }else{

                returnfalse;

            }

 

        }

    }

    functionlSize($key){

        try{

            $ret$this->con->lSize($key);

            return$ret;

        }catch(\Exception $e){

            $this->connect();

            if($this->tryConnectTimes <= $this->maxTryConnectTimes){

                return$this->lSize($key);

            }else{

                returnfalse;

            }

 

        }

    }

    functiongetRedisConnect(){

        return$this->con;

    }

    functionping(){

        try{

            $ret$this->con->ping();

            if(!empty($ret)){

                $this->tryConnectTimes = 0;

                returntrue;

            }else{

                returnfalse;

            }

        }catch(\Exception $e){

            returnfalse;

        }

    }

 

}

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3月前
|
PHP
使用PHP实现随机调用图片
使用PHP实现随机调用图片
72 0
使用PHP实现随机调用图片
|
3月前
|
消息中间件 移动开发 NoSQL
Redis 协议 事务 发布订阅 异步连接
Redis 协议 事务 发布订阅 异步连接
|
3月前
|
消息中间件 存储 NoSQL
redis协议与异步方式学习笔记
redis协议与异步方式学习笔记
49 0
|
3月前
|
消息中间件 NoSQL Java
别再用 Redis List 实现消息队列了,Stream 专为队列而生
别再用 Redis List 实现消息队列了,Stream 专为队列而生
68 0
|
16天前
|
NoSQL Linux PHP
php添加redis扩展 linux和windos图文详解 l
php添加redis扩展 linux和windos图文详解 l
3 0
|
1月前
|
存储 PHP Apache
使用CFimagehost源码搭建无需数据库支持的PHP免费图片托管私人图床
使用CFimagehost源码搭建无需数据库支持的PHP免费图片托管私人图床
|
2月前
|
存储 NoSQL API
【小小思考】Redis实现去重任务队列
【2月更文挑战第1天】思考一下如何用Redis实现去重的任务队列,主要有List 、List + Set/Hash/Bloom Filter、ZSet、Lua和开源库等方式。
79 1
|
2月前
|
消息中间件 NoSQL Kafka
Redis事务与异步方式
Redis事务与异步方式
35 0
|
3月前
|
NoSQL Java 关系型数据库
使用Kafka实现Java异步更新通知解决Redis与MySQL数据不一致
使用Kafka实现Java异步更新通知解决Redis与MySQL数据不一致
41 0

热门文章

最新文章