文章目錄
-
- 0.準備工作
- 1. 分析
- 2. 構思
- 3. 程式設計
-
- 3.1 定義一個bean,用于儲存電影的資料
- 3.2 按照之前的構思進行程式設計
- 4.效果圖
- 5.擷取資源
-
- 5.1GitHub
- 5.2百度雲
0.準備工作
下載下傳jsoup的jar包,有兩種方式:
- 使用maven架構進行建構
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
- 到 https://mvnrepository.com/artifact/org.jsoup/jsoup 下載下傳jar包(jsoup-1.12.1.jar),然後加到類路徑中。
1. 分析
豆瓣電影top25的第一個頁面網址是 https://movie.douban.com/top250,我們檢查該網頁(google浏覽器:ctrl+shift+c)可以發現,ol标簽後面 li 标簽即為每個電影的内容。

以下是格式化了的li标簽的内容:(這是第一個電影《肖申克的救贖》)
<li>
<div class="item">
<div class="pic">
<em class="">1</em>
<a href="https://movie.douban.com/subject/1292052/">
<img width="100" alt="肖申克的救贖"
src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
</a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救贖</span> <span class="title"> / The Shawshank Redemption</span> <span
class="other"> / 月黑高飛(港) / 刺激1995(台)</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p class="">
導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...
<br>
1994 / 美國 / 犯罪 劇情
</p>
<div class="star">
<span class="rating5-t"></span> <span class="rating_num" property="v:average">9.7</span> <span
property="v:best" content="10.0"></span> <span>1539997人評價</span>
</div>
<p class="quote">
<span class="inq">希望讓人自由。</span>
</p>
</div>
</div>
</div>
</li>
之後的工作基本上圍繞這段代碼來開展。
2. 構思
講代碼之前我們要現有思路,下面是我的思路:
- 擷取“單頁-一個電影”的資料
- 擷取“單頁-所有電影-25個”的資料
- 擷取“所有頁面-所有電影-25+10=250個”的資料
雖然這和我一開始想法有些差異,但是方向是一樣的。
3. 程式設計
3.1 定義一個bean,用于儲存電影的資料
定義Movie類,用于儲存電影的相關資料。包含:排名,電影名,電影的豆瓣頁網址,(國家,放映年份),平均評分,評價人數,引用(一句話評語)。
注意:為了友善在控制台檢視資料和儲存資料,這裡定義了兩個tostring方法,第一個是自動生成的,便于在控制台檢視資料;第二個是自己定義的,為了友善儲存資料到本地txt,如果你需要儲存TXT檔案,請選擇第二種形式。
Movie.java
代碼:
/**
* @Title Movie.java
* @Package xyz.yansheng.top250
* @Description TODO
* @author yansheng
* @date 2019-08-12 15:34:16
* @version v1.0
*/
package xyz.yansheng.top250;
/**
* <p>Title: Movie</p>
* <p>Description: 定義Movie類,用于儲存電影的相關資料。包含:排名,電影名,電影的豆瓣頁網址,(國家,放映年份),平均評分,評價人數,引用(一句話評語)。</p>
* <p>Company: </p>
* @author yansheng
* @date 2019-08-12 15:34:16
* @version v1.0
*/
public class Movie {
// 排名,電影名,電影的豆瓣頁網址,(國家,放映年份),平均評分,評價人數,引用(一句話評語)
private Integer rank;
private String title;
private String url;
private Double ratingNum;
private Integer ratingPeopleNum;
private String quote;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void setRank(Integer rank) {
this.rank = rank;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Double getRatingNum() {
return ratingNum;
}
public void setRatingNum(Double ratingNum) {
this.ratingNum = ratingNum;
}
public Integer getRatingPeopleNum() {
return ratingPeopleNum;
}
public void setRatingPeopleNum(Integer ratingPeopleNum) {
this.ratingPeopleNum = ratingPeopleNum;
}
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = quote;
}
@Override
public String toString() {
// 形式1.為了友善控制台列印
return "Movie [rank=" + rank + ", title=" + title + ", url=" + url + ", ratingNum=" + ratingNum
+ ", ratingPeopleNum=" + ratingPeopleNum + ", quote=" + quote + "]";
// 形式2.為了友善儲存資料到本地txt
// 在将資料寫到本地txt儲存時,建議用下面這個格式,資料比較幹淨,有利用導入到資料庫等。
//return rank + "," + title + "," + url + "," + ratingNum + "," + ratingPeopleNum + "," + quote + "\n";
}
}
3.2 按照之前的構思進行程式設計
為了友善起見,我直接将這個方法定義在一個類中。所有方法在main方法裡面進行測試,可以按照方法進行測試。
注意:方法4,選用第二種tostring方法(上面有提到的)。
下面這個是
CrawlMovie.java
檔案中的
main()
方法,先看這個測試代碼,你會比較容易了解主要的幾個方法的作用:
public static void main(String[] args) {
// 1.擷取“單頁-一個電影”的資料
// 測試方法:Movie crawlMovie()
// crawlMovie();
// 2.擷取“單頁-所有電影-25個”的資料
// 測試方法:Movie crawlMovie()
/*final String URL = "https://movie.douban.com/top250";
ArrayList<Movie> movies2 = crawlMovies(URL);
for (Movie movie : movies2) {
System.out.println(movie.toString());
}*/
// 3.擷取“所有頁面-所有電影-25+10=250個”的資料
// 測試方法:ArrayList<Movie> crawlAllMovies()
ArrayList<Movie> movies3 = crawlAllMovies();
for (Movie movie : movies3) {
System.out.println(movie.toString());
}
// 4.為了簡單起見,這裡僅僅是将資料儲存為txt檔案,不儲存到excel或者是資料庫。
// 測試方法:void writeMovie(ArrayList<Movie> movies)
writeMoviesToTxt(movies3);
}
CrawlMovie.java
的所有代碼:
/**
* @Title CrawlMovie.java
* @Package xyz.yansheng.top250
* @Description TODO
* @author yansheng
* @date 2019-08-12 15:47:06
* @version v1.0
*/
package xyz.yansheng.top250;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Company: </p>
* @author yansheng
* @date 2019-08-12 15:47:06
* @version v1.0
*/
public class CrawlMovie {
/**
* @Title main
* @author yansheng
* @version v1.0
* @date 2019-08-12 15:47:06
* @Description 爬取豆瓣電影top250:https://movie.douban.com/top250
*/
public static void main(String[] args) {
// 1.擷取“單頁-一個電影”的資料
// 測試方法:Movie crawlMovie()
// crawlMovie();
// 2.擷取“單頁-所有電影-25個”的資料
// 測試方法:Movie crawlMovie()
/*final String URL = "https://movie.douban.com/top250";
ArrayList<Movie> movies2 = crawlMovies(URL);
for (Movie movie : movies2) {
System.out.println(movie.toString());
}*/
// 3.擷取“所有頁面-所有電影-25+10=250個”的資料
// 測試方法:ArrayList<Movie> crawlAllMovies()
ArrayList<Movie> movies3 = crawlAllMovies();
for (Movie movie : movies3) {
System.out.println(movie.toString());
}
// 4.為了簡單起見,這裡僅僅是将資料儲存為txt檔案,不儲存到excel或者是資料庫。
// 測試方法:void writeMovie(ArrayList<Movie> movies)
writeMoviesToTxt(movies3);
}
// 1.擷取“單頁-一個電影”的資料
public static void crawlMovie() {
// 1.擷取網頁
final String URL = "https://movie.douban.com/top250";
Document document = null;
try {
document = Jsoup.connect(URL).get();
} catch (IOException e) {
e.printStackTrace();
}
// System.out.println("document:" + document);
Movie movie = new Movie();
// 2.選擇具體的電影的項,注意first方法,這裡先隻選取第一個進行測試
Element itemElement = document.select("ol li").first();
// System.out.println("item:" + item.toString());
// 3.1電影排名
Element rankElement = itemElement.selectFirst("em");
String rankString = rankElement.text();
System.out.println("rankString:" + rankString.toString());
movie.setRank(new Integer(rankString));
// 3.2電影網址
Element urlElement = itemElement.select("div.hd a").first();
String urlString = urlElement.attr("href");
System.out.println("urlString:" + urlString.toString());
movie.setUrl(urlString);
// 3.3電影名
Element titleElement = urlElement.select("span.title").first();
String titleString = titleElement.text();
System.out.println("titleString:" + titleString.toString());
movie.setTitle(titleString);
// 3.4評分
Element ratingNumElement = itemElement.select("div.star span.rating_num").first();
String ratingNumString = ratingNumElement.text();
System.out.println("ratingNumString:" + ratingNumString.toString());
movie.setRatingNum(new Double(ratingNumString));
// 3.5評價人數
Element ratingPeopleNumElement = itemElement.select("div.star span").last();
String ratingPeopleNumString = ratingPeopleNumElement.text();
System.out.println("ratingPeopleNumString:" + ratingPeopleNumString.toString());
// 注意這裡文本是:1539997人評價,我們需要選取其中人數,進行裁剪
movie.setRatingPeopleNum(
new Integer(ratingPeopleNumString.substring(0, ratingPeopleNumString.length() - 3)));
// 3.6 一句話簡評
Element quoteElement = itemElement.select("p.quote span.inq").first();
String quoteString = quoteElement.text();
System.out.println("quoteString:" + quoteString.toString());
movie.setQuote(quoteString);
System.out.println(movie.toString());
}
// 2.擷取“單頁-所有電影-25*1=25個”的資料
public static ArrayList<Movie> crawlMovies(String URL) {
// 1.擷取網頁
//final String URL = "https://movie.douban.com/top250";
Document document = null;
try {
document = Jsoup.connect(URL).get();
} catch (IOException e) {
e.printStackTrace();
}
// System.out.println("document:" + document);
// 2.選擇具體的電影的項,注意這裡和上面第一個不同,這裡是選取的所有電影的項
Elements itemElement = document.select("ol li");
ArrayList<Movie> movies = new ArrayList<Movie>(25);
for (Element element : itemElement) {
Movie movie = new Movie();
// 3.1電影排名
Element rankElement = element.selectFirst("em");
String rankString = rankElement.text();
movie.setRank(new Integer(rankString));
// 3.2電影網址
Element urlElement = element.select("div.hd a").first();
String urlString = urlElement.attr("href");
movie.setUrl(urlString);
// 3.3電影名
Element titleElement = urlElement.select("span.title").first();
String titleString = titleElement.text();
movie.setTitle(titleString);
// 3.4評分
Element ratingNumElement = element.select("div.star span.rating_num").first();
String ratingNumString = ratingNumElement.text();
movie.setRatingNum(new Double(ratingNumString));
// 3.5評價人數
Element ratingPeopleNumElement = element.select("div.star span").last();
String ratingPeopleNumString = ratingPeopleNumElement.text();
movie.setRatingPeopleNum(
new Integer(ratingPeopleNumString.substring(0, ratingPeopleNumString.length() - 3)));
// 3.6 一句話簡評
Element quoteElement = element.select("p.quote span.inq").first();
// 注意:這裡可能會沒有簡評,如125的《我不是藥神》,字元串會為null,如果是null,置為空字元串,否則會出現NPE問題
String quoteString = null;
if (quoteElement == null) {
quoteString = "";
} else {
quoteString = quoteElement.text();
}
movie.setQuote(quoteString);
movies.add(movie);
}
return movies;
}
// 3.擷取“所有頁面-所有電影-25+10=250個”的資料
public static ArrayList<Movie> crawlAllMovies() {
ArrayList<Movie> movies = new ArrayList<Movie>(250);
/*注意檢視網址之間的特點,然後拼接字元串:
* 第1頁. https://movie.douban.com/top250
* 2. https://movie.douban.com/top250?start=25&filter=
* 3. https://movie.douban.com/top250?start=50&filter=
*
* 通過觀察我們可以發現:(如果有懷疑直接到浏覽器測試拼接的網址是否正确)
* (1)前面都是一樣的:“https://movie.douban.com/top250”,
* (2)後面加一個查詢串:“?start=25*(-1)”,其中i表示頁數,根據意思我們可以知道其實是:指定指定該頁是從排名第幾的電影開始,
* 即如果是“?start=20”,那麼該頁第一個就是21。
* (3)按照(2)的意思,其實第一個頁面就是:https://movie.douban.com/top250?start=0&filter=
* (4)而最後面的"&filter=",其實有沒有都無所謂。
*/
String prefix = "https://movie.douban.com/top250";
// 為了友善起見我先将網址拼接好,後面直接就可以用了
ArrayList<String> urlList = new ArrayList<String>(10);
for (int i = 0; i < 11; i++) {
String url = prefix + "?start=" + new Integer(i * 25).toString() + "&filter=";
urlList.add(url);
}
// 這裡直接調用上面的方法2(找到每頁的電影),将得到的(25個電影)集合添加到(250個電影)集合,通過循環周遊10個頁面。
for (String url : urlList) {
movies.addAll(crawlMovies(url));
}
return movies;
}
// 4.為了簡單起見,這裡僅僅是将資料儲存為txt檔案,不儲存到excel或者是資料庫。
public static void writeMoviesToTxt(ArrayList<Movie> movies) {
// 4.1 先将每個電影對象轉化為字元串
ArrayList<String> moviesString = new ArrayList<String>(250);
for (Movie movie : movies) {
moviesString.add(movie.toString());
}
// 4.2寫位元組流
try (FileOutputStream out = new FileOutputStream("豆瓣電影top250.txt");) {
for (String string : moviesString) {
out.write(string.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.效果圖
- 控制台輸出:(部分截圖)
jsoup爬取豆瓣電影top250 - 儲存的txt檔案:(部分截圖)
jsoup爬取豆瓣電影top250 - 處理後的excel表格資料:(部分截圖)
jsoup爬取豆瓣電影top250
通過觀察我們可以發現,不是評分高排名就靠前!!
5.擷取資源
5.1GitHub
github倉庫:https://github.com/yansheng836/jsoup-test#user-content-2-爬取豆瓣電影top250
5.2百度雲
資源清單:
說明:
- Excel表格資料是經過處理的,該程式沒有實作該功能(儲存資料到excel的功能)。
-
是mysql資料庫的一個表的轉儲sql檔案,直接在mysql執行該檔案可得到以資料庫表:movie.sql
jsoup爬取豆瓣電影top250
百度雲盤連結:https://pan.baidu.com/s/1fXr8psMndIzdu5r656m1ow
提取碼:f36z