缺點是需要人工尋找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來爬取該網頁動態加載的正文部分(一個簡單應用)
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屬性的值。這裏只貼出純文本輸出的部分結果)