1.爬取頁面效果圖
javascript
點擊"百度一下"按鈕前頁面
css
點擊"百度一下"按鈕後頁面html
天涯社區登陸頁面java
登陸進去以後我的主頁node
2、具體實現代碼
web
HtmlUnit(底層也是採用httpclient)和jsoup API
ajax
package com.yuanhai.test; import java.io.IOException; import java.net.MalformedURLException; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.safety.Whitelist; import org.jsoup.select.Elements; import org.junit.Assert; import org.junit.Test; import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider; import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlAnchor; import com.gargoylesoftware.htmlunit.html.HtmlButton; import com.gargoylesoftware.htmlunit.html.HtmlDivision; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlInput; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; import com.gargoylesoftware.htmlunit.html.HtmlTextInput; //參考博文 //1.http://blog.csdn.net/zstu_cc/article/details/39250903 //2.http://blog.csdn.net/cslie/article/details/48735261 public class HtmlUnitAndJsoup { /* * 首先說說HtmlUnit相對於HttpClient的最明顯的一個好處, * 是HtmlUnit不只保存了這個網頁對象,更難能難得的是它還存有這個網頁的全部基本操做甚至事件。 * 如今不少網站使用大量ajax,普通爬蟲沒法獲取js生成的內容。 */ /* * 依賴的jar包 commons-lang3-3.1.jar htmlunit-2.13.jar htmlunit-core-js-2.13.jar * httpclient-4.3.1.jar httpcore-4.3.jar httpmime-4.3.1.jar sac-1.3.jar * xml-apis-1.4.01.jar commons-collections-3.2.1.jar commons-io-2.4.jar * xercesImpl-2.11.0.jar xalan-2.7.1.jar cssparser-0.9.11.jar * nekohtml-1.9.19.jar */ // 百度新聞高級搜索 @Test public void HtmlUnitBaiduAdvanceSearch() { try { // 獲得瀏覽器對象,直接New一個就能獲得,如今就比如說你獲得了一個瀏覽器了 WebClient webclient = new WebClient(); // 這裏是配置一下不加載css和javaScript,配置起來很簡單,是否是 webclient.getOptions().setCssEnabled(false); webclient.getOptions().setJavaScriptEnabled(false); // 作的第一件事,去拿到這個網頁,只須要調用getPage這個方法便可 HtmlPage htmlpage = webclient .getPage("http://news.baidu.com/advanced_news.html"); // 根據名字獲得一個表單,查看上面這個網頁的源代碼能夠發現表單的名字叫「f」 final HtmlForm form = htmlpage.getFormByName("f"); System.out.println(form); // 一樣道理,獲取」百度一下「這個按鈕 final HtmlSubmitInput button = form.getInputByValue("百度一下"); System.out.println(button); // 獲得搜索框 final HtmlTextInput textField = form.getInputByName("q1"); System.out.println(textField); // 最近周星馳比較火呀,我這裏設置一下在搜索框內填入」周星馳「 textField.setValueAttribute("周星馳"); // 輸入好了,咱們點一下這個按鈕 final HtmlPage nextPage = button.click(); // 我把結果轉成String System.out.println(nextPage); String result = nextPage.asXml(); System.out.println(result); } catch (Exception e) { e.printStackTrace(); } } // 測試天涯論壇登錄界面 HtmlUnit 頁面JS的自動跳轉(響應碼是200,可是響應的頁面就是一個JS) // httpClient就麻煩了 @Test public void TianyaTestByHtmlUnit() { try { WebClient webClient = new WebClient(); // The ScriptException is raised because you have a syntactical // error in your javascript. // Most browsers manage to interpret the JS even with some kind of // errors // but HtmlUnit is a bit inflexible in that sense. // 加載的頁面有js語法錯誤會拋出異常 webClient.getOptions().setJavaScriptEnabled(true); // 啓用JS解釋器,默認爲true webClient.getOptions().setCssEnabled(false); // 禁用css支持 // 設置Ajax異步處理控制器即啓用Ajax支持 webClient .setAjaxController(new NicelyResynchronizingAjaxController()); // 當出現Http error時,程序不拋異常繼續執行 webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); // 防止js語法錯誤拋出異常 webClient.getOptions().setThrowExceptionOnScriptError(false); // js運行錯誤時,是否拋出異常 // 拿到這個網頁 HtmlPage page = webClient .getPage("http://passport.tianya.cn/login.jsp"); // 填入用戶名和密碼 HtmlInput username = (HtmlInput) page.getElementById("userName"); username.type("yourAccount"); HtmlInput password = (HtmlInput) page.getElementById("password"); password.type("yourPassword"); // 提交 HtmlButton submit = (HtmlButton) page.getElementById("loginBtn"); HtmlPage nextPage = submit.click(); System.out.println(nextPage.asXml()); } catch (Exception e) { e.printStackTrace(); } } // jsoup解析文檔 @Test public void jsoupParse() { try { /** HtmlUnit請求web頁面 */ // 模擬chorme瀏覽器,其餘瀏覽器請修改BrowserVersion.後面 WebClient wc = new WebClient(BrowserVersion.CHROME); wc.getOptions().setJavaScriptEnabled(true); // 啓用JS解釋器,默認爲true wc.getOptions().setCssEnabled(false); // 禁用css支持 wc.getOptions().setThrowExceptionOnScriptError(false); // js運行錯誤時,是否拋出異常 wc.getOptions().setTimeout(10000); // 設置鏈接超時時間 ,這裏是10S。若是爲0,則無限期等待 HtmlPage page = wc.getPage("http://passport.tianya.cn/login.jsp"); String pageXml = page.asXml(); // 以xml的形式獲取響應文本 // text只會獲取裏面的文本,網頁html標籤和script腳本會被去掉 String pageText = page.asText(); System.out.println(pageText); // 方法一,經過get方法獲取 HtmlButton submit = (HtmlButton) page.getElementById("loginBtn"); // 方法二,經過XPath獲取,XPath一般用於沒法經過Id搜索,或者須要更爲複雜的搜索時 HtmlDivision div = (HtmlDivision) page.getByXPath("//div").get(0); // 網絡爬蟲中主要目的就是獲取頁面中全部的連接 java.util.List<HtmlAnchor> achList = page.getAnchors(); for (HtmlAnchor ach : achList) { System.out.println(ach.getHrefAttribute()); } System.out.println("-------jsoup部分------"); // 服務器端進行校驗並清除有害的HTML代碼,防止富文本提交有害代碼 Jsoup.clean(pageXml, Whitelist.basic()); /** jsoup解析文檔 */ // 把String轉化成document格式 Document doc = Jsoup.parse(pageXml); Element loginBtn = doc.select("#loginBtn").get(0); System.out.println(loginBtn.text()); Assert.assertTrue(loginBtn.text().contains("登陸")); } catch (Exception e) { e.printStackTrace(); } } // htmlunit設置代理上網 @Test public void proxy() { String proxyHost = "192.168.0.1"; int port = 80; WebClient webClient = new WebClient(BrowserVersion.CHROME, proxyHost, port); webClient.setAjaxController(new NicelyResynchronizingAjaxController()); DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient .getCredentialsProvider(); String username = "account"; String password = "password"; credentialsProvider.addCredentials(username, password); } // jsoup請求並解析 @Test public void jsoupCrawl() throws IOException { String url = "http://passport.tianya.cn/login.jsp"; Connection con = Jsoup.connect(url);// 獲取請求鏈接 // 瀏覽器可接受的MIME類型。 con.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); con.header("Accept-Encoding", "gzip, deflate"); con.header("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"); con.header("Connection", "keep-alive"); con.header("Host", url); con.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0"); Document doc = con.get(); Elements loginBtn = doc.select("#loginBtn"); System.out.println(loginBtn.text());// 獲取節點中的文本,相似於js中的方法 } }
httpclient模擬post請求登陸
apache
package com.yuanhai.test; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import org.apache.http.Consts; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import com.steadystate.css.parser.ParseException; /** * @author * @date * @version * */ public class TianyaTestByHttpClient { /** * 沒法實現js頁面的自動跳轉,HtmlUnit能夠 */ public static void main(String[] args) throws Exception { // 這是一個測試,也是爲了讓你們看的更清楚,請暫時拋開代碼規範性,不要糾結於我多建了一個局部變量等 // 獲得認證https的瀏覽器對象 HttpClient client = getSSLInsecureClient(); // 獲得咱們須要的post流 HttpPost post = getPost(); // 使用咱們的瀏覽器去執行這個流,獲得咱們的結果 HttpResponse hr = client.execute(post); // 在控制檯輸出咱們想要的一些信息 showResponseInfo(hr); } private static void showResponseInfo(HttpResponse hr) throws ParseException, IOException { System.out.println("響應狀態行信息:" + hr.getStatusLine()); System.out.println("---------------------------------------------------------------"); System.out.println("響應頭信息:"); Header[] allHeaders = hr.getAllHeaders(); for (int i = 0; i < allHeaders.length; i++) { System.out.println(allHeaders[i].getName() + ":" + allHeaders[i].getValue()); } System.out.println("---------------------------------------------------------------"); System.out.println("響應正文:"); System.out.println(EntityUtils.toString(hr.getEntity())); /* <body> <script> location.href="http://passport.tianya.cn:80/online/loginSuccess.jsp?fowardurl=http%3A%2F%2Fwww.tianya.cn%2F110486326&userthird=®Orlogin=%E7%99%BB%E5%BD%95%E4%B8%AD......&t=1458895519504&k=06d41f547cd05fb5dea1590a60e1ec98&c=669767baea73097dde58423fac777138"; </script> </body>*/ } // 獲得一個認證https連接的HttpClient對象(由於咱們將要的天涯登陸是Https的) // 具體是如何工做的咱們後面會提到的 private static HttpClient getSSLInsecureClient() throws Exception { // 創建一個認證上下文,承認全部安全連接,固然,這是由於咱們僅僅是測試,實際中承認全部安全連接是危險的 SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext); return HttpClients.custom().// setSSLSocketFactory(sslsf)// // .setProxy(new HttpHost("127.0.0.1", 8888)) .build(); } // 獲取咱們須要的Post流,若是你是把個人代碼複製過去,請記得更改成你的用戶名和密碼 private static HttpPost getPost() { HttpPost post = new HttpPost("https://passport.tianya.cn/login"); // 首先咱們初始化請求頭 post.addHeader("Referer", "https://passport.tianya.cn/login.jsp"); post.addHeader("Host", "passport.tianya.cn"); post.addHeader("Origin", "http://passport.tianya.cn"); // 而後咱們填入咱們想要傳遞的表單參數(主要也就是傳遞咱們的用戶名和密碼) // 咱們能夠先創建一個List,以後經過post.setEntity方法傳入便可 // 寫在一塊兒主要是爲了你們看起來方便,你們在正式使用的固然是要分開處理,優化代碼結構的 List<NameValuePair> paramsList = new ArrayList<NameValuePair>(); /* * 添加咱們要的參數,這些能夠經過查看瀏覽器中的網絡看到,以下面個人截圖中看到的同樣 * 不論你用的是firebug,httpWatch或者是谷歌自帶的查看器也好,都能查看到(後面會推薦輔助工具來查看) * 要把表單須要的參數都填齊,順序不影響 */ paramsList.add(new BasicNameValuePair("Submit", "")); paramsList.add(new BasicNameValuePair("fowardURL", "http://www.tianya.cn")); paramsList.add(new BasicNameValuePair("from", "")); paramsList.add(new BasicNameValuePair("method", "name")); paramsList.add(new BasicNameValuePair("returnURL", "")); paramsList.add(new BasicNameValuePair("rmflag", "1")); paramsList.add(new BasicNameValuePair("__sid", "1#1#1.0#a6c606d9-1efa-4e12-8ad5-3eefd12b8254")); // 你能夠申請一個天涯的帳號 並在下兩行代碼中替換爲你的用戶名和密碼 paramsList.add(new BasicNameValuePair("vwriter", "yourAccount"));// 替換爲你的用戶名 paramsList.add(new BasicNameValuePair("vpassword", "yourPassword"));// 你的密碼 // 將這個參數list設置到post中 post.setEntity(new UrlEncodedFormEntity(paramsList, Consts.UTF_8)); return post; } }
參考文章:
api
http:
//blog.csdn.net/zstu_cc/article/details/39250903
瀏覽器
http:
//blog.csdn.net/cslie/article/details/48735261