Python 實現 CNKI批量下載 和FireFox Extension 入門學習筆記 javascript
因爲須要也是爲了督促本身學習新的東西,我本來想要嘗試着寫一個爬蟲程序,可以在cnki上自動得將論文進行批量下載,學習過程當中遇到了諸多狀況,cnki也真是專業,不得不佩服cnki的強大。 java
下面進入正題: python
學習、實驗環境:ubuntu 14.04 chrome
工具:Eclipse , FireFox, FireBug,HttpFox 編程
編程語言:python, js, XUL ubuntu
因爲我是中山大學學生,使用校園網進入cnki進行下載是不用登陸的,因此我也就沒進行模擬登陸等方面的實現,有須要的朋友可使用splinter進行模擬登陸,也算快速便捷哈。 windows
首先咱們要實現使用python對cnki的論文實現批量下載,咱們首先要對客戶端和服務器之間相互傳遞的信息進行了解,這裏我第一次使用的是wireshark,可是這個工具雖然強大,可是真不利於咱們進行分析,它抓取的是咱們電腦端口的信息,而不能只抓取當前網頁的,在屢次嘗試以後我選擇了HttpFox進行數據包抓取: 瀏覽器
如圖咱們能夠發現cnki對一個下載進行了3此redirect,咱們經過對得到的數據和再一次發送的數據對比能夠發現:前一次得到的url就是下一次get的url,因此咱們就能夠寫出下載部分的核心代碼,只有一點點是本身寫的,許多網上一搜就有。 服務器
# -*- coding: UTF-8 -*- import sys import urllib2 import cookielib import string import re import time cj = cookielib.CookieJar() cookie_support = urllib2.HTTPCookieProcessor(cj) opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) urllib2.install_opener(opener) url = 'http://epub.cnki.net/kns/download.aspx?filename=MBnRwcDMudGaItiamtScHVzb2Y0ZrVWRCBjaykEVXRTOjV0QHxUcTh3KNFXbHBDTyQVMNR2cP9kYGh1SXZnQnp3b3I2YqBnbUJ3KSNnRvpEUwhWTVJjNKBDcXVnSmZUayMkRVJUdytCe1AjT1ImTYdWdth1RtlGb&tablename=CMFDLAST2013' h = { 'Referer' : url, 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0' } r = urllib2.urlopen(urllib2.Request(url,headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) data = r.read() print data
使用FireBug獲取網頁源代碼,隨意找幾個下載圖標的連接url粘貼到代碼中試一試成功了。 cookie
下載部分的代碼成功了,那下面就是,如何從cnki的網頁中獲取到下載的url了,在這部分的實現中,我本來想要使用純python的實現,使用python寫一個爬蟲,直接上cnki進行抓取,可是具體實現的時候碰到了很大的問題,例如:1、爬蟲網頁動態生成的數據困難重重;2、cnki網頁在瀏覽器顯示的url一直都是:」http://epub.cnki.net/kns/brief/default_result.aspx」;3、咱們須要的網頁是放在一個iframe標籤裏面的,這就很是蛋疼了,一直沒找到獲取辦法
在同窗的提示下,我發現了也許FireFox Extension是可行的解決方案。
學習FireFox Extension的話首先須要能至少看懂XUL代碼,而後基本的模範着寫,而後呢,就得學會javascript了,固然也有不用js實現的插件,例如使用python寫,那使用PyXPCOM,可是我還沒學會,這裏頁不須要哈。
(一)FF extension整體認知
FF是基於mozilla內核的,其瀏覽器引擎功能主要由C語言實現,但其瀏覽器界面及其界面上的相關操做都是由JS和XUL完成的,這就是FF的強大之處,同時它也爲你們提供了很好的擴展機制。
FF擴展的開發目錄結構:
能夠到官網上仔細看看。
FF的工做方式:
對於任何一種新的開發語言或環境,你們一般都試圖去尋找程序的入口點。能夠很負責任地跟你們說,任何編譯型(解釋型程序)開發語言的程序都有相似C中的Main函數、Java中的主類(public static void main函數)、C#中的入口函數(static void/int Main)等做爲程序入口。
這裏咱們呢瞭解這些也就夠了。
這裏個人目錄結構是:
--chrome
--content
--overlay.js
--sample.xul
--chrome.manifest
--install.rdf
其中install.rdf代碼爲:
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>sample@example.net</em:id> <em:version>1.0</em:version> <em:type>2</em:type> <!-- Target Application this extension can install into, with minimum and maximum supported versions. --> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.5</em:minVersion> <em:maxVersion>4.0.*</em:maxVersion> </Description> </em:targetApplication> <!-- Front End MetaData --> <em:name>DownLoadPaper</em:name> <em:description>A test extension</em:description> <em:creator>Liang</em:creator> <em:homepageURL>http://www.example.com/</em:homepageURL> </Description> </RDF>
chrome.manifest代碼爲
overlay chrome://browser/content/browser.xul chrome://sample/content/sample.xul content sample chrome/content/
overlay.js代碼爲:
function getURL() { if ( window.content.document.location.href != " { alert("Worng address"); } else { var myWin = window.content.document.getElementById('iframeResult').contentWindow; var hre = myWin.document.getElementsByClassName('brief_downloadIcon'); var path = prompt("save address","eg. //****/****"); path = path + "/test.csv"; try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); } catch (e) { alert("no permisson..."); } var file = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); file.initWithPath(path); if ( file.exists() == false ) { file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 ); } var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance( Components.interfaces.nsIFileOutputStream ); outputStream.init( file, 0x04 | 0x08 | 0x20, 420, 0 ); var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); for (var i = 0; i < hre.length; i++) { converter.charset = 'UTF-8'; var convSource = converter.ConvertFromUnicode(hre[i].href+"\n"); var result = outputStream.write( convSource, convSource.length ); } outputStream.close(); alert("File was saved in "+path); } }
sample.xul代碼以下:
<?xml version="1.0"?> <overlay id="sample" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/x-javascript" src="overlay.js"/> <menupopup id="menu_ToolsPopup"> <menuitem id="DownLoadPaper" label="DownLoadPaper" oncommand="getURL();"/> </menupopup> </overlay>
至此,這個粗糙的輔助插件就編寫完了,將文件打包壓縮成zip格式,而後更名後綴爲.xpi,再拖入FF就能安裝了,這裏須要修改一下FF的權限,使得插件可以修改本地文件,這樣,工具欄裏會多出一個工具,點擊就能把論文下載的URL下載到一個test.csv的文件裏了,windows下的用戶就不要存到C盤裏哈。
完整python文件爲:
# -*- coding: UTF-8 -*- import sys import urllib2 import cookielib import string import re import time f = open('test.csv', 'r') i = 1 for line in f: print line try: cj = cookielib.CookieJar() cookie_support = urllib2.HTTPCookieProcessor(cj) opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) urllib2.install_opener(opener) url = line refer = 'http://epub.cnki.net/kns/brief/brief.aspx?pagename=ASP.brief_default_result_aspx&dbPrefix=SCDB&dbCatalog=%e4%b8%ad%e5%9b%bd%e5%ad%a6%e6%9c%af%e6%96%87%e7%8c%ae%e7%bd%91%e7%bb%9c%e5%87%ba%e7%89%88%e6%80%bb%e5%ba%93&ConfigFile=SCDBINDEX.xml&research=off&t=1431252221059&keyValue=python&S=1' h = { 'Referer' : refer, 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0' } r = urllib2.urlopen(urllib2.Request(url,headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) r = urllib2.urlopen(urllib2.Request(r.geturl(),headers = h)) data = r.read() if data[:8] == '[TARGET]': with open(str(i)+".caa", "wb") as up: up.write(data) up.close else: with open(str(i)+".caj", "wb") as up: up.write(data) up.close print str(i)+' '+'succeed' time.sleep(2) except: print str(i)+' '+'failed' i = i + 1
這樣,將test.csv與python文件放於相同目錄下,運行python文件就能夠下載了。