一種繞過限制下載論文的思路

註:本文下面的內容僅討論繞過思路,作為技術交流之用。大家下載論文還是應該通過正規渠道,付費下載,尊重各位站長的勞動成果。敏感圖片和代碼中涉及站點的內容均已打碼。

有時候要研究技術,我們也需要下載一些論文來看看的。一些論文站點,雖然提供預覽功能,但是下載卻是收費的。

舉個例子,如下站點:

當我們點擊「同意並開始全文預覽」按鈕時,是有一個彈出窗口來預覽論文的。

但是當我們點擊「下載」按鈕時,卻提示需要收費。

一方面它單篇論文的收費實在是挺貴的;另外一方面,我們可能更傾向於把論文批量下載到本地,等到有時間時慢慢讀完。這該怎麼辦呢?

我們F12看看預覽頁面的內容:

可以清晰的看到,id=」pdf」的div下的每個子節點div對應著論文的每一頁,而每一個子div中包含的img標籤對應的圖片則是每一頁的內容。我們將img標籤的src中的鏈接複製出來,粘貼在瀏覽器的新頁簽中,其實是可以看到本頁論文內容,而右鍵「保存圖片」是可以將此頁論文保存到本地的。

以上就是手動繞過限制下載論文的思路。但是有的論文頁數實在太多,手動逐個複製鏈接下載實在有些效率低下,所以我們可以寫個腳本來提升效率。

#coding:utf-8import tracebackimport urllib2import urllibimport sysimport Queueimport osimport timefrom bs4 import BeautifulSoupfrom selenium import webdriverdriver = webdriver.Firefox()driver.implicitly_wait(30) host = "此處打碼"searchurl = "https://" + host + "/index.php?m=Search&a=index"dstpath = "h:/downloadpdf"download_queue = Queue.Queue()reload(sys)sys.setdefaultencoding("utf-8")class UnicodeStreamFilter: def __init__(self, target): self.target = target self.encoding = utf-8 self.errors = replace self.encode_to = self.target.encoding def write(self, s): if type(s) == str: s = s.decode("utf-8") s = s.encode(self.encode_to, self.errors).decode(self.encode_to) self.target.write(s) if sys.stdout.encoding == cp936: sys.stdout = UnicodeStreamFilter(sys.stdout) def get_search_result(keywords): data = {"q":keywords} headers = {"cookie":"訪問論文站點時f12看到的cookie填入此處,此處打碼"} req = urllib2.Request(url=searchurl,data=urllib.urlencode(data),headers=headers) res = urllib2.urlopen(req) content = res.read() soup = BeautifulSoup(content, features="lxml") divlist = soup.find_all(class_="item-title") if divlist is not None and len(divlist) > 0: for divitem in divlist: alist = divitem.find_all("a") if alist is not None and len(alist) > 0: ahref = alist[0].attrs["href"] title = alist[0].attrs["title"] download_queue.put([ "http://%s%s"%(host,ahref,), title ])def save_pdf(title, imgls, chost): headers = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Cache-Control": "max-age=0", "Connection": "keep-alive", "Cookie": "__cfduid=dd7361d04f439dbfd27d12f286b72afdb1520244765; Hm_lvt_5d91dc9c92e499ab00ba867fc2294136=1520385180", "Upgrade-Insecure-Requests": 1, "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36" } if not os.path.exists(dstpath): os.mkdir(dstpath) curdst = dstpath + os.sep + str(title).replace(".pdf","").decode() if not os.path.exists(curdst): os.mkdir(curdst) pageindex = -1 for imgitem in imgls: if imgitem.attrs["src"].find("loading") != -1: continue src = imgitem.attrs["src"] src = "http://%s/%s"%(chost,src[3:],) pageindex = pageindex + 1 realpath = curdst + os.sep + str(pageindex) + ".png" with open(realpath, "wb") as f: req = urllib2.Request(url=src,headers=headers) f.write(urllib2.urlopen(req).read()) f.flush() print "下載",title,"完成" else: print curdst,"已存在"def download_pages(): while not download_queue.empty(): url,title = download_queue.get() html = urllib.urlopen(url).read() signal = "javascript:viewLogin.viewDl(" if html.find(signal) != -1: cid = html[html.find(signal) + len(signal):] cid = cid[:cid.find("")] pagerequest_url = "http://%s/index.php?g=Home&m=View&a=viewUrl&cid=%s&flag=1"%(host,cid,) pagereal_url = urllib.urlopen(pagerequest_url).read() chost = pagereal_url[2:].split("/")[0] pagereal_url = "http:%s"%(pagereal_url,) driver.get(pagereal_url) try: time.sleep(3) #每次移動滾動條的距離 distance = 300 #統計img標籤的個數,下拉時會新增img標籤 pimgnum = 0 #img標籤個數不再發生變化的次數 samecount = 0 while True: driver.execute_script($("#pdf").scrollTop(%s);%distance) time.sleep(2) distance = distance + 300 cimgnum = len(driver.find_elements_by_tag_name("img")) if cimgnum != pimgnum: pimgnum = cimgnum samecount = 0 continue else: samecount = samecount + 1 #當img標籤不再發生變化的次數達到20次時,則表明全部載入完畢 if samecount >= 20: break pagecontent = driver.page_source soup = BeautifulSoup(pagecontent, features="lxml") imgls = soup.find_all("img") if imgls is not None and len(imgls) > 0: save_pdf(title, imgls, chost) except Exception,e: traceback.print_exc()if __name__ == __main__: keywords = "攻擊樹" get_search_result(keywords) download_pages() driver.quit()

腳本主要步驟如下:

1.根據傳入的關鍵字(keyword欄位),模擬搜索請求;得到與該關鍵字相關的論文的標題以及url

2.打開論文對應的url,此時的頁面還不是真實的論文全文頁面;定位到預覽關鍵欄位cid(在javascript:viewLogin.viewDl()方法中),發送請求,得到論文真實全文頁面的對應的url

3.由於論文預覽採用了逐步載入的模式,即最初顯示3頁,然後隨著滾動條的拖動再逐漸載入後續內容;所以使用selelium模擬滾動頁面內容,判斷是否有新頁面被載入出來,直至頁面內容不再發生變化為止

4.此時基於第三部載入出的全部頁面內容,提取img欄位,逐個保存到本地;即對應著論文的每一頁

腳本運行效果如下:

得到的論文:

如果網路效果不是很好,可以適當將sleep時間延長。跑個腳本吃個飯回來,論文都下好了,還是很爽的。

原文鏈接:一種繞過限制下載論文的思路 - FreeBuf互聯網安全新媒體平台 | 關注黑客與極客

* 本文作者:tammypi,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載


推薦閱讀:

我是這麼看虹橋機場在上海空港中定位的
如何避開查重系統,降低重複率
從0開始寫Paper的10條「奧義」
北大中文經濟類核心期刊目錄
【翻譯】ACS Style Guide Chapter 2 Scientific Papers

TAG:論文 | 黑客Hacker |