最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)爬蟲給App提供數(shù)據(jù)(Jsoup 網(wǎng)絡(luò)爬蟲)

 更新時(shí)間:2020年07月31日 11:57:06   作者:學(xué)習(xí)編程知識(shí)  
這篇文章主要介紹了Java實(shí)現(xiàn)爬蟲給App提供數(shù)據(jù),即Jsoup 網(wǎng)絡(luò)爬蟲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、需求

最近基于 Material Design 重構(gòu)了自己的新聞 App,數(shù)據(jù)來源是個(gè)問題。

有前人分析了知乎日?qǐng)?bào)、鳳凰新聞等 API,根據(jù)相應(yīng)的 URL 可以獲取新聞的 JSON 數(shù)據(jù)。為了鍛煉寫代碼能力,筆者打算爬蟲新聞頁面,自己獲取數(shù)據(jù)構(gòu)建 API。

二、效果圖

下圖是原網(wǎng)站的頁面

爬蟲獲取了數(shù)據(jù),展示到 APP 手機(jī)端

三、爬蟲思路

關(guān)于App 的實(shí)現(xiàn)過程可以參看這幾篇文章,本文主要講解一下如何爬蟲數(shù)據(jù)。

Android下錄制App操作生成Gif動(dòng)態(tài)圖的全過程 ://m.fzitv.net/article/78236.htm
學(xué)習(xí)Android Material Design(RecyclerView代替ListView)://m.fzitv.net/article/78232.htm
Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易新聞的頁面(RecyclerView )://m.fzitv.net/article/78230.htm

Jsoup 簡(jiǎn)介

Jsoup 是一個(gè) Java 的開源HTML解析器,可直接解析某個(gè)URL地址、HTML文本內(nèi)容。

Jsoup主要有以下功能:

  • - 從一個(gè)URL,文件或字符串中解析HTML;
  • - 使用DOM或CSS選擇器來查找、取出數(shù)據(jù);
  • - 對(duì)HTML元素、屬性、文本進(jìn)行操作;
  • - 清除不受信任的HTML (來防止XSS攻擊)

四、爬蟲過程

Get 請(qǐng)求獲取網(wǎng)頁 HTML

新聞網(wǎng)頁Html的DOM樹如下所示:

下面這段代碼根據(jù)指定的 url,用代碼獲取get 請(qǐng)求返回的 html 源代碼。

public static String doGet(String urlStr) throws CommonException {
 URL url;
 String html = "";
 try {
 url = new URL(urlStr);
 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 connection.setRequestMethod("GET");
 connection.setConnectTimeout(5000);
 connection.setDoInput(true);
 connection.setDoOutput(true);
 if (connection.getResponseCode() == 200) {
 InputStream in = connection.getInputStream();
 html = StreamTool.inToStringByByte(in);
 } else {
 throw new CommonException("新聞服務(wù)器返回值不為200");
 }
 } catch (Exception e) {
 e.printStackTrace();
 throw new CommonException("get請(qǐng)求失敗");
 }
 return html;
}

InputStream in = connection.getInputStream();將得到輸入流轉(zhuǎn)化為字符串是個(gè)普遍需求,我們將其抽象出來,寫一個(gè)工具方法。

public class StreamTool {
 public static String inToStringByByte(InputStream in) throws Exception {
 ByteArrayOutputStream outStr = new ByteArrayOutputStream();
 byte[] buffer = new byte[1024];
 int len = 0;
 StringBuilder content = new StringBuilder();
 while ((len = in.read(buffer)) != -1) {
 content.append(new String(buffer, 0, len, "UTF-8"));
 }
 outStr.close();
 return content.toString();
 }
}

五、解析 HTML 獲取標(biāo)題

利用 google 瀏覽器的審查元素,找出新聞標(biāo)題對(duì)于的html 代碼:

<div id="article_title">
 <h1>
 <a >
 關(guān)于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知
 </a>
 </h1>
</div>

我們需要從上面的 HTML 中找出id="article_title"的部分,使用 getElementById(String id) 方法

String htmlStr = HttpTool.doGet(urlStr);

// 將獲取的網(wǎng)頁 HTML 源代碼轉(zhuǎn)化為 Document
Document doc = Jsoup.parse(htmlStr);

Element articleEle = doc.getElementById("article");
// 標(biāo)題
Element titleEle = articleEle.getElementById("article_title");
String titleStr = titleEle.text();

六、獲取發(fā)布日期、信息來源

同樣找出對(duì)于的 HTML 代碼

<html>
 <head></head>
 <body>
 <div id="article_detail"> 
 <span> 2015-05-28 </span> 
 <span> 來源: </span> 
 <span> 瀏覽次數(shù): <script language="JavaScript" src="http://see.xidian.edu.cn/index.php/news/click/id/7428">
 </script> 477 </span> 
 </div>
 </body>
</html>

思路也和上面類似,使用 getElementById(String id) 方法找出id="article_detail"為Element,再利用getElementsByTag獲取span 部分。因?yàn)橐还灿?個(gè)<span> ... </span>,所以返回的是Elements而不是Element。

// article_detail包括了 2016-01-15 來源: 瀏覽次數(shù):177
Element detailEle = articleEle.getElementById("article_detail");
Elements details = detailEle.getElementsByTag("span");

// 發(fā)布時(shí)間
String dateStr = details.get(0).text();

// 新聞來源
String sourceStr = details.get(1).text();

七、解析瀏覽次數(shù)

如果打印出上面的details.get(2).text(),只會(huì)得到

瀏覽次數(shù):
沒有瀏覽次數(shù)?為什么呢?

因?yàn)闉g覽次數(shù)是JavaScript 渲染出來的, Jsoup爬蟲可能僅僅提取HTML內(nèi)容,得不到動(dòng)態(tài)渲染出的數(shù)據(jù)。
解決方法有兩種

  • 在爬蟲的時(shí)候,內(nèi)置一個(gè)瀏覽器內(nèi)核,執(zhí)行js渲染頁面后,再抓取。這方面對(duì)應(yīng)的工具有Selenium、HtmlUnit或者PhantomJs。
  • 所以分析JS請(qǐng)求,找到對(duì)應(yīng)數(shù)據(jù)的請(qǐng)求url

如果你訪問上面的 urlhttp://see.xidian.edu.cn/index.php/news/click/id/7428,會(huì)得到下面的結(jié)果

document.write(478)

這個(gè)478就是我們需要的瀏覽次數(shù),我們對(duì)上面的url做get 請(qǐng)求,得到返回的字符串,利用正則找出其中的數(shù)字。

// 訪問這個(gè)新聞頁面,瀏覽次數(shù)會(huì)+1,次數(shù)是 JS 渲染的
String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);
int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));
// 或者使用下面這個(gè)正則方法
// String readTimesStr = jsStr.replaceAll("[^0-9]", "");

八、解析新聞內(nèi)容

本來是獲取新聞內(nèi)容純文字的形式,但后來發(fā)現(xiàn) Android 端也可以顯示 CSS 格式,所以后來內(nèi)容保留了 HTML 格式。

Element contentEle = articleEle.getElementById("article_content");
// 新聞主體內(nèi)容
String contentStr = contentEle.toString();
// 如果用 text()方法,新聞主體內(nèi)容的 html 標(biāo)簽會(huì)丟失
// 為了在 Android 上用 WebView 顯示 html,用toString()
// String contentStr = contentEle.text();

九、解析圖片 Url

注意一個(gè)網(wǎng)頁上大大小小的圖片很多,為了只獲取新聞?wù)闹械膬?nèi)容,我們最好首先定位到新聞內(nèi)容的Element,然后再利用getElementsByTag(“img”)篩選出圖片。

Element contentEle = articleEle.getElementById("article_content");
// 新聞主體內(nèi)容
String contentStr = contentEle.toString();
// 如果用 text()方法,新聞主體內(nèi)容的 html 標(biāo)簽會(huì)丟失
// 為了在 Android 上用 WebView 顯示 html,用toString()
// String contentStr = contentEle.text();

Elements images = contentEle.getElementsByTag("img");
String[] imageUrls = new String[images.size()];
for (int i = 0; i < imageUrls.length; i++) {
 imageUrls[i] = images.get(i).attr("src");
}

十、新聞實(shí)體類 JavaBean

上面獲取了新聞的標(biāo)題、發(fā)布日期、閱讀次數(shù)、新聞內(nèi)容等等,我們自然需要構(gòu)造一個(gè) javabean,把獲取的內(nèi)容封裝進(jìn)實(shí)體類中。

public class ArticleItem {

 private int index;
 private String[] imageUrls;
 private String title;
 private String publishDate;
 private String source;
 private int readTimes;
 private String body;

 public ArticleItem(int index, String[] imageUrls, String title, String publishDate, String source, int readTimes,
 String body) {
 this.index = index;
 this.imageUrls = imageUrls;
 this.title = title;
 this.publishDate = publishDate;
 this.source = source;
 this.readTimes = readTimes;
 this.body = body;
 }

 @Override
 public String toString() {
 return "ArticleItem [index=" + index + ",\n imageUrls=" + Arrays.toString(imageUrls) + ",\n title=" + title
 + ",\n publishDate=" + publishDate + ",\n source=" + source + ",\n readTimes=" + readTimes + ",\n body=" + body
 + "]";
 }


}

測(cè)試

public static ArticleItem getNewsItem(int currentPage) throws CommonException {
 // 根據(jù)后綴的數(shù)字,拼接新聞 url
 String urlStr = ARTICLE_BASE_URL + currentPage + ".html";

 String htmlStr = HttpTool.doGet(urlStr);

 Document doc = Jsoup.parse(htmlStr);

 Element articleEle = doc.getElementById("article");
 // 標(biāo)題
 Element titleEle = articleEle.getElementById("article_title");
 String titleStr = titleEle.text();

 // article_detail包括了 2016-01-15 來源: 瀏覽次數(shù):177
 Element detailEle = articleEle.getElementById("article_detail");
 Elements details = detailEle.getElementsByTag("span");

 // 發(fā)布時(shí)間
 String dateStr = details.get(0).text();

 // 新聞來源
 String sourceStr = details.get(1).text();

 // 訪問這個(gè)新聞頁面,瀏覽次數(shù)會(huì)+1,次數(shù)是 JS 渲染的
 String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);
 int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));
 // 或者使用下面這個(gè)正則方法
 // String readTimesStr = jsStr.replaceAll("[^0-9]", "");

 Element contentEle = articleEle.getElementById("article_content");
 // 新聞主體內(nèi)容
 String contentStr = contentEle.toString();
 // 如果用 text()方法,新聞主體內(nèi)容的 html 標(biāo)簽會(huì)丟失
 // 為了在 Android 上用 WebView 顯示 html,用toString()
 // String contentStr = contentEle.text();

 Elements images = contentEle.getElementsByTag("img");
 String[] imageUrls = new String[images.size()];
 for (int i = 0; i < imageUrls.length; i++) {
 imageUrls[i] = images.get(i).attr("src");
 }

 return new ArticleItem(currentPage, imageUrls, titleStr, dateStr, sourceStr, readTimes, contentStr);

}

public static void main(String[] args) throws CommonException {
 System.out.println(getNewsItem(7928));
}

輸出信息

ArticleItem [index=7928,
 imageUrls=[/uploads/image/20160114/20160114225911_34428.png],
 title=電院2014級(jí)開展“讓誠(chéng)信之花開遍冬日校園”教育活動(dòng),
 publishDate=2016-01-14,
 source=來源: 電影新聞網(wǎng),
 readTimes=200,
 body=<div id="article_content">
 <p style="text-indent:2em;" align="justify"> <strong><span style="font-size:16px;line-height:1.5;">西電新聞網(wǎng)訊</span></strong><span style="font-size:16px;line-height:1.5;">&nbsp;(通訊員</span><strong><span style="font-size:16px;line-height:1.5;"> 丁彤 王朱丹</span></strong><span style="font-size:16px;line-height:1.5;">...)

本文講解了如何實(shí)現(xiàn)Jsoup 網(wǎng)絡(luò)爬蟲,如果文章對(duì)您有幫助,那就給個(gè)贊吧。

相關(guān)文章

  • 詳解mybatis批量插入10萬條數(shù)據(jù)的優(yōu)化過程

    詳解mybatis批量插入10萬條數(shù)據(jù)的優(yōu)化過程

    這篇文章主要介紹了詳解mybatis批量插入10萬條數(shù)據(jù)的優(yōu)化過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • SpringCloud實(shí)現(xiàn)SSO 單點(diǎn)登錄的示例代碼

    SpringCloud實(shí)現(xiàn)SSO 單點(diǎn)登錄的示例代碼

    作為分布式項(xiàng)目,單點(diǎn)登錄是必不可少的,這篇文章主要介紹了SpringCloud實(shí)現(xiàn)SSO 單點(diǎn)登錄的示例代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2019-01-01
  • 簡(jiǎn)單了解Java程序運(yùn)行整體流程

    簡(jiǎn)單了解Java程序運(yùn)行整體流程

    這篇文章主要介紹了簡(jiǎn)單了解Java程序運(yùn)行整體流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java解碼H264格式視頻流中的圖片

    Java解碼H264格式視頻流中的圖片

    這篇文章主要為大家詳細(xì)介紹了Java解碼H264格式視頻流中的圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • SpringBoot整合Redisson的步驟(單機(jī)版)

    SpringBoot整合Redisson的步驟(單機(jī)版)

    Redisson非常適用于分布式鎖,而我們的一項(xiàng)業(yè)務(wù)需要考慮分布式鎖這個(gè)應(yīng)用場(chǎng)景,于是我整合它做一個(gè)初步簡(jiǎn)單的例子(和整合redis一樣)。
    2021-05-05
  • Java中深拷貝和淺拷貝的區(qū)別解析

    Java中深拷貝和淺拷貝的區(qū)別解析

    這篇文章主要介紹了Java中深拷貝和淺拷貝的區(qū)別解析,淺拷貝是源對(duì)象和拷貝對(duì)象的存放地址不同,但被復(fù)制的源對(duì)象的引用類型屬性存放的地址仍然和源對(duì)象的引用類型屬性相同,修改引用類型屬性的屬性會(huì)影響相互影響,需要的朋友可以參考下
    2024-01-01
  • SpringMVC實(shí)現(xiàn)文件上傳和下載的工具類

    SpringMVC實(shí)現(xiàn)文件上傳和下載的工具類

    這篇文章主要為大家詳細(xì)介紹了SpringMVC實(shí)現(xiàn)文件上傳和下載的工具類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Mybatis查詢語句返回對(duì)象和泛型集合的操作

    Mybatis查詢語句返回對(duì)象和泛型集合的操作

    這篇文章主要介紹了Mybatis查詢語句返回對(duì)象和泛型集合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • springboot v2.0.3版本多數(shù)據(jù)源配置方法

    springboot v2.0.3版本多數(shù)據(jù)源配置方法

    這篇文章主要介紹了springboot v2.0.3版本多數(shù)據(jù)源配置方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-11-11
  • SpringBoot集成tensorflow實(shí)現(xiàn)圖片檢測(cè)功能

    SpringBoot集成tensorflow實(shí)現(xiàn)圖片檢測(cè)功能

    TensorFlow名字的由來就是張量(Tensor)在計(jì)算圖(Computational?Graph)里的流動(dòng)(Flow),它的基礎(chǔ)就是前面介紹的基于計(jì)算圖的自動(dòng)微分,本文將給大家介紹Spring?Boot集成tensorflow實(shí)現(xiàn)圖片檢測(cè)功能,需要的朋友可以參考下
    2024-06-06

最新評(píng)論

乐亭县| 石城县| 石河子市| 无为县| 灵璧县| 高清| 沐川县| 井研县| 灵山县| 那曲县| 汕尾市| 隆子县| 太原市| 云龙县| 新巴尔虎右旗| 邵东县| 乐陵市| 克拉玛依市| 迁西县| 会同县| 广安市| 恩施市| 道孚县| 同江市| 林口县| 阳曲县| 宁陕县| 曲周县| 东乡族自治县| 康定县| 黔西县| 八宿县| 静乐县| 中牟县| 勃利县| 巢湖市| 高碑店市| 龙岩市| 金湖县| 遂平县| 靖边县|