[python] 溜了,溜了,七牛雲圖片資源批量下載 && 自建圖床服務器



故事背景:

七牛雲最近一波測試域名操作真是把我坑死了!這簡直和百度贈送你2T網盤,之后再限速一樣騷操作。於是,痛定思痛自己買個雲主機、自己搭圖床應用!


1、七牛圖片批量下載到本地

1.1 曲折嘗試

當測試鏈接不能用的時候,我想依次用到下面幾個方法嘗試download圖片:

  • 用七牛之前的傳圖工具qshell,看看有啥辦法(行不通)
  • 找七牛圖片資源處看看有沒有批量打包下載(NO)
  • 自己寫個前端爬蟲將圖片爬下來(沒下載鏈接...)
  • 綁定一個自己的域名(需要實名認證+域名備案)
    ...

最后發現一個神器:qfetch,是根據七牛雲存儲API實現的一個簡易命令行輔助工具。覆蓋七牛雲存儲開發者網站包含的大部分甚至更高級的功能。開發者在對七牛雲存儲 API 有基本了解的情況下,此工具將會非常適用。


1.2 qfetch基本操作

-按照如下指令,輸入自己七牛雲的賬號和密碼登錄

./qrstcl login <your username> <your password>

由於我之前所有圖片是在七牛雲對象存儲中的bucket中,運行如下代碼查看目前我建立的所有bucket:

./qrsctl buckets

我里面只有一個buckets:beautifulzzzz

可以用下列命令查看該buckets下的所有資源:(注意最后是兩個英文單引號)

./qrsctl listprefix beautifulzzzz ''

得到資源列表后,可以調用下列命令下載一個資源:

qrsctl get <Bucket> <Key> <DestFile>
比如./qrsctl get beautifulzzzz 1.jpg ./1.jpg可以將picture中的1.jpg下載到本地機器當前路徑下的1.jpg

1.3 自動化腳本

綜上幾步,可以寫一個自動化腳本:

qiniuyun (master) ✗ cat download.sh 
#!/bin/bash
imgs=`./qrsctl listprefix beautifulzzzz ''`

i=0 
echo $imgs | tr " " "\n" | while read line
do
    if(($i>0))
    then
	echo $line
	path=`dirname $line`
	echo $path
	if [ ! -d "$path" ];then
	    mkdir -p $path
	fi

	./qrsctl get beautifulzzzz $line ./$line
    fi
    i=$(($i+1))
done

注:該腳本相對於 chensonglu 分享的《七牛雲測試域名失效導致圖片外鏈失效的解決辦法》,增加了多級目錄文件下載功能。


2、python 圖床服務器搭建

2.1 python3環境搭建

安裝python:

sudo apt-get install python2.7-dev python3-dev
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py

安裝python虛擬環境virtualenv virtualenvwrapper:(用虛擬開發環境可以為每個工程提供獨立的python開發環境、獨立的包、獨立的版本,每個獨立的環境會在~/.virtualenvs/下形成資源包~)

sudo pip install virtualenv virtualenvwrapper
sudo rm -rf ~/.cache/pip

之后在~/.profile文件最后添加下面幾行:

# virtualenv and virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh

之后如果想用python虛擬環境,在每次打開一個新的terminal就要執行一次source ~/.profile

$ source ~/.profile

接下來我們生成一個python虛擬環境來用於python_pic_server的開發提供環境:(這里不講python2,強烈建議用python3)

mkvirtualenv python_pic_server -p python3

注:再次說明python虛擬環境是完全獨立的,也就是說在python_pic_server的環境下安裝的python包,步適用於全局;在全局安裝的包,不適合python_pic_server。

如何驗證你如何將python_pic_server環境生成好了呢?——新開一個terminal,執行下列命令:

$ source ~/.profile
$ workon python_pic_server

如果terminal前面的文字變成了(python_pic_server)表明成功創建了名為python_pic_server的python虛擬環境,在接下來的操作中都要保持在python_pic_server環境中!


2.2 安裝Sanic

sanic 是一個比較新的,但是發展比較快的框架。其特征是速度非常快。據他們官方網站自己說,sanic 是最快的 python 框架。

Sanic is a Flask-like Python 3.5+ web server that’s written to go fast. It’s based on the work done by the amazing folks at magicstack, and was inspired by this article.

在python_pic_server中安裝sanic:

pip install sanic

sanic用法比較簡單,具體可以參考:[6].sanic getting started page


2.3 寫圖床服務器程序

在/root/App/python_pic_server目錄下創建run.py:

(python_pic_server) ➜  python_pic_server cat run.py 
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from sanic import Sanic
from sanic.log import logger
from sanic.response import json, text, file
import os, sys
import hashlib
import base64

app = Sanic()
# 圖片存儲目錄
baseDir = sys.path[0] + '/image/'
# 校驗 Token 寫死就成,反正自己用的嘛
token = 'SheIsABeautifulGirl'
# 允許的域名列表
allowHost = [
	    '127.0.0.1:8000',
	    'localhost',
	    'pic.phage.com'
	]

# 成功返回方法
def ok(data):
    if type(data) == list:
	return json({"data": {"list": data}, "status": 0})
    else:
	return json({"data": data, "status": 0})
# 失敗返回方法
def fail(data):
    return json({"data": data, "status": 1})

# 獲取圖片后綴名
def getSuffix(filename):
    tempArr = filename.split('.')
    suffix = tempArr[-1]
    fileType = ['jpg', 'jpeg', 'gif', 'png']
    if len(tempArr) < 2:
	return 'error name'
    elif suffix not in fileType:
	return 'error type'
    else:
	return suffix
# 檢查請求地址是否授權
def checkHost(host):
    for i in allowHost:
	if i in host:
	    return True
    return False

# 上傳圖片文件接口
@app.route('/api/v1/upimg', methods=['POST'])
async def upimg(request):
    # 判斷用戶是否具有上傳權限
    if request.headers.get('token') != token:
	return fail('您沒有使用本服務的權限')
    image = request.files.get('file').body
    # 判斷文件是否支持
    imageName = request.files.get('file').name
    imageSuffix = getSuffix(imageName)
    if 'error' in imageSuffix:
	return fail(imageSuffix)
    # 組織圖片存儲路徑
    m1 = hashlib.md5()
    m1.update(image)
    md5Name = m1.hexdigest()

    # 用 md5 的前兩位來建文件夾,防止單個文件夾下圖片過多,又或者根目錄下建立太多的文件夾
    saveDir = baseDir + md5Name[0:2] + '/'
    savePath = saveDir + md5Name[2:] + '.' + imageSuffix
    resPath = '/' + md5Name[0:2] + '/' + md5Name[2:] + '.' + imageSuffix

    # 如果文件夾不存在,就創建文件夾
    if not os.path.exists(saveDir):
	os.makedirs(saveDir)

    # 將文件寫入到硬盤
    tempFile = open(savePath, 'wb')
    tempFile.write(image)
    tempFile.close()

    # 給客戶端返回結果
    return ok({"path": resPath})

# 請求圖片接口
@app.route('/', methods=['GET'])
async def img(request):
    # 判斷是否為網站請求,否則就加上自定義的字符串(允許本地訪問)
    host = request.headers.get('host') or 'no_host'
    # 判斷請求接口是否帶參數,否則加上自定義字符串(沒有這個文件夾,返回404)
    args = request.args.get('path') or 'no_file'
    # 拼接文件地址
    path = baseDir + args
    #logger.info(request.headers)
    #logger.info(path)
    #logger.info(host)
    # 如果不在允許列表,則展示 401 圖片
    if not checkHost(host):
	path = baseDir + '/cb/fea262f9b861c6fce14d3c3c8ba9a1.png'
    # 如果文件不存在,則展示 404 圖片
    if not os.path.exists(path):
	path = baseDir + '/b4/dcd9ad1068ae6aa41ce486fa7f2739.png'
    # 返回文件
    logger.info(path)
    return await file(path)
# 啟動服務
if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)

2.4 nginx配置

vim /etc/nginx/nginx.conf 編輯配置文件,在http模塊的最后添加:

server {
	listen 3000;
	server_name tuchuang.beautifulzzzz.com;
	location / {
		proxy_pass  http://127.0.0.1:8000;
	}
}

修改好之后relaod一下nginx:

nginx -s reload

這樣訪問 tuchuang.beautifulzzzz.com:3000 就相當於訪問本機的8000端口,正好是我們的圖床服務器端口!

注: 別忘了在你購買域名的地方設置一下A解析!我沒備案,因此就用了3000端口。


2.5 運行圖床並使用

將第1步下載的七牛雲圖片放在image目錄下,然后將run.py設置為可執行,並執行:

chmod +x run.py
./run.py

注: 想在后台執行可以用:nohup ./run.py &

此時,訪問圖片可以通過 (/image/20180926/flygame.png)

http://tuchuang.beautifulzzzz.com:3000/?path=/20180926/flygame.png 

上傳圖片可以通過:

curl http://tuchuang.beautifulzzzz.com:3000/api/v1/upimg -F "file=@a.png" -H "token: SheIsABeautifulGirl" -v

3、shell腳本批量替換某文件夾下文件中的域名字串

現在,准備寫一個批處理腳本進行善后。我首先想到的是用下面命令直接搞定:

sed -i "s/A/B/g" `grep -rl A`

可是發現grep出來的文件目錄中帶有空格,這樣這條命令就處理不到!

於是自己寫了一個循環查找替換的批處理腳本:

doc (master) ✗ cat change.sh 
#!/bin/bash
#bash change.sh "odff1d90v.bkt.cloudd
#n.com" "tuchuang.beautifulzzzz.com:3000\/?path="

#bash change.sh "sed src string" "sed dst string"
IFS=$'\n'

if [ "$1" = "" ] && [ "$2" = "" ];then
    echo "params 2"
    exit
fi

for element in `grep -rl "$1"`
do
    #echo $element
    cmd="s/$1/$2/g"
    echo $cmd
    sed -i $cmd $element
done

注: 這里IFS=$'\n'是為了讓FOR循環的時候以換行作為分割

使用的時候只要將該文件放置在對應的ROOT目錄中,執行:

bash change.sh "odff1d90v.bkt.clouddn.com" "tuchuang.beautifulzzzz.com:3000\/?path="

注:change.sh的兩個參數就是sed的被替換對象和替換對象,注意轉譯符!


[1].七牛雲測試域名失效導致圖片外鏈失效的解決辦法
[2].命令行輔助工具(qrsctl)
[3].Linux shell 之 提取文件名和目錄名的一些方法
[4].逐行處理文本文件-一點心青-cnblog
[5].shell中的特殊變量IFS- __Cheny-csdn
[6].sanic getting started page
[7].Python3 初學實踐案例(14)打造一個私人圖床服務器-FungLeo-csdn
[8].Python 打造自己的圖床升級篇 - PIL 為圖片添加水印-FungLeo-csdn
[9].nohup和&后台運行,進程查看及終止-彌塵-cnblog


@beautifulzzzz
智能硬件、物聯網,熱愛技術,關注產品
博客:http://blog.beautifulzzzz.com
園友交流群:414948975


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM