日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java爬取app_Java实现爬虫给App提供数据(Jsoup 网络爬虫)

發(fā)布時間:2023/12/20 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java爬取app_Java实现爬虫给App提供数据(Jsoup 网络爬虫) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

需求 ##

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

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

效果圖

下圖是原站點的頁面

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

爬蟲思路

Created with Rapha?l 2.1.0開始基于Get請求獲取URL對于的網(wǎng)頁Html利用Jsoup把Html解析為Document利用Dom的getElementsById等方法獲取標(biāo)題、公布時間、內(nèi)容等依據(jù)標(biāo)題、公布時間、內(nèi)容構(gòu)建javabean給APP使用結(jié)束

關(guān)于 App 的實現(xiàn)過程能夠參看這幾篇文章,本文主要解說一下怎樣爬蟲數(shù)據(jù)。

Jsoup 簡單介紹

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

Jsoup主要有以下功能:

- 從一個URL,文件或字符串中解析HTML。

- 使用DOM或CSS選擇器來查找、取出數(shù)據(jù);

- 對HTML元素、屬性、文本進行操作;

- 清除不受信任的HTML (來防止XSS攻擊)

爬蟲過程

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

新聞網(wǎng)頁Html的DOM樹例如以下所看到的:

以下這段代碼依據(jù)指定的 url,用代碼獲取get 請求返回的 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請求失敗");

}

return html;

}

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

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)題對于的html 代碼:

關(guān)于舉辦《經(jīng)典音樂作品贊賞與人文審美》講座的通知

我們須要從上面的 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();

獲取公布日期、信息來源

相同找出對于的 HTML 代碼

2015-05-28

來源:

瀏覽次數(shù): 477

思路也和上面相似。使用 getElementById(String id) 方法找出id="article_detail"為Element。再利用getElementsByTag獲取span 部分。由于一共同擁有3個 ... ,所以返回的是Elements而不是Element。

// article_detail包含了 2016-01-15 來源: 瀏覽次數(shù):177

Element detailEle = articleEle.getElementById("article_detail");

Elements details = detailEle.getElementsByTag("span");

// 公布時間

String dateStr = details.get(0).text();

// 新聞來源

String sourceStr = details.get(1).text();

解析瀏覽次數(shù)

假設(shè)打印出上面的details.get(2).text(),僅僅會得到

瀏覽次數(shù):

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

由于瀏覽次數(shù)是JavaScript 渲染出來的。 Jsoup爬蟲可能僅僅提取HTML內(nèi)容,得不到動態(tài)渲染出的數(shù)據(jù)。

解決方法有兩種

在爬蟲的時候,內(nèi)置一個瀏覽器內(nèi)核,運行js渲染頁面后。再抓取。

所以分析JS請求,找到相應(yīng)數(shù)據(jù)的請求url

假設(shè)你訪問上面的 urlhttp://see.xidian.edu.cn/index.php/news/click/id/7428。會得到以下的結(jié)果

document.write(478)

這個478就是我們須要的瀏覽次數(shù)。我們對上面的url做get 請求,得到返回的字符串。利用正則找出當(dāng)中的數(shù)字。

// 訪問這個新聞頁面。瀏覽次數(shù)會+1,次數(shù)是 JS 渲染的

String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);

int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));

// 或者使用以下這個正則方法

// 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();

// 假設(shè)用 text()方法。新聞主體內(nèi)容的 html 標(biāo)簽會丟失

// 為了在 Android 上用 WebView 顯示 html,用toString()

// String contentStr = contentEle.text();

解析圖片 Url

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

Element contentEle = articleEle.getElementById("article_content");

// 新聞主體內(nèi)容

String contentStr = contentEle.toString();

// 假設(shè)用 text()方法,新聞主體內(nèi)容的 html 標(biāo)簽會丟失

// 為了在 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");

}

新聞實體類 JavaBean

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

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

+ "]";

}

}

測試

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");

// 公布時間

String dateStr = details.get(0).text();

// 新聞來源

String sourceStr = details.get(1).text();

// 訪問這個新聞頁面。瀏覽次數(shù)會+1,次數(shù)是 JS 渲染的

String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);

int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));

// 或者使用以下這個正則方法

// String readTimesStr = jsStr.replaceAll("[^0-9]", "");

Element contentEle = articleEle.getElementById("article_content");

// 新聞主體內(nèi)容

String contentStr = contentEle.toString();

// 假設(shè)用 text()方法,新聞主體內(nèi)容的 html 標(biāo)簽會丟失

// 為了在 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級開展“讓誠信之花開遍冬日校園”教育活動,

publishDate=2016-01-14,

source=來源: 電影新聞網(wǎng),

readTimes=200,

body=

西電新聞網(wǎng)訊?(通訊員 丁彤 王朱丹...)

展望

本文解說了怎樣實現(xiàn)Jsoup 網(wǎng)絡(luò)爬蟲。假設(shè)文章對您有幫助,感謝捐贈。

近期用 Material Design 重構(gòu)了自己的新聞 App,新聞數(shù)據(jù)是利用 Jsoup 實現(xiàn)的。

第1版爬蟲是在手機端實現(xiàn)的(我承認這設(shè)計非常不好,既費流量又添加client負擔(dān)),后來在新浪云上實現(xiàn)了一個簡單的 JSP 。過濾了原網(wǎng)頁的圖片、一級欄目等,僅僅返回新聞標(biāo)題、閱讀次數(shù)、新聞內(nèi)容等等。

后期的打算是把爬蟲這步移到新浪云上,返回格式化的 JSON 數(shù)據(jù)給client使用。

可能的話,圖片使用七牛CDN(Content Delivery Network 內(nèi)容分發(fā)網(wǎng)絡(luò))。在云上利用 Mysql 數(shù)據(jù)庫緩存新聞信息。

參考文章

總結(jié)

以上是生活随笔為你收集整理的java爬取app_Java实现爬虫给App提供数据(Jsoup 网络爬虫)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。