前几天的简单写了个利用JSOUP进行JAVA爬虫,里面有谈到后续版本会更新数据库操作,所以这次来更新了。
此次的版本里数据爬取部分新增了[电影主演-star]和[电影评分-score]部分,并对之前的数据提取进行了筛选和优化。
功能部分新增【翻页爬取】(共10页)、【连接数据库】、【向数据库输入数据】以及【打印数据】部分。
老规矩,先上目录
这个逻辑顺序是我参考一个技术大佬的,如果感兴趣可以点击:基于java的网络爬虫框架
首先,main方法,将url传给util获取响应的html文件,然后util将其获得的html文件,传给parse进行解析,获取最终数据,封装在集合中。解析完毕后,数据返回到main,接着main操作db将数据导入到mysql中。
model
用来封装对象,比如我要获取猫眼电影榜单的ID、电影名、电影主演、电影评分、上映时间,则需要在model写入对应的属性。说的直白一些,封装的就是我要操作数据对应的属性名。
(比如对象是猫,则model用来添加猫的属性,比如名字、性别、年龄等)
main
程序起点,也是重点,建立客户端、获取数据、连接数据库、执行数据库语句、存放数据。
util
包括【HTTPUtils】和【URLHandle】
HTTPUtils:响应客户端
URLHandle:将main方法,传过来的url,通过httpclient相关方法,获取需要解析的html文件或者json文件等。
parse
这里面存放的是针对util获取的文件采用Jsoup进行解析,并利用正则表达式将获取的文本数据进行筛选。
db
主要放的是数据库操作文件,里面【MySqlControl】用来连接数据库,对数据库进行增删改查操作等。
这些包网上一搜就能下载到。
不过在这里给大家推荐一个网站Download JAR files ,里面的jar包非常全,以后有需要的jar包直接搜索下载就行。
接下来的实例部分就不特别进行讲解了,看代码注释即可。
myMovie
package model;
public class myMovie {
private int movieRank;//电影排名
private String movieName;//电影名
private String releaseTime;//上映时间
private String star;//电影主演
private String score;//电影评分
public String getStar() {
return star;
}
public void setStar(String star) {
this.star = star;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public int getMovieRank() {
return movieRank;
}
public void setMovieRank(int movieRank) {
this.movieRank = movieRank;
}
public String getMovieName() {
return movieName;
}
public void setMovieName(String movieName) {
this.movieName = movieName;
}
public String getReleaseTime() {
return releaseTime;
}
public void setReleaseTime(String releaseTime) {
this.releaseTime = releaseTime;
}
@Override
public String toString() {
return "myMovie{" +
"movieRank='" + movieRank + '\'' +
", movieName='" + movieName + '\'' +
", releaseTime='" + releaseTime + '\'' +
'}';
}
}
myMovieMain
package Main;
import db.MySqlControl;
import model.myMovie;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import util.URLHandle;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import static db.MySqlControl.getConn;
public class myMovieMain {
/**
* 解析页面,并把数据插入至数据库
*/
public static List<myMovie> getOnePage(String url,List<myMovie> movieList,HttpClient client,Connection c) {
try {
movieList = URLHandle.urlParser(client, url);
//如果数组不为空,将数据插入至数据库
if (movieList != null) {
Object[][] params = new Object[movieList.size()][5];
MySqlControl.insertDate(params, movieList, c);
}else {
try {
System.out.println("准备关闭数据库...");
c.close();
System.out.println("成功关闭数据库.");
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch(ParseException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
}
return movieList;
}
/**
* 数据库操作
*/
public static void databaseControl(Connection c,List<myMovie> movieList){
System.out.println("开始打印数据...");
MySqlControl.printDate(c);
System.out.println("数据库操作执行完毕.");
try {
System.out.println("准备关闭数据库...");
c.close();
System.out.println("成功关闭数据库.");
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
/**
* 初始化
*/
List<myMovie> movieList = null;
//生成客户端
System.out.println("正在生成客户端...");
HttpClient client = HttpClientBuilder.create().build();
System.out.println("客户端生成完毕.");
//连接数据库
Connection c = getConn();
System.out.println("解析url...");
//翻页爬取
for(int i = 0; i < 10 ; i++) {
String offset = String.valueOf(i*10);//将i*10转换为字符串
String url = "https://maoyan.com/board/4?" + "offset=" + offset;
movieList = getOnePage(url,movieList,client,c);
}
System.out.println("所有数据均已插入数据库.");
//对数据库进行操作
databaseControl(c,movieList);
System.out.println("所有操作已完成,结束程序运行.");
}
}
URLHandle
package util;
import model.myMovie;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.util.EntityUtils;
import parse.MovieParse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class URLHandle {
public static List<myMovie> urlParser(HttpClient client, String url) throws IOException {
//创建一个接受数据的数组
List<myMovie> data = new ArrayList<>();
//获取响应资源
HttpResponse response = HTTPUtils.getHtml(client,url);
//获取响应状态码
int statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
if(statusCode == 200) {//200表示成功
//获取响应实体内容,并且将其转换为utf-8形式的字符串编码
String entity = EntityUtils.toString(response.getEntity(),"utf-8");
System.out.println("开始解析...");
data = MovieParse.getData(entity);
System.out.println("URL解析完成.");
} else {
EntityUtils.consume(response.getEntity());//释放资源实体
}
return data;
}
}
HTTPUtils
package util;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.message.BasicHttpResponse;
import java.io.IOException;
public class HTTPUtils {
public static HttpResponse getHtml(HttpClient client, String url){
//获取响应文件,即HTML,采用get方法获取响应数据
HttpGet getMethod = new HttpGet(url);
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
try {
//通过client执行get方法
response = client.execute(getMethod);
} catch (IOException e) {
e.printStackTrace();
} finally {
//getMethod.abort();
}
return response;
}
}
MovieParse
package parse;
import model.myMovie;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MovieParse {
public static List<myMovie> getData(String entity){
List<myMovie> data = new ArrayList<>();
//采用jsoup解析
Document doc = Jsoup.parse(entity);
//根据页面内容分析出需要的元素
Elements elements = doc.select("dl[class=\"board-wrapper\"]").select("dd");
//利用正则表达式对文本内容进行处理
//去掉“主演:”,将主演名字提取出来
String patternStar = "[^\\主演:]\\S*";
Pattern reStar = Pattern.compile(patternStar);
//创建将电影评分的integer和fraction合在一起的字符串
String score = "";
// 将时间信息单独提取出来
String patternTime = "\\d{4}?\\D\\d{2}?\\D\\d{2}|\\d{4}";
Pattern reTime = Pattern.compile(patternTime);
//开始提取关键信息并添加至数组
for(Element element : elements) {
myMovie movie = new myMovie();
//电影排名
movie.setMovieRank(Integer.parseInt(element.select("i.board-index").text()));//class等于board-index的i标签
//电影名
movie.setMovieName(element.select("p[class=\"name\"]").text());//带有class属性的p元素
//电影主演
//movie.setStar(element.select("p[class=\"star\"]").text());
Matcher mStar = reStar.matcher(element.select("p[class=\"star\"]").text());
if (mStar.find()){
movie.setStar(mStar.group());
}else {
System.out.println("演员部分匹配失败。");
}
//电影评分
score = element.select("i.integer").text()+element.select("i.fraction").text();
movie.setScore(score);
//电影上映时间
//movie.setReleaseTime(element.select("p[class=\"releasetime\"]").text());
Matcher mTime = reTime.matcher(element.select("p[class=\"releasetime\"]").text());
if(mTime.find()){
movie.setReleaseTime(mTime.group());
}else{
System.out.println("时间部分匹配失败。");
}
data.add(movie);
}
return data;
}
}
MySqlControl
package db;
/**
* 对数据库进行控制
* 例如:增删改查
*/
import model.myMovie;
import java.sql.*;
import java.util.List;
import model.myMovie;
public class MySqlControl {
/**
* 连接数据库
* @return
*/
public static Connection getConn() {
// JDBC 驱动名及数据库 URL
String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost:3306/Crawler?useSSL=false&serverTimezone=UTC";
// 数据库的用户名与密码,需要根据自己的设置
String USER = "root";
String PASS = "123456";
Connection conn = null;
Statement stmt = null;
try {
// 注册 JDBC 驱动
Class.forName(JDBC_DRIVER);
// 打开链接
System.out.println("连接数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("link success.");
} catch (SQLException se) {
// 处理 JDBC 错误
se.printStackTrace();
} catch (Exception e) {
// 处理 Class.forName 错误
e.printStackTrace();
}
return conn;
}
/**
* 插入数据库
* @param params
* @param movieList
* @param c
*/
public static void insertDate(Object params[][], List<myMovie> movieList,Connection c){
try {
for(int i = 0;i<params.length;i++) {
PreparedStatement pstmt = c.prepareStatement("insert into movie_rank values(?,?,?,?,?)");
params[i][0] = movieList.get(i).getMovieRank();
params[i][1] = movieList.get(i).getMovieName();
params[i][2] = movieList.get(i).getStar();
params[i][3] = movieList.get(i).getScore();
params[i][4] = movieList.get(i).getReleaseTime();
pstmt.setInt(1, (Integer) params[i][0]);
pstmt.setString(2, (String) params[i][1]);
pstmt.setString(3, (String) params[i][2]);
pstmt.setString(4, (String) params[i][3]);
pstmt.setString(5, (String) params[i][4]);
pstmt.executeLargeUpdate();
}
System.out.println("成功插入所有数据。");
}catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 打印数据
* @param c
*/
public static void printDate(Connection c){
Statement stmt = null;
try {
stmt = c.createStatement();
String query = "select * from movie_rank";
ResultSet resultSet = stmt.executeQuery(query);
System.out.println("ID Name Star Score RealeseTime");
//打印数据
while(resultSet.next()){
int rank = resultSet.getInt("ID");
String name = resultSet.getString("Name");
String star = resultSet.getString("Star");
String score = resultSet.getString("Score");
String time = resultSet.getString("RealeseTime");
System.out.println(rank +" " + name + " " + star + " " + score+" "+time);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
直接MySql官网下载社区版即可。然后用自带的MySql Work Bench写语句。
不懂sql语句的直接上菜鸟教程现学,很简单。
create database Crawler;
use Crawler;
create table movie_rank(ID int(4),
`Name` varchar(20),
Star varchar(50),
Score varchar(10),
RealeseTime varchar(20)
);
select * from movie_rank;
正在生成客户端...
客户端生成完毕.
连接数据库...
link success.
解析url...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
正在插入数据...
所有数据均已插入数据库.
开始打印数据...
ID Name Star Score RealeseTime
1 霸王别姬 张国荣,张丰毅,巩俐 9.5 1993-01-01
2 肖申克的救赎 蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿 9.5 1994-10-14
3 罗马假日 格利高里·派克,奥黛丽·赫本,埃迪·艾伯特 9.1 1953-09-02
4 这个杀手不太冷 让·雷诺,加里·奥德曼,娜塔莉·波特曼 9.5 1994-09-14
5 泰坦尼克号 莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩 9.5 1998-04-03
6 唐伯虎点秋香 周星驰,巩俐,郑佩佩 9.1 1993-07-01
7 千与千寻 柊瑠美,入野自由,夏木真理 9.3 2001-07-20
8 魂断蓝桥 费雯·丽,罗伯特·泰勒,露塞尔·沃特森 9.2 1940-05-17
9 乱世佳人 费雯·丽,克拉克·盖博,奥利维娅·德哈维兰 9.1 1939-12-15
10 天空之城 寺田农,鹫尾真知子,龟山助清 9.1 1992
11 辛德勒的名单 连姆·尼森,拉尔夫·费因斯,本·金斯利 9.2 1993-12-15
12 喜剧之王 周星驰,莫文蔚,张柏芝 9.1 1999-02-13
13 大闹天宫 邱岳峰,毕克,富润生 9.0 1965-12-31
14 音乐之声 朱莉·安德鲁斯,克里斯托弗·普卢默,埃琳诺·帕克 9.0 1965-03-02
15 春光乍泄 张国荣,梁朝伟,张震 9.2 1997-05-30
16 剪刀手爱德华 约翰尼·德普,薇诺娜·瑞德,黛安·韦斯特 8.8 1990-12-06
17 美丽人生 罗伯托·贝尼尼,尼可莱塔·布拉斯基,乔治·坎塔里尼 9.3 1997-12-20
18 海上钢琴师 蒂姆·罗斯,普路特·泰勒·文斯,比尔·努恩 9.2 1998-10-28
19 黑客帝国 基努·里维斯,凯瑞-安·莫斯,劳伦斯·菲什伯恩 9.0 2000-01-14
20 指环王3:王者无敌 伊莱贾·伍德,伊恩·麦克莱恩,丽芙·泰勒 9.2 2004-03-15
21 哈利·波特与魔法石 丹尼尔·雷德克里夫,鲁伯特·格林特,艾玛·沃特森 9.1 2002-01-26
22 加勒比海盗 约翰尼·德普,凯拉·奈特莉,奥兰多·布鲁姆 8.9 2003-11-21
23 射雕英雄传之东成西就 张国荣,梁朝伟,张学友 8.9 1993-02-05
24 无间道 刘德华,梁朝伟,黄秋生 9.1 2003-09-05
25 楚门的世界 金·凯瑞,劳拉·琳妮,诺亚·艾默里奇 8.9 1998-06-01
26 教父2 阿尔·帕西诺,罗伯特·德尼罗,黛安·基顿 9.0 1974-12-12
27 蝙蝠侠:黑暗骑士 克里斯蒂安·贝尔,希斯·莱杰,阿伦·伊克哈特 9.3 2008-07-18
28 指环王1:护戒使者 伊莱贾·伍德,伊恩·麦克莱恩,丽芙·泰勒 9.0 2002-04-04
29 指环王2:双塔奇兵 伊莱贾·伍德,伊恩·麦克莱恩,丽芙·泰勒 9.1 2003-04-25
30 天堂电影院 菲利浦·诺瓦雷,赛尔乔·卡斯特利托,蒂兹亚娜·罗达托 9.2 1988-11-17
31 机器人总动员 本·贝尔特,艾丽莎·奈特,杰夫·格尔林 9.3 2008-06-27
32 狮子王 马修·布罗德里克,尼基塔·卡兰姆,詹姆斯·厄尔·琼斯 8.8 1995-07-15
33 活着 葛优,巩俐,牛犇 9.0 1994-05-18
34 拯救大兵瑞恩 汤姆·汉克斯,马特·达蒙,汤姆·塞兹摩尔 8.9 1998-07-24
35 忠犬八公的故事 Forest,理查·基尔,琼·艾伦 9.3 2010-03-12
36 哈尔的移动城堡 倍赏千惠子,木村拓哉,美轮明宏 9.0 2004-11-20
37 疯狂原始人 尼古拉斯·凯奇,艾玛·斯通,瑞安·雷诺兹 9.5 2013-04-20
38 阿凡达 萨姆·沃辛顿,佐伊·索尔达娜,米歇尔·罗德里格兹 9.1 2010-01-04
39 盗梦空间 莱昂纳多·迪卡普里奥,渡边谦,约瑟夫·高登-莱维特 9.2 2010-09-01
40 东邪西毒 张国荣,梁朝伟,刘嘉玲 8.8 1994-09-17
41 搏击俱乐部 爱德华·哈里森·诺顿,布拉德·皮特,海伦娜·伯翰·卡特 8.8 1999-10-15
42 幽灵公主 松田洋治,石田百合子,田中裕子 8.9 1998-05-01
43 风之谷 岛本须美,永井一郎,坂本千夏 8.9 1992
44 V字仇杀队 娜塔莉·波特曼,雨果·维文,斯蒂芬·瑞 8.8 2006-03-17
45 十二怒汉 亨利·方达,李·科布,马丁·鲍尔萨姆 9.1 1957-04-13
46 当幸福来敲门 威尔·史密斯,贾登·史密斯,坦迪·牛顿 8.9 2008-01-17
47 放牛班的春天 热拉尔·朱尼奥,让-巴蒂斯特·莫尼耶,玛丽·布奈尔 8.8 2004-10-16
48 勇敢的心 梅尔·吉布森,苏菲·玛索,帕特里克·麦高汉 8.8 1995-05-24
49 三傻大闹宝莱坞 阿米尔·汗,黄渤,卡琳娜·卡普 9.1 2011-12-08
50 闻香识女人 阿尔·帕西诺,克里斯·奥唐纳,加布里埃尔·安瓦尔 8.8 1992-12-23
51 黑客帝国3:矩阵革命 基努·里维斯,雨果·维文,凯瑞-安·莫斯 8.8 2003-11-05
52 驯龙高手 杰伊·巴鲁切尔,杰拉德·巴特勒,亚美莉卡·费雷拉 9.0 2010-05-14
53 断背山 希斯·莱杰,杰克·吉伦哈尔,米歇尔·威廉姆斯 9.0 2006-01-13
54 速度与激情5 范·迪塞尔,保罗·沃克,道恩·强森 9.2 2011-05-12
55 神偷奶爸 史蒂夫·卡瑞尔,杰森·席格尔,拉塞尔·布兰德 9.0 2010-07-09
56 少年派的奇幻漂流 苏拉·沙玛,伊尔凡·可汗,塔布 9.1 2012-11-22
57 飞屋环游记 爱德华·阿斯纳,乔丹·长井,鲍勃·彼德森 8.9 2009-08-04
58 大话西游之月光宝盒 周星驰,莫文蔚,吴孟达 9.6 2014-10-24
59 怦然心动 玛德琳·卡罗尔,卡兰·麦克奥利菲,艾丹·奎因 8.9 2010-08-06
60 致命魔术 休·杰克曼,克里斯蒂安·贝尔,迈克尔·凯恩 8.8 2006-10-20
61 鬼子来了 姜文,姜宏波,陈强 8.9 2000-05-12
62 末代皇帝 尊龙,陈冲,彼得·奥图尔 8.8 1987-10-23
63 美丽心灵 罗素·克洛,詹妮弗·康纳利,艾德·哈里斯 8.8 2001-12-21
64 无敌破坏王 约翰·C·赖利,萨拉·西尔弗曼,简·林奇 9.1 2012-11-06
65 夜访吸血鬼 汤姆·克鲁斯,布拉德·皮特,克尔斯滕·邓斯特 8.8 1994-11-11
66 蝙蝠侠:黑暗骑士崛起 克里斯蒂安·贝尔,迈克尔·凯恩,加里·奥德曼 8.9 2012-08-27
67 倩女幽魂 张国荣,王祖贤,午马 9.2 2011-04-30
68 哈利·波特与死亡圣器(下) 丹尼尔·雷德克里夫,鲁伯特·格林特,艾玛·沃特森 9.0 2011-08-04
69 本杰明·巴顿奇事 布拉德·皮特,凯特·布兰切特,塔拉吉·P·汉森 8.8 2008-12-25
70 钢琴家 艾德里安·布洛迪,艾米莉娅·福克斯,米哈乌·热布罗夫斯基 8.8 2002-09-25
71 甜蜜蜜 黎明,张曼玉,曾志伟 9.2 2015-02-13
72 触不可及 弗朗索瓦·克鲁塞,奥玛·希,安娜·勒尼 9.1 2011-11-02
73 新龙门客栈 张曼玉,梁家辉,甄子丹 8.8 2012-02-24
74 熔炉 孔刘,郑有美,金智英 8.8 2011-09-22
75 初恋这件小事 马里奥·毛瑞尔,平采娜·乐维瑟派布恩,阿查拉那·阿瑞亚卫考 8.8 2012-06-05
76 大话西游之大圣娶亲 周星驰,朱茵,莫文蔚 8.8 2014-10-24
77 小鞋子 默罕默德·阿米尔·纳吉,Kamal 9.1 1999-01-22
78 教父 马龙·白兰度,阿尔·帕西诺,詹姆斯·肯恩 9.3 2015-04-18
79 素媛 李来,薛耿求,严志媛 9.1 2013-10-02
80 萤火之森 内山昂辉,佐仓绫音,后藤弘树 9.0 2011-09-17
81 穿条纹睡衣的男孩 阿沙·巴特菲尔德,维拉·法梅加,大卫·休里斯 9.0 2008-09-12
82 窃听风暴 乌尔里希·穆埃,塞巴斯蒂安·科赫,马蒂娜·格德克 9.0 2006-03-23
83 时空恋旅人 瑞秋·麦克亚当斯,多姆纳尔·格里森,比尔·奈伊 8.9 2013-09-04
84 7号房的礼物 柳承龙,郑镇荣,朴信惠 8.9 2013-01-23
85 恐怖直播 河正宇,李璟荣,李大为 8.8 2013-07-31
86 海豚湾 里克·奥巴瑞,路易·西霍尤斯,哈迪·琼斯 8.9 2009-07-31
87 忠犬八公物语 仲代达矢,春川真澄,井川比佐志 9.0 1987-08-01
88 上帝之城 亚历桑德雷·罗德里格斯,艾莉丝·布拉加,莱安德鲁·菲尔米诺 8.9 2002-08-30
89 美国往事 罗伯特·德尼罗,詹姆斯·伍兹,伊丽莎白·麦戈文 9.1 2015-04-23
90 七武士 三船敏郎,志村乔,千秋实 9.1 1954-04-26
91 完美的世界 凯文·科斯特纳,克林特·伊斯特伍德,T·J·劳瑟 8.9 1993-11-24
92 英雄本色 狄龙,张国荣,周润发 9.2 2017-11-17
93 一一 吴念真,金燕玲,李凯莉 8.9 2000-09-20
94 爱·回家 俞承豪,金艺芬,童孝熙 9.0 2002-04-05
95 海洋 雅克·贝汉,姜文,兰斯洛特·佩林 9.0 2011-08-12
96 我爱你 宋在浩,李顺才,尹秀晶 9.0 2011-02-17
97 黄金三镖客 克林特·伊斯特伍德,李·范·克里夫,埃里·瓦拉赫 8.9 1966-12-23
98 迁徙的鸟 雅克·贝汉,Philippe 9.1 2001-12-12
99 阿飞正传 张国荣,张曼玉,刘德华 8.8 2018-06-25
100 龙猫 秦岚,糸井重里,岛本须美 9.1 2018-12-14
数据库操作执行完毕.
准备关闭数据库...
成功关闭数据库.
所有操作已完成,结束程序运行.