華(hua)為(wei)云照片的(de)爬蟲程序更新(python3.6)
一、背景:
每(mei)年終都有一個習慣,就是整(zheng)理(li)資料進行歸檔,結果發現(xian)手(shou)機照(zhao)(zhao)片全備份在華為(wei)云里,在官網上找了(le)一圈(quan),沒找到官方的pc工具(ju)用來同步照(zhao)(zhao)片。
于是找出上次寫的程(cheng)序,看(kan)看(kan)能(neng)不(bu)能(neng)爬(pa)到數據,然而……果(guo)然不(bu)好(hao)用。因為(wei)華(hua)為(wei)在登錄(lu)上又增(zeng)加(jia)了一些(xie)驗(yan)證(zheng)機制,譬如:賬號保(bao)護

抓了一(yi)下報文,發現邏(luo)輯變復雜了很多,部分邏(luo)輯還封裝在js里。
算了,懶(lan)得琢磨了,直接用(yong)selenium吧。
二、實現思路:
1、用Python + selenium +瀏覽器 ,人工登錄,保存cookie及簽名信息。
2、再調用requests加第一步保(bao)存的cookie和前(qian)面(mian),直(zhi)接向后臺發(fa)post請求,獲取數據。
思路確定,開干。
三、開發環境:
1、python3.6,在(zai)(zai)最近的一個項目中由(you)于多(duo)次遇到中文問題,實(shi)在(zai)(zai)是煩不(bu)勝煩,所以就把開發工具升級到了py3,確實(shi)方便(bian)多(duo)了。
說(shuo)到py2升到py3,雖然還是有些寫法調整,有些包在py3下不(bu)支持,但總體來說(shuo),遷移很平穩,寫法問題,百(bai)度一下基本就可以解決(jue)。
我用的Anaconda的python包。
3.6.3 |Anaconda custom (64-bit)| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] Python Type "help", "copyright", "credits" or "license" for more information.
2、selenium 3.9.0,用conda現安裝的。
conda install selenium
3、瀏覽(lan)器,試用(yong)了(le)firefox,edge,chrome,phantomjs,分別版本如(ru)下(xia):
firefox: 58.0.2 (64 位) edge: Microsoft Edge 41.16299.248.0 ,Microsoft Edge 41.16299.248.0 chrome: 版(ban)本 63.0.3239.132(正式版本) (32 位) phantomjs: 2.1.1 另(ling)外,操作(zuo)系統:Microsoft Windows [版本 10.0.16299.248]
4、瀏覽器驅動:
firefox驅動,//github.com/mozilla/geckodriver/releases/,支持 Firefox 55及以上版本(ben)。
edge驅動,//developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads,最新版本 Release 16299,Version: 5.16299,支持 Edge version supported: 16.16299 。注意(yi)edge驅動只(zhi)有在edge瀏覽(lan)器未啟動的情況(kuang)下才能正常運行,否則會(hui)報(bao)錯(cuo)。
chrome驅動,//sites.google.com/a/chromium.org/chromedriver/downloads,這里需要注意的是(shi):最新版本是(shi)2.35(不是(shi)2.9),2.35才支持(chi)chrome 61-63版本。
phantomjs,//phantomjs.org/download.html,phantomjs可以(yi)理解成沒(mei)有界(jie)面的瀏(liu)覽(lan)器,所以(yi)驅動跟瀏(liu)覽(lan)器是(shi)一(yi)體的。
驅動版本(ben)一(yi)定要選對,否則會有奇(qi)奇(qi)怪怪的(de)問題。
四、實現代碼
huaweiphoto_sele.py,如下:
#-*-coding=utf-8-*- #Create by : zhongtang #Create Date : 2018.2.28 from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.proxy import ProxyType from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from PIL import Image import json,re,os,time,requests,socket #下載函數(shu) from huaweiphoto_py3 import HuaWei class hwSele: SeleBrowser=None TimeOUT=30 Headers=None Username='*****' Passwd='****' DriverType="Edge".lower() def __init__(self,ip=None,port=None,SeleDriver="Edge",SeleHeader=None): print (u'proxy %s %s...' %(ip,port)) if not SeleHeader : self.Headers = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0" else: self.Headers = SeleHeader if SeleDriver: self.DriverType= SeleDriver.lower() #加代理(li)的目的是為(wei)了更便于抓報文。 if self.DriverType=='chrome' : chromeOptions = webdriver.ChromeOptions() if ip: chromeOptions.add_argument('--proxy-server=//%s:%s' %(ip,port)) self.SeleBrowser = webdriver.Chrome(chrome_options=chromeOptions) else: self.SeleBrowser = webdriver.Chrome() #DriverType='Edge' elif self.DriverType=='phantomjs': #設(she)置(zhi)userAgent dcap = dict(DesiredCapabilities.PHANTOMJS) dcap["phantomjs.page.settings.userAgent"] = (self.Headers) self.SeleBrowser = webdriver.PhantomJS(executable_path=r'D:\python\toupiao\phantomjs\bin\phantomjs.exe',desired_capabilities=dcap) if ip: proxy=webdriver.Proxy() proxy.proxy_type=ProxyType.MANUAL proxy.http_proxy='%s:%s' %(ip,port) proxy.add_to_capabilities(webdriver.DesiredCapabilities.PHANTOMJS) else: self.SeleBrowser.start_session(webdriver.DesiredCapabilities.PHANTOMJS) elif self.DriverType=='edge': self.KillSeleProc() #edge,默認先kill掉(diao)已啟動的(de)瀏覽器。 self.SeleBrowser = webdriver.Edge() elif self.DriverType=='firefox': webdriver.DesiredCapabilities.FIREFOX['firefox.page.settings.userAgent'] = self.Headers profile = webdriver.FirefoxProfile() if ip: profile.set_preference('network.proxy.type', 1) # 默認值0,就是直接(jie)連接(jie);1就是手工配置(zhi)代理。 profile.set_preference('network.proxy.http', ip) profile.set_preference('network.proxy.http_port', port) profile.set_preference('network.proxy.ssl', ip) profile.set_preference('network.proxy.ssl_port', port) profile.update_preferences() self.SeleBrowser = webdriver.Firefox(profile) else: self.SeleBrowser = webdriver.Firefox() socket.setdefaulttimeout(self.TimeOUT) # 設(she)置(zhi)10秒頁面超(chao)時(shi)返回,類似于requests.get()的timeout選項,driver.get()沒(mei)有timeout選項 # 以前遇到過driver.get(url)一直不(bu)返回,但也不(bu)報錯的問(wen)題,這(zhe)時程序會卡住,設置(zhi)超時選(xuan)項(xiang)能解決這(zhe)個問(wen)題。 self.SeleBrowser.set_page_load_timeout(self.TimeOUT) # 設(she)置10秒腳本超時時間 self.SeleBrowser.set_script_timeout(self.TimeOUT) # 隱式等待(dai)30秒,可(ke)以自(zi)己調節(jie) self.SeleBrowser.implicitly_wait(self.TimeOUT) def KillSeleProc(self): if self.DriverType=='edge': command = 'taskkill /F /IM MicrosoftWebDriver.exe & taskkill /F /IM MicrosoftEdge.exe' #比(bi)如這里關(guan)閉edge進程(cheng) elif self.DriverType=='chrome': command = 'taskkill /F /IM chromedriver.exe & taskkill /F /IM chrome.exe' elif self.DriverType=='firefox': command = 'taskkill /F /IM geckodriver.exe & taskkill /F /IM firefox.exe' elif self.DriverType=="phantomjs": command = 'taskkill /F /IM phantomjs.exe ' if command: os.system(command) def QuitSele(self,e,mess=None,iRet= -1): print (mess,e) if self.SeleBrowser: self.SeleBrowser.save_screenshot('error.png') self.SeleBrowser.close() self.KillSeleProc() return iRet def LoginHW(self): ''' try: element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "loadedButton"))) finally: print(driver.find_element_by_id("content").text) driver.close() #等待(dai)頁(ye)面加載(zai)完畢(bi)1,顯示等待(dai) try: auth_img = WebDriverWait(self.SeleBrowser, 5).until(EC.presence_of_element_located((By.ID, "randomCodeImg"))) except Exception as e: print (u'加載(zai)驗證碼超時(shi)...',e) SeleBrowser.save_screenshot(r'd:\python\toupiao\error.jpg') self.SeleBrowser.close() return -1 #等待(dai)頁(ye)面加載(zai)完畢(bi)2,隱式等待(dai) dr=WebDriverWait(self.SeleBrowser,20,0.5) dr.until(lambda the_driver:the_driver.find_element_by_xpath("//img[@id='randomCodeImg']").is_displayed()) ''' try: self.SeleBrowser.get('//cloud.huawei.com') except Exception as e: return self.QuitSele(e,"打開主(zhu)頁出錯!") try: #等待頁面加載完畢(bi) dr=WebDriverWait(self.SeleBrowser,self.TimeOUT,0.5) dr.until(lambda the_driver:the_driver.find_element_by_id("randomCodeImg").is_displayed()) except Exception as e: return self.QuitSele(e,"加載(zai)驗證(zheng)碼超時!") elem_user = self.SeleBrowser.find_element_by_id("login_userName") elem_user.clear() elem_user.send_keys(self.Username) elem_pwd = self.SeleBrowser.find_element_by_id("login_password") elem_pwd.clear() elem_pwd.send_keys(self.Passwd) auth_img = self.SeleBrowser.find_element_by_id("randomCodeImg") if not auth_img.is_displayed() : if not auth_img.is_displayed(): return self.QuitSele(e,"驗證(zheng)碼未正常顯(xian)示!") if self.DriverType=='firefox': #firefox驅動支持直接 元素另存圖片 auth_img.screenshot("captcha.png") im = Image.open('captcha.png') else: #chrome ,edge 都不支(zhi)持,phantomjs存的(de)還是整個窗口(kou) self.SeleBrowser.save_screenshot('captcha.png') im = Image.open('captcha.png') x= y= width= height= im = im.crop((x, y, x+width, y+height)) #這里采(cai)用最原(yuan)始、最準(zhun)確的方法:顯(xian)示(shi)圖片,人工(gong)識別^_^,智能輸(shu)入驗證碼。 #當然也可以調(diao)用三方的圖像識(shi)別api進行識(shi)別,譬如pytesseract或者鵝廠的圖像識(shi)別api,不復雜(za),但懶得寫了。 im.show() authCode= input(u'請輸入(ru)驗證碼(ma):') # 先(xian)獲取(qu)焦點,再(zai)賦值,再(zai)點擊登錄 ''' js= '$("#randomCode").attr("value","%s");$("#randomCode").trigger("onchange");' %authCode self.SeleBrowser.execute_script(js) js= '$("#btnLogin").trigger("click");' self.SeleBrowser.execute_script(js) ''' randomCode = self.SeleBrowser.find_element_by_id("randomCode") randomCode.clear() randomCode.send_keys(authCode) #休息(xi)五秒,等待完(wan)成后臺(tai)預驗證(zheng)交互 time.sleep(5) btnLogin = self.SeleBrowser.find_element_by_id("btnLogin") btnLogin.click() #賬號保(bao)護有時候會提(ti)示 ''' <div class="global_dialog_confirm_main" style="display: block; margin-top: -163.5px;"> <div class="global_dialog_confirm_title"> <h3 class="ellipsis" title="帳(zhang)號(hao)保(bao)護(hu)(hu)">帳(zhang)號(hao)保(bao)護(hu)(hu)</h3> </div> <div class="global_dialog_confirm_content" style="padding-bottom: 0px;"><div> <div id="authenDialog"><p class="inptips2">您已開啟帳(zhang)號(hao)保(bao)護(hu)(hu),請(qing)輸入驗證碼以完成登錄。</p> <div class="margin10-EMUI5"><div id="accountDiv" class="fixAccountDrt ddrop-EMU5"> ''' try : #loginConfirm = self.SeleBrowser.find_element_by_class_name("global_dialog_confirm_main") loginConfirm =WebDriverWait(self.SeleBrowser, 5, 0.5).until(EC.presence_of_element_located((By.CLASS_NAME, 'global_dialog_confirm_main') )) #需要驗證,這塊懶得實現(xian)了,休眠60秒,手動操作吧。 if loginConfirm.is_displayed(): time.sleep(self.TimeOUT*2) except: #不需要驗證,直接下一(yi)步 pass #等待頁面加載完畢 ''' <span class="index-span" data-bind="lang.common.album">圖(tu)庫</span> ''' try : #loginConfirm = self.SeleBrowser.find_element_by_class_name("global_dialog_confirm_main") success =WebDriverWait(self.SeleBrowser, 20, 0.5).until(EC.presence_of_element_located((By.XPATH, '//span[@data-bind="lang.common.album"]') )) except Exception as e: #登錄失敗 return self.QuitSele(e,"登錄(lu)失(shi)敗!",iRet=-999) #判斷登(deng)錄結果 if not success.is_displayed(): return self.QuitSele(None,"登錄失敗(bai)!",iRet=-999) #再次判斷,增(zeng)加(jia)一次意外處理 source_code =self.SeleBrowser.page_source if '聯(lian)系人' not in source_code or '圖庫' not in source_code : return self.QuitSele(None,"登錄(lu)失敗!",iRet = -9999 ) cookie = [item["name"] + "=" + item["value"] for item in self.SeleBrowser.get_cookies()] cookiestr = ';'.join(item for item in cookie) #保存CSRFToken pattern = re.compile('CSRFToken = "(.*?)"',re.S) content = re.search(pattern,source_code) if content : CSRFToken = content.group(1) else : print ('獲取(qu)CSRFToken出錯(cuo)!') self.Headers={ 'User-Agent': '%s' %self.Headers, 'CSRFToken': '%s' %CSRFToken, 'Cookie': '%s' %cookiestr } return 1 if __name__ == '__main__': photohw= HuaWei() count =0 while (count <100): count += 1 selehw= hwSele(SeleDriver='edge') iRet = selehw.LoginHW() if iRet !=1: print( '登(deng)錄華為失敗!!!\n\n') continue photohw.loginHeaders = selehw.Headers page = photohw.getAlbumList() if page=='' : print( '獲(huo)取到(dao)相冊列表(biao)失(shi)敗!!!\n\n') break #保存相冊列表 iRet = photohw.getFileList(page,'albumList','albumId') if iRet <=0 : print('保(bao)存(cun)相冊出錯,重新登(deng)錄') continue #保存公(gong)共相(xiang)冊列表 iRet = photohw.getFileList(page,'ownShareList','shareId') if iRet ==0 : print('運(yun)行結束,可以用迅(xun)雷(lei)打(da)開相冊文件(jian)進(jin)行批量(liang)下(xia)載(zai)到本(ben)地(di)!!!\n\n') #運行結束 selehw.QuitSele(None) break else: continue
huaweiphoto_py3.py如(ru)下:
# -*- coding=utf-8 -*- # Create by : zhongtang # Create date : 2018.2.28 import json import requests from requests.adapters import HTTPAdapter import html class HuaWei: #華(hua)為云服務登錄(lu) def __init__(self): self.getalbumsUrl= '//www.hicloud.com/album/getCloudAlbums.action' self.getalbumfileUrl = '//www.hicloud.com/album/getCloudFiles.action' self.loginHeaders = { } self.SReq=requests.session() self.SReq.mount('//', HTTPAdapter(max_retries=3)) self.SReq.mount('//', HTTPAdapter(max_retries=3)) self.OnceMaxFile=100 #單次最大獲取文件數量 self.FileNum=0 self.AlbumList={} #保存(cun)相冊照(zhao)片地(di)址到文件(jian) ,不同相冊保存(cun)到不同的文件(jian) def saveFileList2Txt(self,filename,hjsondata,flag): if len(hjsondata)<= 0 : return -1 hjson2 = {} try: hjson2 = json.loads(hjsondata) except: print('獲(huo)取相冊(ce)明細出錯(cuo)\n') return -1 lfilename = filename+u".txt" if flag == 0 : #新建文件 print( u'創(chuang)建相(xiang)冊(ce)文件'+lfilename+"\n") #新(xin)(xin)建文件,代(dai)表新(xin)(xin)的相(xiang)冊(ce)重新(xin)(xin)開始計數 self.FileNum = 0 f = open(lfilename, 'w') else: #追加文件 f = open(lfilename, 'a') i = 0 if hjson2.get("fileList"): for each in hjson2["fileList"]: fileurl= html.unescape(hjson2["fileList"][i]["fileUrl"]) f.write(fileurl+"\n") #每一千行分(fen)頁 self.FileNum += 1 if self.FileNum%1000 ==0 :f.write('\n\n\n\n\n\n--------------------page %s ------------------\n\n\n\n\n\n' %(int(self.FileNum/1000))) i += 1 f.close() return i #循環(huan)讀取相(xiang)冊文件(jian) def getFileList(self,hjsondata,parentkey,childkey): #step 3 getCoverFiles.action,循環取相冊文件列(lie)表,單(dan)次最(zui)多取100條記錄。 #每次count都是(shi)最大數(shu)量49,不管實際數(shu)量是(shi)否夠,每次currentnum遞(di)增,直到返回空列表。 #albumIds[]=default-album-2&ownerId=220086000029851117&height=300&width=300&count=49¤tNum=0&thumbType=imgcropa&fileType=0 #albumIds[]=default-album-1&ownerId=220086000029851117&height=300&width=300&count=49¤tNum=49&thumbType=imgcropa&fileType=0 #albumIds[]=default-album-1&ownerId=220086000029851117&height=300&width=300&count=49¤tNum=98&thumbType=imgcropa&fileType=0 #albumIds[]=default-album-2&ownerId=220086000029851117&height=300&width=300&count=49¤tNum=101&thumbType=imgcropa&fileType=0 #最后一次返(fan)回 空列表(biao) #{"albumSortFlag":true,"code":0,"info":"success!","fileList":[]} #第一次取文(wen)件時,例如文(wen)件總(zong)數量只有(you)2個(ge),count也是放最大值(zhi)49。 #albumIds[]=default-album-102-220086000029851117&ownerId=220086000029851117&height=300&width=300&count=49¤tNum=0&thumbType=imgcropa&fileType=0 #[{u'photoNum': 2518, u'albumName': u'default-album-1', u'iversion': -1, u'albumId': u'default-album-1', u'flversion': -1, u'createTime': 1448065264550L, u'size': 0}, #{u'photoNum': 100, u'albumName': u'default-album-2', u'iversion': -1, u'albumId': u'default-album-2', u'flversion': -1, u'createTime': 1453090781646L, u'size': 0}] try: hjson = json.loads(hjsondata) except Exception: print ('加載json出錯!') return -1 #字典獲取出錯(cuo) if not hjson.get(parentkey): print ('加載json根節點[%s]出錯!' %parentkey) return -1 #初(chu)始(shi)化全局 albumlist if not self.AlbumList : self.AlbumList=hjson for idx,album in enumerate(self.AlbumList[parentkey]): if 'currentNum' not in self.AlbumList[parentkey][idx].keys(): self.AlbumList[parentkey][idx]['currentNum']=0 #循環保(bao)存相冊 for each in hjson[parentkey]: #該(gai)相(xiang)冊(ce)已(yi)經進入記錄 paraAlbum={} paraAlbum['albumIds[]'] = each[childkey] paraAlbum['ownerId'] = hjson['ownerId'] paraAlbum['height'] = '300' paraAlbum['width'] = '300' paraAlbum['count'] = self.OnceMaxFile paraAlbum['thumbType'] = 'imgcropa' paraAlbum['fileType'] = '0' itotal= each['photoNum'] #取當前節點的當前記(ji)錄 for idx,album in enumerate(self.AlbumList[parentkey]): if each[childkey]==album[childkey]: icurrentnum = self.AlbumList[parentkey][idx]['currentNum'] break #保存相冊中所有文件(jian) while icurrentnum<itotal: paraAlbum['currentNum'] = icurrentnum response=self.SReq.post(self.getalbumfileUrl,headers=self.loginHeaders,data=paraAlbum,verify=False) page = response.text #保存(cun)下載(zai)(zai)地址到文(wen)本文(wen)件(jian)中,但不下載(zai)(zai)文(wen)件(jian) iret = self.saveFileList2Txt(each[childkey],page,icurrentnum) if iret >0 : self.AlbumList[parentkey][idx]['currentNum'] += iret icurrentnum = self.AlbumList[parentkey][idx]['currentNum'] else: #出錯!!! return -1 return 1 #step 1 getCloudAlbums,取相冊列表 def getAlbumList(self): response=self.SReq.post(self.getalbumsUrl,headers=self.loginHeaders,verify=False) page=response.text '''#返回報(bao)文 {"ownerId":"220086000029851117","code":0, "albumList":[{"albumId":"default-album-1","albumName":"default-album-1","createTime":1448065264550,"photoNum":2521,"flversion":-1,"iversion":-1,"size":0}, {"albumId":"default-album-2","albumName":"default-album-2","createTime":1453090781646,"photoNum":101,"flversion":-1,"iversion":-1,"size":0}], "ownShareList":[{"ownerId":"220086000029851117","resource":"album","shareId":"default-album-102-220086000029851117","shareName":"微信","photoNum":2,"flversion":-1,"iversion":-1,"createTime":1448070407055,"source":"HUAWEI MT7-TL00","size":0,"ownerAcc":"****","receiverList":[]}], "recShareList":[]}' ''' if len(page)<=0 : print( u'取(qu)相冊列表(biao)出錯,無(wu)返回(hui)報文(wen)!!!\n\n') return page
五、運行結果:
程序會(hui)在當前(qian)目錄(lu)生成華為(wei)云相冊照片下(xia)載地址文(wen)件,內容如下(xia):
//d167.g03.dbankcloud.com/file/MDAwMTZBODissQaaaaaaaaaaaaaaaaaaaaQc2CR-znjyRnw../162807b277aaaaaaaaaaaaaaaaaa9ee1/IMG_20170606_141952.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaaWNLIosPR_EKv8VQ..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODhhoFaaaaaaaaaaaaaaaaaaaa7r6jPU67bWTQA../4039a1be5caaaaaaaaaaaaaaaaaac726/IMG_20170605_203519.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaajvduIL8cXufhNhQ..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODgpoWaaaaaaaaaaaaaaaaaaaaaciAQlIVHRbXg../9e336da286aaaaaaaaaaaaaaaaaaf89d/IMG_20170604_171032.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaaThkDgJKHpBtiG5w..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODgUz2aaaaaaaaaaaaaaaaaaaatyFMDr71YpXGg../b3c17582ccaaaaaaaaaaaaaaaaac278b/IMG_20170603_134831.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaaTI_xPSzF_VzUsJA..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODgGfwaaaaaaaaaaaaaaaaaaaad7DLSHH4rwKVA../2722df087baaaaaaaaaaaaaaaaa915e4/IMG_20170603_133833.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaaluTQ8grDHok9BzQ..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODgsrHaaaaaaaaaaaaaaaaaaaatq2yOJ-OnkDtQ../77e0ef0560aaaaaaaaaaaaaaaaa44702/IMG_20170602_183736.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaa20WJbfxn-qoqIeQ..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODiAcDaaaaaaaaaaaaaaaaaaaaEXW-ONoF0Shuw../df033e69ffaaaaaaaaaaaaaaaaa8c1b1/IMG_20170601_185446.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaaxIC-spleDG_xxVg..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODjY8EaaaaaaaaaaaaaaaaaaaaVbr9kC-JU0M8g../d5230d2032aaaaaaaaaaaaaaaaa903b3/IMG_20170601_102059.jpg?key=AWqIQFqVkEaaaaaaaaaaaaaaaaaaaaaa49iM03bK-Cm-Z9g..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
//d167.g03.dbankcloud.com/file/MDAwMTZBODi04Caaaaaaaaaaaaaaaaaaaaaaw41bSNB4pxBw../6ee510e28aaaaaaaaaaaaaaaaa57cb5a/IMG_20170601_102042.jpg?key=AWqIQFqVkaaaaaaaaaaaaaaaaaaaaaaxlapdsHLoRCSITVw..&a=220086000029851117-3da1ab76-92808-5840&nsp_ver=3.0
把上述(shu)下載(zai)鏈(lian)接復制到(dao)迅雷,添(tian)加批量任務就可以下載(zai)圖片到(dao)本地。
以上,-- End --
