soup
抓取網頁后,需要對網頁解析,可以使用字符串處理工具解析頁面,也可以使用正則表達式
jsoup 的作用:是一款 Java 的HTML 解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于JQuery的操作方法來取出和操作數據
jsoup的主要功能如下:
1.從一個URL,文件或字符串中解析HTML;
2.使用DOM或CSS選擇器來查找、取出數據;
3.可操作HTML元素、屬性、文本;
創建練習類
解析URL
第一個參數是訪問的url,第二個參數是訪問的超時時間
使用標簽選擇器,獲取title標簽中的內容
輸出結果
讀取文件
準備一個簡易的HTML文件
獲取這個
讀取文件,獲取字符串,代碼及結果
使用dom方式遍歷文檔
解析文件獲取document對象
依據id獲取,這個是id的內容,我們獲取這個內容
編寫代碼,顯示結果
依據標簽獲取,我們獲取這個標簽的內容
代碼及結果
依據class獲取,獲取內容
代碼和結果
依據屬性,屬性內容
代碼和結果
接下來從元素中獲取數據
首先從元素中獲取ID
從元素中獲取className
文本
代碼及結果
如果內容是兩個class
那么代碼及結果
從元素中獲取屬性
代碼及結果
獲取元素的所有屬性
代碼及結果
從元素中獲取文本內容,這個之前有,代碼和結果
soup介紹
Jsoup是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數據。
Jsoup主要功能
注冊中心:
以實例來講解Jsoup使用
步驟:創建項目、pom.xml引入、創建啟動類、運行項目。
中文偽代碼
需求:我們要爬取Docker技術文章,這個網站頁面左邊為菜單,右邊為內容。
經過分析:菜單里的url,是在css的class:left-navigation下面的a標簽下,并且url以/article/index/開始的。
內容:直接在css的class:article_content下面的html。開始寫代碼了:
pom.xml引入
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency>
創建啟動類
注:可能學校的教務系統已經做了升級,當前的程序不知道還能不能成功獲取信息,加上已經畢業,我的賬戶已經被注銷,試不了,在這里做下思路跟過程的記錄。
在我的畢業設計中”基于SSM框架賀州學院校園二手交易平臺設計與實現”我有這樣一個設想:使用學校教務系統賬號進行賀州學院學生身份認證(通過HttpClient模擬登陸),發布者身份信息真實、平臺由學生(可以跟計算機協會合作,由他們進行維護)維護,平臺安全可靠,校園身份認證時本校園二手交易平臺的一大特色。為了實現這個功能,我對我們學校的教務系統進行了模擬登陸。
我通過HttpClients模擬登陸教務系統,獲取學生信息,使用jsoup俗稱“大殺器”進行解析響應回來的html 匹配個人信息a標簽地址并做攜帶參數頁Referer進行第二次請求,使用jsoup來解析響應回來的htm匹配所有學生信息獲取我們想要的學生信息。在存儲過程中要進行唯一性認證,一個賬號只能認證一次,一個學生教務教務系統賬號只能綁定一個平臺賬號。
目前頭像的上傳我是這樣做的,先把圖片下載的用戶電腦本地作為臨時文件,再調用FtpUtil.upload()方法讀取文件上傳到我們nginx圖片服務器,成功上傳后刪除用戶電腦中的臨時文件。(因為上傳需要傳入一個InputStream但是在寫代碼過程中發現從響應回來的HttpResponse獲取到的數據轉為InputStream時文件出現損失導致上傳后圖片無法正常打開的情況)。而一個重要的技術點就是驗證碼的問題,在編寫代碼時發現想使用Tesseract-OCR開源工具,然而,實現起來沒那么簡單,所以我的做法是把教務系統的驗證碼直接writeTo到用戶的HttpServletResponse獲取圖片驗證碼,直接響應回瀏覽器,讓用戶自己手動輸入再傳到后臺。
引入jar:(如果想在控制臺打印更多連接時的信息,可以使用log4j),或者使用maven引入也行
public class AuthenticationUtil {
private static HttpClient client = HttpClients.createDefault();//實例化httpclient
//static HttpResponse response = null;
private static String rawHtml; //響應回來的數據
/* public static void main(String[] args) throws Exception {
//模擬登陸教務系統,獲取學生信息
System.out.println("======模擬登陸教務系統,獲取學生信息======");
//獲取驗證碼
int i=getVerifyingCode();
if(i==1){
//提醒用戶并輸入驗證碼
System.out.println("驗證碼圖片下載成功! D:/verifyCode.gif,請輸入圖片驗證碼:");
String code;
Scanner in = new Scanner(System.in);
code = in.nextLine();
in.close();
Map map = login("xxx","***",code);
if("200".equals(map.get("code"))){
String xm= (String) map.get("xm");//姓名
String xh= (String) map.get("xh");//學號
String lbl_xb= (String) map.get("lbl_xb");//性別
String lbl_csrq= (String) map.get("lbl_csrq");//出生日期
String lbl_sfzh= (String) map.get("lbl_sfzh");//身份證號
String lbl_xy= (String) map.get("lbl_xy");//學院
String lbl_zymc= (String) map.get("lbl_zymc");//專業
String lbl_xzb= (String) map.get("lbl_xzb");//班級
System.out.println(xm);
}else{
System.out.println(map.get("msg"));
}
}else{
System.out.println("驗證碼圖片下載失敗...");
}
}*/
/**
* 模擬登陸
* @param login_xh
* @param login_mm
* @param code
* @throws IOException
* @throws ParseException
*/
public static Map<String,String> login(String login_xh,String login_mm,String code) throws Exception {
Map<String,String> map =new HashMap<String,String>();
String __VIEWSTATE="";
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");
HttpResponse response = client.execute(getVerifyCode);//獲取驗證碼
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document doc = Jsoup.parse(rawHtml);
Elements select_input = doc.select("input");
for (Element a : select_input) {
String name = a.attr("name");
if("__VIEWSTATE".equals(name)){
__VIEWSTATE=a.attr("value");
break;
}
}
//設定post參數
ArrayList<NameValuePair> postData = new ArrayList<NameValuePair>();
postData.add(new BasicNameValuePair("Button1", ""));
postData.add(new BasicNameValuePair("RadioButtonList1", "學生"));//登陸賬號類型
postData.add(new BasicNameValuePair("TextBox2", login_mm));//密碼
postData.add(new BasicNameValuePair("Textbox1", ""));
postData.add(new BasicNameValuePair("__VIEWSTATE", __VIEWSTATE));
postData.add(new BasicNameValuePair("hidPdrs", ""));
postData.add(new BasicNameValuePair("hidsc", ""));
postData.add(new BasicNameValuePair("lbLanguage", ""));
postData.add(new BasicNameValuePair("txtSecretCode", code));//驗證碼
postData.add(new BasicNameValuePair("txtUserName", login_xh));//學號
//登錄 post請求
HttpPost post = new HttpPost("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//構建post對象
post.setEntity(new UrlEncodedFormEntity(postData));//捆綁參數
post.setHeader("Accept", "text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8");//帶上參數頁
post.setHeader("Cookie", "safedog-flow-item=");//帶上參數頁
post.setHeader("Connection", "keep-alive");//帶上參數頁
post.setHeader("Content-Type", "application/x-www-form-urlencoded");//帶上參數頁
post.setHeader("Host", "jwxt.hzu.gx.cn");//帶上參數頁
post.setHeader("Origin", "http://jwxt.hzu.gx.cn");//帶上參數頁
post.setHeader("Upgrade-Insecure-Requests", "1");//帶上參數頁
post.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36");//帶上參數頁
post.setHeader("Referer", "http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//帶上referer 參數頁
response = client.execute(post);//執行登陸行為
//登錄成功,發生302重定向
if(302==response.getStatusLine().getStatusCode()){
//把響應結果打印出來
System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
Header header = response.getFirstHeader("location"); // 跳轉的目標地址是在 HTTP-HEAD 中的
String newuri = header.getValue(); // 這就是跳轉后的地址,再向這個地址發出新申請,以便得到跳轉后的信息是啥。
newuri="http://jwxt.hzu.gx.cn/"+newuri;
// System.out.println(newuri);
//登錄成功 get請求
HttpGet get=new HttpGet(newuri);
get.setHeader("Cookie", "safedog-flow-item=");//帶上參數頁
get.setHeader("Host", "jwxt.hzu.gx.cn");//帶上參數頁
get.setHeader("Referer", "http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//帶上referer 參數頁
// client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 2000);
// client.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000);
// 超時設置
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();//設置請求和傳輸超時時間
get.setConfig(requestConfig);
/*
* 第二次身份認證時,程序會卡在這里
*
*/
response = (CloseableHttpResponse) client.execute(get);//執行重定向
//打印輸出
// rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
// System.out.println(rawHtml);
String xsgrxxUrl="http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/";//個人信息a標簽地址
if(200==response.getStatusLine().getStatusCode()){
//使用jsoup來解析響應回來的html 匹配個人信息a標簽地址
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document document = Jsoup.parse(rawHtml);
Elements select_a = document.select("a");
for (Element a : select_a) {
String href = a.attr("href");
if(href.indexOf("xsgrxx.aspx")!=-1){
xsgrxxUrl=xsgrxxUrl+href;
break;
}
}
//查看個人信息 get請求
get=new HttpGet(xsgrxxUrl);
post.setHeader("Cookie", "safedog-flow-item=");//帶上參數頁
post.setHeader("Host", "jwxt.hzu.gx.cn");//帶上參數頁
get.setHeader("Referer", newuri);//帶上referer 參數頁
response = (CloseableHttpResponse) client.execute(get);//執行
}
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
//打印輸出
// System.out.println(rawHtml);
//使用jsoup來解析響應回來的html 匹配所有學生信息
Document document = Jsoup.parse(rawHtml);
Elements select_span = document.select("span");
for (Element span : select_span) {
String id = span.attr("id");
if("xh".equals(id)){//學號
String xh = span.text();
map.put("xh", xh);
// System.out.println("學號:"+xh);
}
if("xm".equals(id)){//姓名
String xm = span.text();
map.put("xm", xm);
// System.out.println("姓名:"+xm);
}
// if("lbl_TELNUMBER".equals(id)){//手機號碼
// String lbl_TELNUMBER = span.text();
// System.out.println("手機號碼:"+lbl_TELNUMBER);
// }
if("lbl_xb".equals(id)){//性別
String lbl_xb = span.text();
map.put("lbl_xb", lbl_xb);
// System.out.println("性別:"+lbl_xb);
}
if("lbl_csrq".equals(id)){//出生日期
String lbl_csrq = span.text();
map.put("lbl_csrq", lbl_csrq);
// System.out.println("出生日期:"+lbl_csrq);
}
if("lbl_byzx".equals(id)){//畢業中學
String lbl_byzx = span.text();
map.put("lbl_byzx", lbl_byzx);
// System.out.println("畢業中學:"+lbl_byzx);
}
if("lbl_mz".equals(id)){//民族
String lbl_mz = span.text();
map.put("lbl_mz", lbl_mz);
// System.out.println("民族:"+lbl_mz);
}
if("lbl_sfzh".equals(id)){//身份證號
String lbl_sfzh = span.text();
map.put("lbl_sfzh", lbl_sfzh);
// System.out.println("身份證號:"+lbl_sfzh);
}
if("lbl_xy".equals(id)){//學院
String lbl_xy = span.text();
map.put("lbl_xy", lbl_xy);
// System.out.println("學院:"+lbl_xy);
}
if("lbl_zymc".equals(id)){//專業
String lbl_zymc = span.text();
map.put("lbl_zymc", lbl_zymc);
// System.out.println("專業:"+lbl_zymc);
}
if("lbl_xzb".equals(id)){//班級
String lbl_xzb = span.text();
map.put("lbl_xzb", lbl_xzb);
// System.out.println("班級:"+lbl_xzb);
}
if("lbl_lys".equals(id)){//所在省份
String lbl_lys = span.text();
map.put("lbl_lys", lbl_lys);
// System.out.println("所在省份:"+lbl_lys);
}
if("jtdz".equals(id)){//家庭住址
String jtdz = span.text();
map.put("jtdz", jtdz);
// System.out.println("家庭住址:"+jtdz);
}
}
//上傳頭像到圖片服務器上
Elements select_img = document.select("img");
String imagUrl = select_img.attr("src");
getPortrait((String)map.get("xh"),"http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/"+imagUrl, xsgrxxUrl);
//ftp上傳到圖片服務器
FileInputStream fileInputStream = new FileInputStream(new File("D:/portrait.jpg"));
CpshResult result = FtpUtil.upload((String)map.get("xh")+"_portrait.jpg", fileInputStream);
if(result.getStatus()==200){
map.put("tx", result.getData()+"");
//把文件刪掉
File file = new File("D:/portrait.jpg");
file.delete();
}else{
System.out.println("頭像上傳失敗!");
}
//成功
map.put("code", "200");
map.put("msg", "驗證成功");
}else if(200==response.getStatusLine().getStatusCode()){//響應狀態200,登錄失敗
//使用jsoup來解析響應回來的html 解析彈窗提示信息
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document document = Jsoup.parse(rawHtml);
Elements select_script = document.select("script");
String msg="";
for (Element script : select_script) {
String html = script.html();
if(html.indexOf("alert")!=-1){
//只保留中文漢字
msg=html.replaceAll("[^\u4E00-\u9FA5]", "");
break;
}
}
//成功
map.put("code", "400");
map.put("msg", msg);
// System.out.println(msg);
}else if(500==response.getStatusLine().getStatusCode()){//
map.put("code", "500");
map.put("msg", "教務系統響應500...");
}
// client.getConnectionManager().shutdown();
// response.close();
return map;
}
/**
* 獲取圖片驗證碼,直接響應回瀏覽器
* @param client
* @return
*/
public static void getVerifyingCode(HttpServletResponse response1){
try {
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/CheckCode.aspx");//驗證碼get
HttpResponse response = client.execute(getVerifyCode);//獲取驗證碼
if(200==response.getStatusLine().getStatusCode()){//200響應碼
//將響應回來的圖片信息writeTo 到 fileOutputStream
response.getEntity().writeTo(response1.getOutputStream());
}
} catch (Exception e) {
e.printStackTrace();
// return 0;
}finally {
}
}
/**
* 獲取圖片驗證碼,下載到本地
* @param client
* @return
*/
public static int getVerifyingCode(){
FileOutputStream fileOutputStream = null;
try {
// HttpClient client = HttpClients.createDefault();//實例化httpclient
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/CheckCode.aspx");//驗證碼get
HttpResponse response;
response = client.execute(getVerifyCode);//獲取驗證碼
if(200==response.getStatusLine().getStatusCode()){//200響應碼
/*驗證碼寫入文件,保存為verifyCode.jped*/
fileOutputStream = new FileOutputStream(new File("D:/verifyCode.gif"));
//將響應回來的圖片信息writeTo 到 fileOutputStream
response.getEntity().writeTo(fileOutputStream);
return 1;
}else{
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 下載頭像圖片
* @param cilent
* @param imagUrl
* @param referer
* @return
*/
public static void getPortrait(String xh,String imagUrl,String referer){
// HttpClient client = HttpClients.createDefault();//實例化httpclient
FileOutputStream fileOutputStream=null;
try {
// HttpClient client = HttpClients.createDefault();//實例化httpclient
HttpGet portrait = new HttpGet(imagUrl);//get請求 頭像照片
//portrait.setHeader("Referer",referer);
HttpResponse response = client.execute(portrait);// 執行
if(200==response.getStatusLine().getStatusCode()){//200響應碼
// /*圖片寫入文件,保存為portrait.jpg*/
File file = new File("D:/portrait.jpg");
file.createNewFile();
fileOutputStream = new FileOutputStream(file);
response.getEntity().writeTo(fileOutputStream);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
可以再控制臺打印出來,我這里是作為layer彈窗:
作者:huanzi-qch
出處:https://www.cnblogs.com/huanzi-qch
若標題中有“轉載”字樣,則本文版權歸原作者所有。若無轉載字樣,本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利.
*請認真填寫需求信息,我們會在24小時內與您取得聯系。