多线程方式采集搜狗高清壁纸的实现
生活随笔
收集整理的這篇文章主要介紹了
多线程方式采集搜狗高清壁纸的实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一篇,完成了Windows下PHP多線程擴展
pthreads的安裝,下面就利用多線程進行圖片的采集
一、實現前準備工作
1、打開搜狗圖片網站
打開控制臺,分析異步請求數據規律
2、搜狗圖片存儲數據表結構創建
打開搜狗異步請求鏈接,查看響應結果中的json數據
根據上圖中圖片詳情創建搜狗圖片數據表結構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秒繼續采集。
下面是錄入完成后數據表一覽
二、多線程方式下載數據庫中已錄入的搜狗圖片
1、采用Yii2框架實現
在Yii2框架控制臺(console)下創建命令行可執行腳本文件SougouController.php,代碼如下:
<?php
namespace consolecontrollers;
use yii;
use yiiconsoleController;
use commonmodelsSougouPic as M;
use commoncomponentSougouPthreads;
use yiiconsoleException;
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
namespace commoncomponent;
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 yii sougou/download > sougoudownloadinfo.txt
3、下載完后效果一覽
自動按尺寸歸類圖片
【參考資料】
PHP Pthread多線程 操作
總結
以上是生活随笔為你收集整理的多线程方式采集搜狗高清壁纸的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MCPS & MIPS
- 下一篇: ubuntu下root用户默认密码及修改