[Java][華為云Java編程創造營][學習筆記][第三階段][04_Java爬蟲實戰][二]

      網友投稿 670 2025-04-02

      1.4,綜合實戰1:Jsoup爬取博客


      綜合實戰1:Jsoup爬取博客(1)

      以CSDN認證的企業博客,華為開發者論壇為例,需要實現的需求:

      獲取博主的博客文章數量

      獲取博主的博客文章列表的頁數

      獲取博主的每篇博客文章的信息(網址,創建時間,標題)

      獲取每篇博客文章中的圖片鏈接

      將所有獲取的數據存儲到數據庫中

      綜合實戰1:Jsoup爬取博客(2)

      步驟:

      1,博主博客網頁分析

      2,項目搭建及環境準備(JDK1.8,IntelliJ IDEA,MySQL5.7.32)

      3,編寫數據獲取,數據處理,數據存儲工具類

      4,主函數完成業務邏輯

      綜合實戰1:Jsoup爬取博客(3)

      1,新建maven工程,新建包com.huawei,新建數據庫配置文件db.properties

      2,在pom.xml導入Jsoup和MySQL

      [Java][華為云Java編程創造營][學習筆記][第三階段][04_Java爬蟲實戰][二]

      4.0.0 org.example tempjava4 1.0-SNAPSHOT 8 8 org.jsoup jsoup 1.14.3 mysql mysql-connector-java 8.0.25

      3,在db.properties配置數據庫信息

      #mysql className=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/db_blog?characterEncoding=utf8 username=填寫數據庫登錄名 password=填寫數據庫密碼

      4,用面向對象的角度來分析需求得出實體類有文章,博主,圖片

      博主對文章,一對多;文章對圖片,一對多

      5,數據庫建表

      如果建立數據庫時沒有選擇UTF8格式,那么存儲中文的時候就會報錯

      create table t_article ( id int auto_increment primary key, b_id varchar(50) null, url varchar(300) null, create_time varchar(50) null, title varchar(300) null ); create table t_blogger ( id varchar(50) not null primary key, article_count int null, page_count int null ); create table t_picture ( id int auto_increment primary key, a_id int null, url varchar(300) null );

      6,實體類Article

      package com.huawei.entity; /* * 文章實體類 * */ public class Article { //文章id private Integer id; //博主id private String bId; //文章的url private String url; //文章的創建時間 private String createTime; //文章的標題 private String title; public Article() { } @Override public String toString() { return "Article{" + "id=" + id + ", bId='" + bId + '\'' + ", url='" + url + '\'' + ", createTime='" + createTime + '\'' + ", title='" + title + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getbId() { return bId; } public void setbId(String bId) { this.bId = bId; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Article(Integer id, String bId, String url, String createTime, String title) { this.id = id; this.bId = bId; this.url = url; this.createTime = createTime; this.title = title; } }

      7,實體類Blogger

      package com.huawei.entity; /* * 博主實體類 * */ public class Blogger { //博主id private String id; //博主博客文章的數量 private Integer articleCount; //博客文章的總頁面數 private Integer pageCount; public Blogger() { } public Blogger(String id, Integer articleCount, Integer pageCount) { this.id = id; this.articleCount = articleCount; this.pageCount = pageCount; } @Override public String toString() { return "Blogger{" + "id='" + id + '\'' + ", articleCount=" + articleCount + ", pageCount=" + pageCount + '}'; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Integer getArticleCount() { return articleCount; } public void setArticleCount(Integer articleCount) { this.articleCount = articleCount; } public Integer getPageCount() { return pageCount; } public void setPageCount(Integer pageCount) { this.pageCount = pageCount; } }

      8,實體類Picture

      package com.huawei.entity; /* * 圖片實體類 * */ public class Picture { //圖片id private Integer id; //文章id private Integer aId; //圖片的url private String url; public Picture() { } @Override public String toString() { return "Picture{" + "id=" + id + ", aId=" + aId + ", url='" + url + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getaId() { return aId; } public void setaId(Integer aId) { this.aId = aId; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Picture(Integer id, Integer aId, String url) { this.id = id; this.aId = aId; this.url = url; } }

      9,工具類BlogUtil

      package com.huawei.util; import com.huawei.entity.Article; import com.huawei.entity.Picture; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; import java.util.ArrayList; import java.util.List; /* * 博客數據爬取工具類 * */ public class BlogUtil { /* * 獲取博客文章數量 * */ public static int getArticleCount(String blogHome) { //1,獲取文檔對象 Document doc = null; try { doc = Jsoup.connect(blogHome).get(); } catch (IOException e) { e.printStackTrace(); } //2,查找包含博客數量的元素 Element countElement = doc.select("span.count").first(); //3,取出元素包含的文本,這里為博客數量 String articleCount = countElement.text(); return Integer.parseInt(articleCount); } /* * 獲得博客文章頁數 * */ public static int getArticlePageCount(int articleCount) { //向上取整,獲得頁面數量 int pageCount = (int) Math.ceil(articleCount / Constants.PAGE_SIZE); return pageCount; } /* * 獲取博客列表 * */ public static List

      getArticleList(int pageBegin, int pageEnd, String blogHome, String bId) { //1,創建博客列表 ArrayList
      articles = new ArrayList<>((pageEnd - pageBegin + 1) * ((int) Constants.PAGE_SIZE)); //2,定義變量:博客列表的網址 String articleListUrl = null; for (int i = pageBegin; i <= pageEnd; i++) { //拼接URL articleListUrl = blogHome + Constants.ARTICLE_LIST_URI + i; //1,獲取document對象 Document doc = null; try { doc = Jsoup.connect(articleListUrl).get(); } catch (IOException e) { e.printStackTrace(); } //2,查找包含博客列表的元素 Element articleList = doc.select("div.article-list").first(); //3,查找每篇博客的元素 Elements articleElements = articleList.select("div.article-item-box.csdn-tracking-statistics"); for (Element element : articleElements) { //獲取文章的URL String url = element.select("h4>a").first().attr("href"); //獲取文章的標題 String title = element.select("h4>a").first().text().substring(3);//獲取標題后去除前面的"原創 ",共3個字符 //獲取文章的創建時間 String createTime = element.select("span.date").first().text(); Article article = new Article(); article.setUrl(url); article.setTitle(title); article.setCreateTime(createTime); article.setbId(bId); articles.add(article); } } return articles; } /* * 獲取博客圖片 * */ public static List getArticlePictures(String articleUrl) { ArrayList pictures = new ArrayList<>(); //1,獲取文檔對象 Document doc = null; try { doc = Jsoup.connect(articleUrl).get(); } catch (IOException e) { e.printStackTrace(); } //2,獲取文章元素下面的所有圖片元素,并進行遍歷 Element article = doc.select("article.baidu_pl").first(); Elements images = article.select("img"); for (Element image : images) { String picUrl = image.attr("src"); Picture picture = new Picture(); picture.setUrl(picUrl); pictures.add(picture); } return pictures; } }

      10,工具類Constants

      package com.huawei.util; /* * 常量類 * */ public class Constants { //定義常量字符串 /* * BLOG_HOME:華為開發者論壇 https://hwdevelopers.blog.csdn.net/ * */ public static final String BLOG_HOME="https://hwdevelopers.blog.csdn.net"; /* * 博客文章列表拼接url,注意:如果BLOG_HOME的尾部加上了 / ,那么下方的頭部就不要加上 / * */ public static final String ARTICLE_LIST_URI="/article/list/"; /* * 頁面博客數量 * */ public static final double PAGE_SIZE=40.0; }

      11,工具類JDBCUtils

      package com.huawei.util; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; /* * JDBC工具類 * */ public class JDBCUtils { //創建全局屬性 private static String className; private static String url; private static String username; private static String password; static { //加載配置文件,獲取連接信息 Properties properties = new Properties(); try { InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties"); //讀取配置文件,獲取信息 properties.load(in); //根據key獲取value className = properties.getProperty("className"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); } catch (IOException e) { e.printStackTrace(); } } static { //加載驅動程序 try { Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //獲取數據庫連接對象 public static Connection getConn() { try { return DriverManager.getConnection(url, username, password); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("數據庫連接錯誤!"); } } //關閉連接,釋放資源 public static void closeAll(Connection conn, Statement stat, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } //方法重載 public static void closeAll(Connection conn, PreparedStatement pstmt) { if (pstmt != null) { try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static ResultSet executeQuery(String preparedSql, Object... param) { Connection conn = null; PreparedStatement pstmt = null; ResultSet res = null; /*處理SQL,執行SQL*/ try { conn = getConn();//得到數據庫連接 pstmt = conn.prepareStatement(preparedSql);//得到PreparedStatement對象 if (param != null) { for (int i = 0; i < param.length; i++) { pstmt.setObject(i + 1, param[i]);//為預編譯sql設置參數 } } res = pstmt.executeQuery();//執行SQL語句 } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.closeAll(conn, pstmt, res); } return res; } public static int executeUpdate(String preparedSql, Object... param) { Connection conn = null; PreparedStatement pstmt = null; int key = 0;//主鍵 /*處理SQL,執行SQL*/ try { conn = getConn();//得到數據庫連接 //注意:MySQL5.1.7需要顯式添加一個參數Statement.RETURN_GENERATED_KEYS pstmt = conn.prepareStatement(preparedSql,Statement.RETURN_GENERATED_KEYS);//得到PreparedStatement對象 if (param != null) { for (int i = 0; i < param.length; i++) { pstmt.setObject(i + 1, param[i]);//為預編譯SQL設置參數 } } pstmt.executeUpdate();//執行SQL語句 ResultSet resultSet = pstmt.getGeneratedKeys(); if (resultSet.next()) { key = resultSet.getInt(1);//獲取主鍵返回 } } catch (SQLException e) { e.printStackTrace();//處理異常 } finally { JDBCUtils.closeAll(conn, pstmt); } return key; } }

      12,工具類StringUtil

      package com.huawei.util; /* * 字符串工具類 * */ public class StringUtil { /* * 博主id處理 * */ public static String subId(String url)//url為博客網址 { if (url != null && url.trim().length() != 0)//非空判斷 { /*int index = url.lastIndexOf("/");//切割博主id String id = url.substring(index + 1); return id;*/ int index1=url.indexOf("https://"); int index2 = url.indexOf("."); String id = url.substring(index1, index2); id = id.replace("https://", ""); return id; } else { return ""; } } }

      13,啟動類Main

      package com; import com.huawei.entity.Article; import com.huawei.entity.Blogger; import com.huawei.entity.Picture; import com.huawei.util.BlogUtil; import com.huawei.util.Constants; import com.huawei.util.JDBCUtils; import com.huawei.util.StringUtil; import java.util.List; public class Main { public static String insertBlogger = "insert into t_blogger(id,article_count,page_count) value(?,?,?)"; public static String insertArticle = "insert into t_article(b_id,url,create_time,title) value(?,?,?,?)"; public static String insertPicture = "insert into t_picture(a_id,url) value(?,?)"; public static void main(String[] args) { int articleCount = BlogUtil.getArticleCount(Constants.BLOG_HOME); int pageCount = BlogUtil.getArticlePageCount(articleCount); //博主對象 Blogger blogger = new Blogger(StringUtil.subId(Constants.BLOG_HOME), articleCount, pageCount); System.out.println(blogger); JDBCUtils.executeUpdate(insertBlogger, blogger.getId(), blogger.getArticleCount(), blogger.getPageCount()); //文章列表 List

      articleList = BlogUtil.getArticleList( 1, 2, Constants.BLOG_HOME, StringUtil.subId(Constants.BLOG_HOME)); for (Article article : articleList) { System.out.println(article); final int aid = JDBCUtils.executeUpdate(insertArticle, article.getbId(), article.getUrl(), article.getCreateTime(), article.getTitle()); //圖片列表 List pictures = BlogUtil.getArticlePictures(article.getUrl()); for (Picture picture : pictures) { System.out.println(picture); JDBCUtils.executeUpdate(insertPicture, aid, picture.getUrl()); } } } }

      Java

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Java并發編程的藝術》 —3.2.4 重排序對多線程的影響
      下一篇:word怎么算平均值(word上怎么算平均值)
      相關文章
      亚洲精品午夜在线观看| 亚洲激情在线观看| 91亚洲精品视频| 情人伊人久久综合亚洲| 亚洲欧洲日产国码av系列天堂| 亚洲综合久久夜AV | 亚洲国产精品综合久久一线 | 国产v亚洲v天堂无码网站| 久久久久亚洲AV无码专区桃色| 亚洲精品第一国产综合境外资源 | 国产91成人精品亚洲精品| 色偷偷亚洲男人天堂| 亚洲第一se情网站| 国产精品亚洲综合一区在线观看| 国产精品亚洲а∨无码播放麻豆| 亚洲?V无码乱码国产精品| 亚洲婷婷国产精品电影人久久| 亚洲一区二区三区免费| 亚洲综合无码精品一区二区三区| 亚洲一区二区三区香蕉| 亚洲AV永久纯肉无码精品动漫 | 91亚洲精品第一综合不卡播放| 久久久亚洲欧洲日产国码aⅴ| 亚洲一区综合在线播放| 亚洲校园春色小说| 亚洲91精品麻豆国产系列在线| 久久亚洲国产最新网站| 亚洲av无码一区二区三区人妖| 国产精品亚洲精品日韩动图| 亚洲精品第一国产综合精品99| 久久亚洲精品无码观看不卡| 亚洲精品无码成人AAA片| 亚洲av激情无码专区在线播放| 亚洲综合图片小说区热久久| 亚洲人精品亚洲人成在线| 国产精品亚洲专区无码唯爱网 | 亚洲网站视频在线观看| 亚洲午夜一区二区三区| 少妇亚洲免费精品| 亚洲中文字幕无码中文字在线| 亚洲大片在线观看|