如何才能讓你的程序?qū)崿F(xiàn)自動更新?
????當(dāng)我們寫了一個軟件的時候,有時候因為其他地方的調(diào)整,之前的版本已經(jīng)不再適用,而再次發(fā)布,再次分享新軟件的鏈接,對用戶很不友好,這時候就需要給舊版本一個通道,讓它能夠有檢測新版本的功能并且自動升級。

???
?當(dāng)然解決的方法不唯一,我是這么操作的,在每次軟件打開的時候就訪問一個特定的網(wǎng)站,然后獲取它顯示的內(nèi)容,我們把每次更新后的版本都發(fā)布在那個網(wǎng)站上面,當(dāng)舊軟件獲取到了新軟件的信息后,舊提示,有新的軟件升級,然后自動下載到指定的目錄。
????話不多說,干活。我個人來說經(jīng)常把一些東西上傳到藍(lán)奏云上,最主要的原因是它不限速,只需要獲取到藍(lán)奏云的個人主頁,就可以查看發(fā)表了哪些內(nèi)容。
比如:
https://vk666.lanzous.com/b00z8pwpg

????一個軟件的舊版本的名字叫xxx.1.0,而新版本的名字叫xxx.2.0,通過舊軟件提取這個頁面的所有名字,當(dāng)發(fā)現(xiàn)了有大于2.0的版本的時候,就提示用戶,有新的更新了。

url="https://vk666.lanzous.com/b00z8pwpg"headers={??'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36Edg/88.0.705.56',???}res?=?requests.get(url,headers=headers)r=res.textimport?re#用正則表達(dá)式,把后面的版本號提取出來pattern1=re.compile('var?(.+?);')
????這下提示的內(nèi)容有了,就剩自動下載了,拿藍(lán)奏云舉例吧。
怎么才能獲取到軟件名字對應(yīng)的下載鏈接呢。
????在想要獲取鏈接的軟件名字那里右鍵,然后點(diǎn)擊檢查,查看它對應(yīng)的html內(nèi)容,在標(biāo)簽的href下發(fā)現(xiàn)了下載鏈接

就產(chǎn)生了這樣的想法,我們直接用
res = requests.get(url,headers=headers)print(res.text)
????
????這樣獲取頁面的html文本,最后通過各種解析方法,從html里面提取出對應(yīng)的鏈接就行。但是仔細(xì)觀察一下?當(dāng)我們刷新網(wǎng)頁的時候,這里div標(biāo)簽和head都閃了一下,表示有新的內(nèi)容填入。

????
????說明了什么,這個網(wǎng)頁不是一個靜態(tài)的網(wǎng)頁,而是根據(jù)js動態(tài)渲染的一個網(wǎng)頁,如果直爬取靜態(tài)內(nèi)容,肯定獲取不到想要的信息。
????這時候,就可以通過抓包,來看看瀏覽器到底對服務(wù)器進(jìn)行了什么操作,來顯示這些動態(tài)的內(nèi)容呢?打開網(wǎng)絡(luò),發(fā)現(xiàn)了這些信息,逐步排查以后發(fā)現(xiàn)了這樣一個post包。

????查看它的響應(yīng)內(nèi)容,發(fā)現(xiàn)了正是我們想要的內(nèi)容。

????是一個json格式的數(shù)據(jù)包含了id ,name 等。瀏覽器向服務(wù)器提交了這個包,服務(wù)器返回了我們想要的信息。這時候,就想起了用程序模擬這個方式。模擬之前,需要查看到底發(fā)送了什么內(nèi)容。

????經(jīng)過不斷刷新以后,發(fā)現(xiàn)只有t和k是不斷變化的,這個t一看就是時間戳,只剩下k不知t,在網(wǎng)絡(luò)頁面下,Ctrl+f全局搜索k的值,看看它在哪個文件里有一次出現(xiàn)了.最后在這個包里發(fā)現(xiàn)了。

????
????從這個包的返回值里解析出來k的值,然后再把它當(dāng)作數(shù)據(jù),提交到
https://vk666.lanzous.com/filemoreajax.php
就可以獲取想要的信息了。
url="https://vk666.lanzous.com/b00z8pwpg"headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36Edg/88.0.705.56',}res?=?requests.get(url,headers=headers)r=res.textimport?repattern1=re.compile('var?(.+?);')t=pattern1.findall(r)[3]k=pattern1.findall(r)[4]k=k.split("'")[1].split("'")[0]t=t.split("'")[1].split("'")[0]data={'lx':'2','fid':'1387166','uid':'1215702','pg':'1','rep':'0','t':t,'k':k,'up':'1',}url='https://vk666.lanzous.com/filemoreajax.php'res?=?requests.post(url,headers=headers,data=data)data=res.json()data=data['text']
????注意這里的t也必須是從這個包里獲取的t值,是當(dāng)時服務(wù)器的時間戳,而不是本地的時間戳。
???點(diǎn)開詳細(xì)頁面發(fā)現(xiàn),每個文件的下載鏈接就是?:https://vk666.lanzous.com+一組數(shù)。而這組數(shù)正是之前獲得的id 。

????問題又來了,這個普通下載按鈕下的鏈接才是真正的下載鏈接,怎么才能獲取到呢,老方法,刷新,發(fā)現(xiàn)在html里面是動態(tài)加載的,抓包。真正的下載url就在這個地方。


????
????又是post老方法,找到需要提交的數(shù)據(jù),就可以獲取。
與之前方法一模一樣,這里不再贅述。
完整代碼
import timeimport requestsfrom parsel import Selectordef get_update():url="https://vk666.lanzous.com/b00z8pwpg"headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36Edg/88.0.705.56',}res = requests.get(url,headers=headers)r=res.textimport repattern1=re.compile('var (.+?);')t=pattern1.findall(r)[3]k=pattern1.findall(r)[4]k=k.split("'")[1].split("'")[0]t=t.split("'")[1].split("'")[0]data={'lx':'2','fid':'1387166','uid':'1215702','pg':'1','rep':'0','t':t,'k':k,'up':'1',}url='https://vk666.lanzous.com/filemoreajax.php'res = requests.post(url,headers=headers,data=data)data=res.json()data=data['text']name_data={}size_data={}url_2='https://lanzous.com/'name_list=name_data.keys()for i in data :name_data[i['name_all']]=url_2+i['id']size_data[i['name_all']]=i['size']for i in name_list:num=re.sub("\D", "", i)if num >'30':url=name_data[i]res=requests.get(url,headers=headers)data=res.textrep=Selector(data)texts=rep.css("iframe[src*='/']::attr(src)").extract()[0]texts=url_2+texts.split('/')[1]res=requests.get(texts,headers=headers)pattern2=re.compile("(?<='signs':ajaxdata,'sign':')(.+?)(?=','ves':1,)")sign=pattern2.findall(res.text)[0]data={'action':'downprocess','signs':'?cftdf','sign':sign,'ves':'1','websign':''}headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36Edg/88.0.705.56','referer':texts}url_3='https://vk666.lanzous.com/ajaxm.php'res=requests.post(url_3,data=data,headers=headers)res=res.json()down_url='https://vip.d0.baidupan.com/file/'+res.get('url')return size_data,down_urlelse:return 0
????把以上程序當(dāng)作一個庫引入主程序,每次運(yùn)行主程序前,運(yùn)行一遍更新程序就好。
????看完這篇以后,相信我們對http更加熟悉了,再來想想,上一篇我們寫過的一個簡單的http服務(wù)器,可是要是有一百個,一千個用戶同時訪問怎么辦呢?
下一篇啊,我會說說,多任務(wù)(多進(jìn)程,多線程,協(xié)程)
