藍奏雲的下載鏈接解析思路並不復雜,但網上幾款真實鏈接解析工具,要么解析出的地址只是跳轉鏈接,要么需要輸入驗證碼,而藍奏雲網頁版在使用是幾乎是不會遇上驗證碼的,這實際上是因為藍奏雲在下載過程中有幾個小坑。
直接上可用代碼,后面再進行解釋:
def downlanzou(lanzouurl, path, extracode): sess = requests.session() sess.headers = {'user-agent':"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"} req = sess.get(lanzouurl, verify=False) sign = re.search(r"action=downprocess&sign=([A-Za-z0-9_-]+?)&p=", req.text).group(1) head2 = { "referer": lanzouurl } req = sess.post("https://lanzous.com/ajaxm.php", data={ "action":"downprocess", "sign":sign, "p":extracode}, headers=head2, verify=False) res = req.json() url = res['dom']+'/file/'+res['url'] filename = res['inf'] os.makedirs(path, exist_ok=True) headnew = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 OPR/28.0.1750.51", "Accept-Encoding":"gzip, deflate, lzma, sdch", # 重點1 "Accept-Language":"zh-CN,zh;q=0.8", # 重點2 "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" # 重點3 } dreq = requests.get(url, headers=headnew, verify=False) with open(os.path.join(path, filename), 'wb') as f: f.write(dreq.content) return filename
關鍵在於三處重點,即最后一次請求里必須包含這三個頭,雖然大多數時候,不帶這類頭並不會對訪問產生影響,但筆者實驗如果少了這幾個頭,就會被重定向到驗證碼頁面,且即便輸入正確也無法跳出。
但如果在Chrome的F12或者Charles里查看抓包,是不會看到這幾個頭的,而是如下圖:
這是因為現在的瀏覽器基本都支持HTTP2標准,請求頭里出現冒號代表服務器與瀏覽器協商后,使用了HTTP2標准來進行通信,但爬蟲常用的requests等庫都不支持HTTP2
雖然我們也可以通過另外的庫讓Python支持HTTP2(hyper庫),但並無必要,只需要讓服務器以HTTP1.1標准工作即可。可以下載各瀏覽器在15年或更早發布的版本,筆者使用的是歐朋28.0,再次訪問即抓到了適合requests使用的請求頭。
強制HTTP協議版本的方法不總是有效,比如天貓就已經開始限制HTTP1.1的使用。