多线程方式采集搜狗高清壁纸的实现

news/2024/7/8 3:10:35 标签: php, 数据库, 操作系统

上一篇,完成了Windows下PHP多线程扩展pthreads的安装,下面就利用多线程进行图片的采集

一、实现前准备工作

1、打开搜狗图片网站

打开控制台,分析异步请求数据规律
640833-20171119234903406-1948171387.png
640833-20171119235456515-2044215667.png

2、搜狗图片存储数据表结构创建

打开搜狗异步请求链接,查看响应结果中的json数据

640833-20171120000951952-1174636073.png
根据上图中图片详情创建搜狗图片数据表结构sql语句如下:

CREATE TABLE `sougou_pic` (
  `sougou_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '表主键id',
  `id` int(11) DEFAULT NULL COMMENT '搜过网站图片id',
  `did` int(10) DEFAULT NULL,
  `thumbUrl` varchar(255) DEFAULT NULL,
  `thumb_width` int(10) DEFAULT NULL,
  `thumb_height` int(10) DEFAULT NULL,
  `sthumbUrl` varchar(255) DEFAULT NULL,
  `sthumb_width` int(10) DEFAULT NULL,
  `sthumb_height` int(10) DEFAULT NULL,
  `bthumbUrl` varchar(255) DEFAULT NULL,
  `bthumb_width` int(10) DEFAULT NULL,
  `bthumb_height` int(10) DEFAULT NULL,
  `pic_url` varchar(255) DEFAULT NULL,
  `width` int(10) DEFAULT NULL,
  `height` int(10) DEFAULT NULL,
  `size` int(10) DEFAULT NULL,
  `ori_pic_url` varchar(255) DEFAULT NULL,
  `ext_url` varchar(255) DEFAULT NULL,
  `page_title` varchar(64) DEFAULT NULL,
  `page_url` varchar(255) DEFAULT NULL,
  `title` varchar(64) DEFAULT NULL,
  `tags` varchar(64) DEFAULT NULL,
  `group_mark` varchar(8) DEFAULT NULL,
  `group_index` int(10) DEFAULT NULL,
  `publish_time` int(10) DEFAULT NULL,
  `surr1` varchar(16) DEFAULT NULL,
  `surr2` varchar(16) DEFAULT NULL,
  `category` varchar(16) DEFAULT NULL,
  `weight` int(10) DEFAULT NULL,
  `deleted` int(10) DEFAULT NULL,
  `waplink` varchar(255) DEFAULT NULL,
  `weblink` varchar(255) DEFAULT NULL,
  `intime` int(10) DEFAULT NULL COMMENT '添加时间',
  `pfrom` varchar(255) DEFAULT '',
  PRIMARY KEY (`sougou_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11088 DEFAULT CHARSET=utf8;

数据库">3、录入搜狗图片到数据库

采集代码这里省略,需要注意的是,采集过程中防止超时的存在(主要可能还是搜狗有做简单反爬虫处理),超时采集不到就延时5秒继续采集。

下面是录入完成后数据表一览
640833-20171120011148133-235507541.png

数据库中已录入的搜狗图片">二、多线程方式下载数据库中已录入的搜狗图片

1、采用Yii2框架实现

  • Yii2框架控制台(console)下创建命令行可执行脚本文件SougouController.php,代码如下:
php">
<?php

namespace console\controllers;

use yii;
use yii\console\Controller;
use common\models\SougouPic as M;
use common\component\SougouPthreads;
use yii\console\Exception;

class SougouController extends Controller
{
    /**
     * 下载搜狗图片
     */
    public function actionDownload()
    {
        try{
            $stime=microtime(true);

            $arrsSougouPic = M::myTables();//3500,6030,9636
            echo '图片总数量共: '.count($arrsSougouPic).PHP_EOL;

            //线程池
            $pool = array();

            foreach ($arrsSougouPic as $member){
                $sougou_id = $member['sougou_id'];
                while (true){
                    if(count($pool) < 5){
                        //要下载的原图
                        $ori_pic_url = $member['ori_pic_url'];
                        $pool[$sougou_id] = new SougouPthreads($member['sougou_id'], $member['size'], $member['title'], $ori_pic_url, $member['width'], $member['height']);
                        $pool[$sougou_id]->start();
                        break;
                    }else{
                        foreach ( $pool as $name => $worker){
                            if(! $worker->isRunning()){
                                unset($pool[$name]);
                            }
                        }
                    }
                }
            }

            $arrsSougouPic = null;

            echo "Download completed!".PHP_EOL;

            $etime=microtime(true);//获取程序执行结束的时间
            $total=$etime-$stime;   //计算差值
            echo '共运行时间:'.$total.'秒'.PHP_EOL;
        } catch (Exception $e) {
            echo '【' , date('H:i:s') , '】', '【系统错误】', $e->getMessage(), "".PHP_EOL;
        }
    }
    
}
  • 搜狗多线程类继承线程类,SougouPthreads.php代码如下
php">
<?php
namespace common\component;

use Yii;
use Thread;

class SougouPthreads extends Thread
{
    public $running = false;
    public $sougou_id = '';
    public $title = '';
    public $size;
    public $ori_pic_url = '';
    public $width = '';
    public $height = '';
    protected $saveDir = '';
    protected $downloadFailedTxt;

    public function __construct($sougou_id, $size, $title, $ori_pic_url, $width, $height)
    {
        $this->sougou_id = $sougou_id;
        $this->size = $size;
        $this->title = $title;
        $this->ori_pic_url = $ori_pic_url;
        $this->width = $width;
        $this->height = $height;

        $this->saveDir.='./static/sougouImages/'.date('Y-m-d').'/'.$this->width.'_'.$this->height.'/';
        $this->downloadFailedTxt = $this->saveDir.'1_downloadfailedlist.txt';
        if(!is_dir($this->saveDir)){
            mkdir($this->saveDir, 0777, true);
            chmod($this->saveDir, 0777);
        }
    }

    public function run()
    {
        //下载
        $return = $this->downloadImage();
        if (!$return) {
            echo $this->ori_pic_url.' Download failed'.PHP_EOL;
        }else{
            echo $this->ori_pic_url.' Download completed'.PHP_EOL;
        }
    }


    /**
     * 下载图片
     * @return bool
     */
    public function downloadImage()
    {
        //图片后缀
        $basename = basename($this->ori_pic_url);
        $dot = strrpos($basename, '.');
        $imageExt = substr($basename, $dot);
        $imageTitle = substr($basename, 0, $dot);
        if(strlen($this->title)<2){
            //图片名称
            $imageName = $imageTitle.'_'.$this->sougou_id;
        }else{
            //图片名称
            $imageName = $this->title.'_'.$this->sougou_id;
        }
        $imageName = iconv('UTF-8', 'GBK', $imageName);
        //保存图片路径及名称
        $filename = $this->saveDir.$imageName.$imageExt;
        //判断文件是否已下载
        if(file_exists($filename)){
            file_put_contents($this->downloadFailedTxt, $this->ori_pic_url.' --文件已下载'.PHP_EOL, FILE_APPEND);
            return true;
        }
        //获取远程文件
        $imgContent = $this->myCurl($this->ori_pic_url);
        if(!$imgContent){
            return false;
        }
        //保存图片到本地
        $return=file_put_contents($filename, $imgContent);

        if(!file_exists($filename)){
            //记录下载失败的图片信息
            file_put_contents($this->downloadFailedTxt, $this->ori_pic_url.' --下载失败'.PHP_EOL, FILE_APPEND);
            return false;
        }

        //图片大小与录入时记录的图片大小不一致,说明图片下载失败
        if(filesize($filename) != $this->size){
            //下载图片不完整,删除
            unlink($filename);
            file_put_contents($this->downloadFailedTxt, $this->ori_pic_url.' --下载图片不完整'.PHP_EOL, FILE_APPEND);
            return false;
        }
        return true;
    }


    /**
     * @author RenZhicai <renzhicai.sz@mopon.cn>
     * 自定义curl请求
     * @param string $url
     * @return mixed
     */
    public function myCurl($url='')
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT,60);   //只需要设置一个秒的数量就可以
        if(preg_match('/https:\/\//', $url)){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //这个是重点。
        }
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1');
        $output = curl_exec($ch);
        if($output === false){
            //记录curl请求失败的详情
            $errorInfo = "cURL Error: ".curl_error($ch);
            file_put_contents('curl_error_'.date('Ymd').'.txt', $errorInfo, FILE_APPEND);
        }
        curl_close($ch);

        return $output;
    }
}

2、在Yii2项目根目录执行控制台脚本(console)

php">//将执行结果记录到文本文件中
php yii sougou/download > sougoudownloadinfo.txt

640833-20171120013304118-1191903083.png

3、下载完后效果一览

自动按尺寸归类图片
640833-20171120012746977-1806088870.png

640833-20171120012910477-1790200874.png

【参考资料】

  • PHP Pthread多线程 操作

转载于:https://www.cnblogs.com/renzhicai/p/7863473.html


http://www.niftyadmin.cn/n/838109.html

相关文章

More-iOS国际化一站式解决方案

关于iOS开发中的国际化&#xff08;也可称为多语言&#xff09;在网上的文章多如牛毛&#xff0c;不过总结起来就那么一回事&#xff0c;不是说他们写的不好我写的多好&#xff0c;而是说过于零散。 现在&#xff0c;我将结合实际场景需求进行国际化做法详解。可以肯定的是&…

jsp使用cookie实现记住密码的功能

文章来源&#xff1a;http://blog.csdn.net/dracowk/article/details/6887327 这个一个页面模拟的cookie 如果你要实现登录&#xff0c;当用户输入用户名密码时&#xff0c;到控制层用 Cookie user new Cookie("user",name"-"passward); 加到cookie中&am…

心医国际全网独家直播“首届人机竞技读片交流会”

2012 年&#xff0c;人工智能首次在自然图像识别领域达到人类水平&#xff1b;2013-2015年&#xff0c;通过GPU加速技术&#xff0c;人工智能快速发展&#xff0c;在各个领域上有了不凡的表现&#xff1b;2016年&#xff0c;谷歌ALphaGo更是以4&#xff1a;1 的成绩完胜世界围棋…

zabbix的setup无法进入第二步

垃圾&#xff0c;什么信息都不报&#xff0c;点击下一步返回welcome页面chmod -R 777 /var/lib/php/session

解决:type=password type=text用户名和密码输入框大小不一样 本篇文章来源于 电脑知识网(www.diannaozs.com) 原文出处:http://www.diann

文章来源&#xff1a;http://blog.csdn.net/dracowk/article/details/6887127 用户名输入框和密码输入框大小不一样&#xff1a; type"password" 这个密码输入框显示出来比type"text" 输入框宽度小&#xff0c;但是高度大&#xff0c;如何调制为一样呢&a…

使用自选择创建团队

在企业中&#xff0c;自选择用于在团队间重新分配员工。使得开发人员有机会参与到战略决策中&#xff0c;并很好地理解业务需求。使用自选择&#xff0c;将赋予员工去承担困难的权利&#xff0c;并告知他们具体的决策情况。那么无论决策是多么艰难&#xff0c;员工都会积极主动…

linux 瓶颈 工具,linux-sar避免系统瓶颈--简单实用的工具

Linux-sar作用目前Linux上最为全面的系统性能分析工具之一&#xff0c;可以从多方面对系统的活动进行报告&#xff0c;包括&#xff1a;文件的读写情况、系统调用的使用情况、磁盘I/O、CPU效率、内存使用状况、进程活动及IPC有关的活动等。安装yum installsysstat -ysar命令常…

Linux-centos-7.2-64bit 安装配置mysql

2018-04-12 安装在/usr/local/下&#xff0c;配置文件在/etc/my.ini 1.下载mysql安装包到 /usr/local/software cd /usr/local/software wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.33-linux-glibc2.5-x86_64.tar.gz 2.安装依赖环境 yum -y install perl pe…