使用HttpClient獲取網頁中動態加載的某部分數據,Java實現

缺點是需要人工尋找post請求的url和對應的參數。

參考:

1.爲GET和POST請求添加請求參數和請求頭 (使用HttpClient,Java)

2.關於抓取js加載出來的內容抓取 (參考了該博客的流程,例如找到實際的請求url)


以一篇新聞資訊爲例:http://news.cqcoal.com/blank/nc.jsp?mid=98212

1.使用F12,在network中的文件列表中先找到該網頁,雙擊彈出各項詳細信息。“正文”查看該網頁的內容,發現資訊對應的信息在網頁沒有顯示,說明是後期加載上去的。

2.試着搜索文中的關鍵字,看看爲獲取數據,請求了哪些文件。例如搜索正文第一個詞“海關總署”,可能會搜出多個文件,需要進行判斷和選擇。

對應的請求正文爲“id: 98212”,即請求參數

3.查看“標頭”

主要看請求url和請求方法,有時候需要設置user-agent。需要使用post方法

4.代碼編寫

 建立Java Maven項目,添加依賴:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.2.4</version>
</dependency>

下載的jar包見下圖:

代碼如下,我只獲取了該文章的正文:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.google.gson.Gson;

/**
 * http://news.cqcoal.com/blank/nc.jsp?mid=98212
 * 該網頁的新聞主題是動態生成的,希望獲取內容
 * @author yangc_cong
 *
 */
public class TestNewContent {
	
	/**
	 * 針對請求的鏈接,使用post方法獲取返回的數據
	 * @param urlStr String類型
	 * @return 這裏是Map類型
	 */
	private Map getPageContByHttpCl(String urlStr) {
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpPost post = new HttpPost(urlStr);
		
		String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362";
		post.setHeader("User-Agent", userAgent);
		CloseableHttpResponse response = null;
		String result = null;
		// 創建請求參數

        List<NameValuePair> list = new LinkedList<NameValuePair>();
        BasicNameValuePair param1 = new BasicNameValuePair("id", "98212");
        list.add(param1);

        // 使用URL實體轉換工具
        UrlEncodedFormEntity entityParam = null;
		try {
			entityParam = new UrlEncodedFormEntity(list, "UTF-8");
			post.setEntity(entityParam);
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
        
		try {
			response = httpclient.execute(post);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println(result);

		Gson gson = new Gson();
		Map map = gson.fromJson(result, Map.class);
		return map;
	}
	
	private void parse_content(Map map) {
		//java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Map
		ArrayList arrayList = (ArrayList)(map.get("rows"));
		Map innerMap = (Map) arrayList.get(0);
		String source = (String) innerMap.get("source");
		String bodyhtml = (String) innerMap.get("body");
		System.out.println("source: "+source);
		System.out.println("bodyhtml:"+'\n'+bodyhtml);
	}
	
	public static void main(String[] args) {
		TestNewContent test1 = new TestNewContent();
		String urlStr = "http://news.cqcoal.com/manage/newsaction.do?method:getNewsArchives";
		Map map = test1.getPageContByHttpCl(urlStr);
		test1.parse_content(map);
	}
}

運行截圖:


補充:使用HtmlUnit來爬取該網頁動態加載的正文部分(一個簡單應用)

參考:HtmlUnit+Jsoup學習總結 

1.在maven項目中的配置

<!-- https://mvnrepository.com/artifact/net.sourceforge.htmlunit/htmlunit -->
<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>2.27</version>
</dependency>

下載的jar包如下,有很多,所以建議使用maven進行配置:

2.代碼部分(按照參考的博客進行編寫的)

import java.io.IOException;
import java.net.MalformedURLException;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public class HtmlUnitTest {
	public static void main(String[] args) {
		String url ="http://www.qidian.com";
		url = "http://news.cqcoal.com/blank/nc.jsp?mid=98212";
		// 1創建WebClient
		WebClient webClient=new WebClient(BrowserVersion.CHROME);
		// 2 啓動JS
		webClient.getOptions().setJavaScriptEnabled(true);
		// 3 禁用Css,可避免自動二次請求CSS進行渲染
		webClient.getOptions().setCssEnabled(false);
		// 4 啓動客戶端重定向
		webClient.getOptions().setRedirectEnabled(true);
		// 5 js運行錯誤時,是否拋出異常
		webClient.getOptions().setThrowExceptionOnScriptError(false);
		// 6 設置超時
		webClient.getOptions().setTimeout(50000);       //獲取網頁
		HtmlPage htmlPage = null;
		try {
			htmlPage = webClient.getPage(url);
		} catch (FailingHttpStatusCodeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 等待JS驅動dom完成獲得還原後的網頁
		webClient.waitForBackgroundJavaScript(10000);
		// 網頁內容  
		String pageHtml = htmlPage.asXml();
		System.out.println(pageHtml);
		System.out.println("\n------\n");
		//網頁內容---純文本形式
		String pageText = htmlPage.asText();
		System.out.println(pageText );
		
		//輸出網頁的title
		String title = htmlPage.getTitleText();
		System.out.println(title );

		//close
		webClient.close();
	}
}

3.運行結果(代碼中要求輸出加載js之後,包含標籤的網頁內容、純文本---網頁的文字部分、網頁標題---即title屬性的值。這裏只貼出純文本輸出的部分結果)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章