在下抓數據也小有研究,現分享幾個本身研究出來的抓數據的技術,可能會有不少不足的地方,歡迎你們指正補充哈哈!
方法一:直接抓取網頁源碼
優勢:速度快。
缺點:1,正因爲速度快,易被服務器端檢測,可能會限制當前ip的抓取。對於這點,能夠嘗試使用ip代碼解決。
2,若是你要抓取的數據,是在網頁加載完後,js修改了網頁元素,沒法抓取。
3,遇到抓取一些大型網站,若是須要抓取如登陸後的頁面,可能須要破解服務器端賬號加密算法以及各類加密算法,及其考驗技術性。
適用場景:網頁徹底靜態化,而且你要抓取的數據在網頁首次加載完成就加載出來了。涉及登陸或者權限操做的相似頁面未作任何賬號加密或只作簡單加密的。
固然,若是該網頁你抓取的數據,是經過接口得到的json,那麼,你就更幸福的,直接抓取json頁面便可。
對於有登陸的頁面,咱們如何拿到他的登陸頁以後的源碼呢?
首先我要介紹一下,對於session保存賬號信息的狀況下,服務器是如何肯定該用戶身份的。
首先,用戶登陸成功後,服務器端會將用戶的當前會話信息保存到session中,每個session有一個惟一標誌sessionId。則用戶訪問這個頁面,session被建立後,就會接收到服務器端傳回的sessionId,並將其保存到cookie中,所以,咱們能夠用chrome瀏覽器打開檢查項,查看當前頁面的jsessionId。下次用戶訪問須要登陸的頁面時,用戶發送的請求頭會附上這個sessionId,服務器端經過這個sessionId就能夠肯定用戶的身份。
這裏,我搭建了一個簡單的jsp登陸頁面,登陸後的賬號信息保存在服務器端session中。
思路:1,登陸。2,登陸成功後得到cookie。3,將cookie放到請求頭中,向登陸頁發送請求。
附上java版本的代碼及python
java版:html
package craw; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; public class CrawTest { //得到網頁源代碼 private static String getHtml(String urlString,String charset,String cookie){ StringBuffer html = new StringBuffer(); try { URL url = new URL(urlString); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); urlConn.setRequestProperty("Cookie", cookie); BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream(),charset)); String str; while((str=br.readLine())!=null){ html.append(str); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return html.toString(); } //發送post請求,並返回請求後的cookie private static String postGetCookie(String urlString,String params,String charset){ String cookies=null; try { URL url = new URL(urlString); URLConnection urlConn = url.openConnection(); urlConn.setDoInput(true); urlConn.setDoOutput(true); PrintWriter out = new PrintWriter(urlConn.getOutputStream()); out.print(params); out.flush(); cookies = urlConn.getHeaderFields().get("Set-Cookie").get(0); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return cookies; } public static void main(String[] args) { String cookie = postGetCookie("http://localhost:8080/loginDemo/login", "username=admin&password=123456","utf-8"); String html = getHtml("http://localhost:8080/loginDemo/index.jsp", "utf-8", cookie); System.out.println(html);//這裏咱們就可能輸出登陸後的網頁源代碼了 } }
python版:java
#encoding:utf-8 import urllib import urllib2 data={'username':'admin','password':'123456'} data=urllib.urlencode(data) response = urllib2.urlopen('http://localhost:8080/loginDemo/login',data=data)//登陸 cookie = response.info()['set-cookie']//得到登陸後的cookie jsessionId = cookie.split(';')[0].split('=')[-1]//從cookie得到sessionId html = response.read() if html=='error': print('用戶名密碼錯誤!') elif html=='success': headers = {'Cookie':'JSESSIONID='+jsessionId}//請求頭 request =urllib2.Request('http://localhost:8080/loginDemo/index.jsp',headers=headers) html = urllib2.urlopen(request).read() print(html)//輸出登陸後的頁面源碼
咱們能夠很明顯看出python的優點,會比java少寫至少一半的代碼量,固然這便是java的優勢,也是java的缺點,優勢就是更加靈活,程序員能夠更好的控制底層代碼的實現,缺點就是不易上手,對技術要求太高,所以,若是你是一名數據抓取新人,我的極力推薦你學習python。
方法二:模擬瀏覽器操做
優勢:1,和用戶操做相相似,不易被服務器端檢測。
2,對於登陸的網站,即便是通過了N層加密的,無需考慮其加密算法。
3,可隨時得到當前頁面各元素最新狀態。
缺點:1,速度稍慢。
這裏介紹幾個不錯的模擬瀏覽器操做的類庫:
C# webbrower控件:
若是你研究過c# winform,相信你絕對不會對webbrower這個控件陌生,他就是一個瀏覽器,內部驅動其實也是ie的驅動。
他能夠以dom方式隨時解析當前的document(網頁文檔對象),不只能夠拿到相關Element對象,還能夠對element對象進行修改,乃至調用方法,如onclick方法,onsubmit等等,也能夠直接調用頁面js方法。
C#對webbrower操做代碼:python
webBrowser1.Navigate("https://localhost//index.html");//加載一個頁面 須要注意的是:不要直接執行如下代碼,由於網頁加載須要時間,建議如下代碼寫到webBrowser1_DocumentCompleted(加載完成)事件中: webBrowser1.Document.GetElementById("username").InnerText="admin";//在網頁中找到id爲username的元素,設置其文本爲admin webBrowser1.Document.GetElementById("password").InnerText = "123456";//在網頁中找到id爲password的元素,設置其文本爲123456 webBrowser1.Document.InvokeScript("loginEncrypt");//調用網頁js函數:loginEncrypt.
因爲有些頁面ie可能不夠友好,或者若是ie版本太低,甚至是安全證書等問題,那麼這個方案可能就pass掉了。
咱們能夠直接使用selenium庫來操做系統中真實瀏覽器,如chrome瀏覽器,selenuim支持多語言開發,以python調用selenium爲例,selenium就是直接操做咱們系統中的瀏覽器,但須要確保瀏覽器安裝對應的驅動。
然而,真正開發中,有時咱們可能不但願看到這個瀏覽器界面,這裏,我能夠推薦你們一個後臺瀏覽器,他直接在cmd中進行操做,沒有界面,那就是phantomjs。
這樣,咱們使用python+selenium+phantomjs就能夠模擬瀏覽器的操做,而且看不到界面,因爲phantomjs沒有界面,因此他會比通常的瀏覽器要快不少。
這裏網上有大量的資料,一時半會也講不請,這裏就不作過多講解,你們能夠看看:http://www.cnblogs.com/luxiaojun/p/6144748.html
三,Fidder script:
fidder是一款很是強大的數據抓取工具,他不只能夠抓取到當前系統中的http請求,他還能夠提供安全證書,所以有時候,咱們抓取過程當中,若是遇到安全證書錯誤,咱們不妨把fidder打開,讓他提供你一個證書,或許你就近成功近在咫尺。
使人更增強大的是fidder script,他能夠在對抓取到了請求後,進行一系統操做,如將請求到的數據保存到硬盤中。或者在請求前,修改請求頭,可謂是抓取一利器,這樣,咱們使用fidder配合上以前的各種方法,相信能夠解決大多難題。而且他的語法和C like系列語法類似,類庫和c#大多相同,相信對C#熟悉的同窗,上手fiddler script會很快。
fidder script:http://blog.csdn.net/crisschan/article/details/45602745程序員