析QQ空間
登錄QQ空間
爬取第一步,分析站點(diǎn),首先需要知道如何登錄QQ空間。最初想法是用requests庫配置登錄請(qǐng)求,模擬登錄,但是不久便放棄了這一思路,請(qǐng)看下圖↓
login
根據(jù)登錄按鈕綁定的監(jiān)聽事件可以追蹤到該按鈕的點(diǎn)擊事件如下:
login function
賬號(hào)加密是必然的,但這一堆堆的代碼真心不好解析,有耐心的勇士盡情一試!
在排除這種登錄方法后,選擇selenium模擬用戶登錄不失為省時(shí)省力的方法,而且我們只是需要通過selenium完成登錄,獲取到Cookies和后面講述的g_tk參數(shù)后,就可以停用了,所以效率并不太低。
分析空間相冊(cè)
登錄以后,頁面會(huì)跳轉(zhuǎn)至 [https://user.qzone.qq.com/{QQ_NUMBER}](javascript:;), 這時(shí)把鼠標(biāo)移到導(dǎo)航欄你會(huì)發(fā)現(xiàn),所有的導(dǎo)航欄鏈接都是javascript:; 。沒錯(cuò)就是這么坑,一切都是暗箱操作。
當(dāng)然這并不難處理,使用調(diào)試工具捕獲點(diǎn)擊后產(chǎn)生的請(qǐng)求,然后過濾出正確的請(qǐng)求包即可。因?yàn)榫W(wǎng)絡(luò)包非常多,那么怎么過濾呢,猜想相冊(cè)數(shù)據(jù)的API必然會(huì)返回個(gè)列表list,嘗試過濾list然后逐個(gè)排除,最后定位到請(qǐng)求包。下面是通過fcg_list過濾后的數(shù)據(jù)包,列表信息以jsonp格式返回,稍作處理即可當(dāng)做json格式來讀取(后面有講)。
album list
從Headers和Response可以分別獲取到兩組重要信息:
先看請(qǐng)求包:
# url https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3 # args g_tk: 477819917 callback: shine0_Callback t: 691481346 hostUin: 123456789 uin: 123456789 appid: 4 inCharset: utf-8 outCharset: utf-8 source: qzone plat: qzone format: jsonp notice: 0 filter: 1 handset: 4 pageNumModeSort: 40 pageNumModeClass: 15 needUserInfo: 1 idcNum: 4 callbackFun: shine0 _: 1551788226819
其中hostUin, uin都是QQ號(hào),g_tk是必須的且每次重新登錄都會(huì)更新(后面有講如何獲取),其它有些參數(shù)不是必須的,我嘗試后整理出如下請(qǐng)求參數(shù):
query = { 'g_tk': self.g_tk, 'hostUin': self.username, 'uin': self.username, 'appid': 4, 'inCharset': 'utf-8', 'outCharset': 'utf-8', 'source': 'qzone', 'plat': 'qzone', 'format': 'jsonp' }
接下來看jsonp格式的跨域響應(yīng)包:
shine0_Callback({ "code":0, "subcode":0, "message":"", "default":0, "data": { "albumListModeSort" : [ { "allowAccess" : 1, "anonymity" : 0, "bitmap" : "10000000", "classid" : 106, "comment" : 11, "createtime" : 1402661881, "desc" : "", "handset" : 0, "id" : "V13LmPKk0JLNRY", "lastuploadtime" : 1402662103, "modifytime" : 1408271987, "name" : "畢業(yè)季", "order" : 0, "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA", "priv" : 1, "pypriv" : 1, "total" : 4, "viewtype" : 0 },
shine0_Callback是請(qǐng)求包的callbackFun參數(shù)決定的,如果沒這個(gè)參數(shù),響應(yīng)包會(huì)以_Callback作為默認(rèn)名,當(dāng)然這都不重要。所有相冊(cè)信息以json格式存入albumListModeSort中,上面僅截取了一個(gè)相冊(cè)的信息。
相冊(cè)信息中,name代表相冊(cè)名稱,id作為唯一標(biāo)識(shí)可用于請(qǐng)求該相冊(cè)內(nèi)的照片信息,而pre僅僅是一個(gè)預(yù)覽縮略圖的鏈接,無關(guān)緊要。
分析單個(gè)相冊(cè)
與獲取相冊(cè)信息類似,進(jìn)入某一相冊(cè),使用cgi_list過濾數(shù)據(jù)包,找到該相冊(cè)的照片信息
photo list
同樣的道理,根據(jù)數(shù)據(jù)包可以獲取照片列表信息的請(qǐng)求包和響應(yīng)信息,先看請(qǐng)求:
# url https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo # args g_tk: 477819917 callback: shine0_Callback t: 952444063 mode: 0 idcNum: 4 hostUin: 123456789 topicId: V13LmPKk0JLNRY noTopic: 0 uin: 123456789 pageStart: 0 pageNum: 30 skipCmtCount: 0 singleurl: 1 batchId: notice: 0 appid: 4 inCharset: utf-8 outCharset: utf-8 source: qzone plat: qzone outstyle: json format: jsonp json_esc: 1 question: answer: callbackFun: shine0 _: 1551790719497
其中有幾個(gè)關(guān)鍵參數(shù):
為了一次性獲取所有照片,可以將pageStart設(shè)為0,pageNum設(shè)為所有相冊(cè)所含照片的最大值。
同樣可以對(duì)上面的參數(shù)進(jìn)行簡(jiǎn)化,在相冊(cè)列表請(qǐng)求參數(shù)的基礎(chǔ)上添加topicId,pageStart和pageNum三個(gè)參數(shù)即可。
下面來看返回的照片列表信息:
shine0_Callback({ "code":0, "subcode":0, "message":"", "default":0, "data": { "limit" : 0, "photoList" : [ { "batchId" : "1402662093402000", "browser" : 0, "cameratype" : " ", "cp_flag" : false, "cp_x" : 455, "cp_y" : 388, "desc" : "", "exif" : { "exposureCompensation" : "", "exposureMode" : "", "exposureProgram" : "", "exposureTime" : "", "flash" : "", "fnumber" : "", "focalLength" : "", "iso" : "", "lensModel" : "", "make" : "", "meteringMode" : "", "model" : "", "originalTime" : "" }, "forum" : 0, "frameno" : 0, "height" : 621, "id" : 0, "is_video" : false, "is_weixin_mode" : 0, "ismultiup" : 0, "lloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "modifytime" : 1402661792, "name" : "QQ圖片20140612104616", "origin" : 0, "origin_upload" : 0, "origin_url" : "", "owner" : "123456789", "ownername" : "123456789", "photocubage" : 91602, "phototype" : 1, "picmark_flag" : 0, "picrefer" : 1, "platformId" : 0, "platformSubId" : 0, "poiName" : "", "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/a\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!", "raw" : "http:\/\/r.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/r\/dIY29GUbJgAA", "raw_upload" : 1, "rawshoottime" : 0, "shoottime" : 0, "shorturl" : "", "sloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "tag" : "", "uploadtime" : "2014-06-13 20:21:33", "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/b\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!", "width" : 932, "yurl" : 0 }, // ... ] "t" : "952444063", "topic" : { "bitmap" : "10000000", "browser" : 0, "classid" : 106, "comment" : 1, "cover_id" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "createtime" : 1402661881, "desc" : "", "handset" : 0, "id" : "V13LmPKk0JLNRY", "is_share_album" : 0, "lastuploadtime" : 1402662103, "modifytime" : 1408271987, "name" : "畢業(yè)季", "ownerName" : "707922098", "ownerUin" : "707922098", "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA", "priv" : 1, "pypriv" : 1, "share_album_owner" : 0, "total" : 4, "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/b\/dIY29GUbJgAA", "viewtype" : 0 }, "totalInAlbum" : 4, "totalInPage" : 4 }
返回的照片信息都存于photoList, 上面同樣只截取了一張照片的信息,后面一部分返回的是當(dāng)前相冊(cè)的一些基本信息。totalInAlbum, totalInPage存儲(chǔ)了當(dāng)前相冊(cè)總共包含的照片數(shù)及本次返回的照片數(shù)。而我們需要下載的圖片鏈接則是url!
OK, 到此,所有請(qǐng)求和響應(yīng)數(shù)據(jù)都分析清楚了,接下來便是coding的時(shí)候了。
確定爬取方案
創(chuàng)建qqzone類
class qqzone(object): """QQ空間相冊(cè)爬蟲""" def __init__(self, user): self.username = user['username'] self.password = user['password']
模擬登錄
from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import WebDriverExceptio # ... def _login_and_get_args(self): """登錄QQ,獲取Cookies和g_tk""" opt = webdriver.ChromeOptions() opt.set_headless() driver = webdriver.Chrome(chrome_options=opt) driver.get('https://i.qq.com/') # time.sleep(2) logging.info('User {} login...'.format(self.username)) driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() driver.find_element_by_id('u').clear() driver.find_element_by_id('u').send_keys(self.username) driver.find_element_by_id('p').clear() driver.find_element_by_id('p').send_keys(self.password) driver.find_element_by_id('login_button').click() time.sleep(1) driver.get('https://user.qzone.qq.com/{}'.format(self.username))
此處需要注意的是:
獲取 Cookies
使用selenium獲取Cookies非常方便
self.cookies = driver.get_cookies()
獲取 g_tk
獲取g_tk最開始可以說是本爬蟲最大的難點(diǎn),因?yàn)閺木W(wǎng)頁中根本找不到直接寫明的數(shù)值,只有各種函數(shù)調(diào)用。為此我全局搜索,發(fā)現(xiàn)好多地方都有其獲取方式。
g_tk
最后選擇了其中一處,通過selenium執(zhí)行腳本的功能成功獲取到了g_tk!
self.g_tk = driver.execute_script('return QZONE.FP.getACSRFToken()')
到此,selenium的使命就完成了,剩下的將通過requests來完成。
初始化 request.Session
接下來需要逐步生成請(qǐng)求然后獲取數(shù)據(jù)。但是為方便起見,這里使用會(huì)話的方式請(qǐng)求數(shù)據(jù),配置好cookie和headers,省的每次請(qǐng)求都設(shè)置一遍。
def _init_session(self): self.session = requests.Session() for cookie in self.cookies: self.session.cookies.set(cookie['name'], cookie['value']) self.session.headers = { 'Referer': 'https://qzs.qq.com/qzone/photo/v7/page/photo.html?init=photo.v7/module/albumList/index&navBar=1', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36' }
請(qǐng)求相冊(cè)信息
獲取相冊(cè)信息,需要先封裝好請(qǐng)求參數(shù),然后通過session.get爬取數(shù)據(jù),再通過正則匹配以json格式讀取jsonp數(shù)據(jù),最后解析所需的name和id。
def _get_ablum_list(self): """獲取相冊(cè)的列表信息""" album_url = '{}{}'.format( 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3?', self._get_query_for_request()) logging.info('Getting ablum list id...') resp = self.session.get(album_url) data = self._load_callback_data(resp) album_list = {} for item in data['data']['albumListModeSort']: album_list[item['name']] = item['id'] return album_list
其中的參數(shù)組合來自下面的函數(shù)_get_query_for_request函數(shù)。
def _get_query_for_request(self, topicId=None, pageStart=0, pageNum=100): """獲取請(qǐng)求相冊(cè)信息或照片信息所需的參數(shù) Args: topicId: 每個(gè)相冊(cè)對(duì)應(yīng)的唯一標(biāo)識(shí)符 pageStart: 請(qǐng)求某個(gè)相冊(cè)的照片列表信息所需的起始頁碼 pageNum: 單次請(qǐng)求某個(gè)相冊(cè)的照片數(shù)量 Returns: 一個(gè)組合好所有請(qǐng)求參數(shù)的字符串 """ query = { 'g_tk': self.g_tk, 'hostUin': self.username, 'uin': self.username, 'appid': 4, 'inCharset': 'utf-8', 'outCharset': 'utf-8', 'source': 'qzone', 'plat': 'qzone', 'format': 'jsonp' } if topicId: query['topicId'] = topicId query['pageStart'] = pageStart query['pageNum'] = pageNum return '&'.join('{}={}'.format(key, val) for key, val in query.items())
其中的jsonp解析函數(shù)如下,主體部分就是一個(gè)正則匹配,非常簡(jiǎn)單。
def _load_callback_data(self, resp): """以json格式解析返回的jsonp數(shù)據(jù)""" try: resp.encoding = 'utf-8' data = loads(re.search(r'.*?\(({.*}).*?\).*', resp.text, re.S)[1]) return data except ValueError: logging.error('Invalid input')
解析并下載照片
獲取相冊(cè)列表后,逐個(gè)請(qǐng)求照片列表信息,進(jìn)而逐一下載
def _get_photo(self, album_name, album_id): """獲取單個(gè)相冊(cè)的照片列表信息,并下載該相冊(cè)所有照片""" photo_list_url = '{}{}'.format( 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo?', self._get_query_for_request(topicId=album_id)) logging.info('Getting photo list for album {}...'.format(album_name)) resp = self.session.get(photo_list_url) data = self._load_callback_data(resp) if data['data']['totalInPage'] == 0: return None file_dir = self.get_path(album_name) for item in data['data']['photoList']: path = '{}/{}.jpg'.format(file_dir, item['name']) logging.info('Downloading {}-{}'.format(album_name, item['name'])) self._download_image(item['url'], path)
下載圖片也是通過request,記得設(shè)置超時(shí)時(shí)間。
def _download_image(self, url, path): """下載單張照片""" try: resp = self.session.get(url, timeout=15) if resp.status_code == 200: open(path, 'wb').write(resp.content) except requests.exceptions.Timeout: logging.warning('get {} timeout'.format(url)) except requests.exceptions.ConnectionError as e: logging.error(e.__str__) finally: pass
爬取測(cè)試
capturing
downloaded photos
寫在最后
前段時(shí)間小編刷抖音的時(shí)候,刷到了咱們前端小伙伴制作的3D炫酷相冊(cè),居然那么火,細(xì)思一下,隨著3D動(dòng)畫的普及,廣泛的運(yùn)作在各個(gè)平臺(tái),各官網(wǎng)都在實(shí)現(xiàn)3D頁面。它可以更接近于真實(shí)的展示我們的產(chǎn)品和介紹,帶來極強(qiáng)的視覺沖擊感。所以說,為了讓自己更加優(yōu)秀,css3 3D動(dòng)畫必不可少。下面這篇文章,將帶你初步了解CSS3實(shí)現(xiàn)酷炫的3D旋轉(zhuǎn)透視
要想自己的網(wǎng)頁能有3D特效,必須要會(huì)透視。
透視 perspective(基礎(chǔ)問題,可以在我的推薦書籍中學(xué)習(xí)到)
圖片來源網(wǎng)絡(luò)
1.CSS3 3D 轉(zhuǎn)換的常用API介紹
首先先上一張css 3D的坐標(biāo)系:
接下來我們來介紹幾個(gè)常用的api:
旋轉(zhuǎn)
相關(guān)代碼如下:
<style> .d3-wrap { position: relative; width: 300px; height: 300px; margin: 120px auto; /* 規(guī)定如何在 3D 空間中呈現(xiàn)被嵌套的元素 */ transform-style: preserve-3d; transform: rotateX(0) rotateY(45deg); transform-origin: 150px 150px 150px; } .rotateX { width: 200px; height: 200px; background-color: #06c; transition: transform 2s; animation: rotateX 6s infinite; } @keyframes rotateX { 0% { transform: rotateX(0); } 100% { transform: rotateX(360deg); } } </style> <div class="d3-wrap"> <div class="rotateX"></div> </div> 復(fù)制代碼
位移(Transform)
這里我們需要注意的是為了能看出位移的效果,我們需要在父容器上加如下屬性:
.d3-wrap { transform-style: preserve-3d; perspective: 500; /* 設(shè)置元素被查看位置的視圖 */ -webkit-perspective: 500; }
當(dāng)為元素定義 perspective 屬性時(shí),其子元素會(huì)獲得透視效果,而不是元素本身。 代碼如下:
.d3-wrap { position: relative; width: 300px; height: 300px; margin: 120px auto; transform-style: preserve-3d; perspective: 500; -webkit-perspective: 500; transform: rotateX(0) rotateY(45deg); transform-origin: center center; } .transformZ { width: 200px; height: 200px; background-color: #06c; transition: transform 2s; animation: transformZ 6s infinite; } @keyframes transformZ { 0% { transform: translateZ(100px); } 100% { transform: translateZ(0); } }
3D縮放
理論上說以上三種常見變換已經(jīng)夠用了,值得關(guān)注的是我們要想讓元素呈現(xiàn)出3D效果,以下不可忽視的API也很重要:
2.CSS3 3D 應(yīng)用場(chǎng)景
css 3D主要應(yīng)用在網(wǎng)站的交互和模型效果上,比如:
3.CSS3 3D 實(shí)現(xiàn)一個(gè)立方體
核心思路就是用6個(gè)面去拼接,通過設(shè)置rotate和translate來調(diào)整相互之間的位置,如下:
具體代碼如下:
.container { position: relative; width: 300px; height: 300px; margin: 120px auto; transform-style: preserve-3d; /* 為了讓其更有立體效果 */ transform: rotateX(-30deg) rotateY(45deg); transform-origin: 150px 150px 150px; animation: rotate 6s infinite; } .container .page { position: absolute; width: 300px; height: 300px; text-align: center; line-height: 300px; color: #fff; background-size: cover; } .container .page:first-child { background-image: url(./my.jpeg); background-color: rgba(0,0,0,.2); } .container .page:nth-child(2) { transform: rotateX(90deg); transform-origin: 0 0; transition: transform 10s; background-color: rgba(179, 15, 64, 0.6); background-image: url(./my2.jpeg); } .container .page:nth-child(3) { transform: translateZ(300px); background-color: rgba(22, 160, 137, 0.7); background-image: url(./my3.jpeg); } .container .page:nth-child(4) { transform: rotateX(-90deg); transform-origin: -300px 300px; background-color: rgba(210, 212, 56, 0.2); background-image: url(./my4.jpeg); } .container .page:nth-child(5) { transform: rotateY(-90deg); transform-origin: 0 0; background-color: rgba(201, 23, 23, 0.6); background-image: url(./my5.jpeg); } .container .page:nth-child(6) { transform: rotateY(-90deg) translateZ(-300px); transform-origin: 0 300px; background-color: rgba(16, 149, 182, 0.2); background-image: url(./my6.jpeg); }
html結(jié)構(gòu)
<div class="container"> <div class="page">A</div> <div class="page">B</div> <div class="page">C</div> <div class="page">D</div> <div class="page">E</div> <div class="page">F</div> </div>
擴(kuò)展
我們可以基于上面介紹的,給父元素添加動(dòng)畫或者拖拽效果,這樣就可以做成更有交互性的3D方塊了,比如置骰子游戲,vr場(chǎng)景,3D相冊(cè)等等,具體實(shí)現(xiàn)我會(huì)抽空依次總結(jié)出來,記得關(guān)注哦~
作者:徐小夕_Lab實(shí)驗(yàn)室
鏈接:https://juejin.im/post/5dd16b39f265da0bca78958e
喜歡小編的可以點(diǎn)個(gè)贊關(guān)注小編哦,小編每天都會(huì)給大家分享文章。
我自己是一名從事了多年的前端老程序員,小編為大家準(zhǔn)備了新出的前端編程學(xué)習(xí)資料,免費(fèi)分享給大家!
如果你也想學(xué)習(xí)前端,那么幫忙轉(zhuǎn)發(fā)一下然后再關(guān)注小編后私信【1】可以得到我整理的這些前端資料了(私信方法:點(diǎn)擊我頭像進(jìn)我主頁有個(gè)上面有個(gè)私信按鈕)
這是一款基于 PHP + MySQL 的開源項(xiàng)目,選定本地電腦的圖庫目錄之后,就能變成一個(gè)很漂亮的相冊(cè)網(wǎng)頁,并且可以通過分類、標(biāo)簽、顏色、鏈接、注釋、時(shí)長(zhǎng)、尺寸等參數(shù)檢索內(nèi)容,支持預(yù)覽圖片、視頻、音頻,甚至 txt 文檔 。
官方提供了一個(gè)演示站點(diǎn):http://pichome.oaooa.com/
可以輕松地放大縮小、翻轉(zhuǎn)鏡像查看,并且可以查看和下載原圖,全憑之后可以通過左右鍵來瀏覽內(nèi)容,可播放視頻、音頻,最有用的就是搜索功能了,找圖快才用的爽。
基于 PHP + MySQL 環(huán)境則可以部署在各種設(shè)備中,比如服務(wù)器、NAS、個(gè)人電腦、云服務(wù)器等,部署后可以在任何瀏覽器打開,所以手機(jī)電腦都可以方便的訪問,最重要的是免費(fèi)、開源,還是相當(dāng)不錯(cuò)的。
官方安裝部署文檔: https://www.yuque.com/pichome/install
本次采用nginx+php7搭建
Gitee下載 https://gitee.com/zyx0814/Pichome/releases
下載安裝包:筆者這邊下載Pichome-beta3.3.tar.gz。
github下載 https://github.com/zyx0814/Pichome/releases
國內(nèi)使用gitee地址
https://gitee.com/zyx0814/Pichome/releases
備用下載: http://js.funet8.com/centos_software/Pichome-beta3.3.tar.gz
cd /data/wwwroot/web
wget http://js.funet8.com/centos_software/Pichome-beta3.3.tar.gz
tar -zxvf Pichome-beta3.3.tar.gz
mv Pichome-beta3.3 p.xgss.net
nginx的配置
server {
listen 80;
server_name p.xgss.net;
root /data/wwwroot/web/p.xgss.net;
access_log /data/wwwroot/log/p.xgss.net-access.log main_aliyun;
error_log /dev/null;
location / {
index index.php index.htm index.html;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last;
}
}
location ~ .*\.(php|php5)?$ {
fastcgi_pass 127.0.0.1:7300;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ .*\.(css|js|jpg|jpeg|gif|png|ico|bmp|gz|xml|zip|rar|swf|txt|xls|xlsx|flv|mid|doc|ppt|pdf|mp3|wma|exe)?$ {
expires max;
access_log off;
}
}
域名解析到服務(wù)器
訪問: http://p.xgss.net/
新建數(shù)據(jù)庫用戶
分配權(quán)限
參考文檔
官網(wǎng):https://oaooa.com/pichome.html
開發(fā)者提供了 Windows、Linux 以及 Docker 安裝方式。
使用Eagle或者Billfish,在本地windows系統(tǒng)下安裝Billfish素材管理工具,billfish為免費(fèi)的。
在billfish軟件中將照片分類
將目錄上傳到服務(wù)器中,庫設(shè)置中添加目錄,就可以在web頁面中顯示你的圖片了。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。