利用Jsoup与 HttpCLient爬取豆瓣电影数据
1.解析页面
影片信息的地址栏链接
首先访问需要爬取的页面
https://movie.douban.com/tag/#/?sort=U&range=0,10&tags=%E7%94%B5%E5%BD%B1,2019
在地址栏可以看到,当前网页的一些状态信息
sort=U (排序方式)
range=0,10 (评分筛选区间)
tags=%E7%94%B5%E5%BD%B1,2019 (最上方选择的标签)
我们划到网页底部,点击加载更多
发现网页内容变多了,但是URL并没有改变
https://movie.douban.com/tag/#/?sort=U&range=0,10&tags=%E7%94%B5%E5%BD%B1,2019
这是因为豆瓣采用异步加载技术,每次访问只修改局部数据
如果这里我们直接使用Jsoup解析
Document doc = Jsoup.parse(new URL("http://www.baidu.com"), 10000);
Elements elements = doc.selct(div.list-wp)
是获取不到影片信息的
存储影片信息的实际链接
但是我们发现,在点击加载更多之后
检查元素的 Network 的XHR中多出了新的数据
点击可以看到 Headers 中有一个 Response URL
我们访问该链接
可以看到影片的信息数据以JSON格式展现出来
对比这两个链接会发现
在原有链接的基础上
新加了 start( 影片信息开始位置 ) 和 year_range(选择的年份范围)
我们尝试更改实际链接(修改start,并将start放到最后,方便后续修改链接)访问其他的影片信息
发现是可行的
所以,我们采用 Response URL 加修改 start 的方式来获取我们的影片信息链接
2.需要爬取的信息
在 影片信息的实际链接 中我们可以获取到
directors : [“庵野秀明”,“鹤卷和哉”,“大塚雅彦”]
rate : 9.4
title : 新世纪福音战士剧场版:Air/真心为你
url : https://movie.douban.com/subject/1308892/
casts : [“绪方惠美”,“林原惠美”,“三石琴乃”,“宫村优子”,“山口由里子”]
cover : https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2250316512.webp
id : 1308892
但如果想进一步获取影片更详细的信息(比如:类型、制片国家、上映日期 )
就需要访问影片详情界面(就是实际链接中url的值)
利用 Jsoup 对页面元素进行解析
知道了想要获取的信息之后,就可以在数据库中建表
3.编写工具类
虽然 Jsoup 也可以用 URL 直接获取页面内容
在网页的抓取上,HttpClient 要优于 Jsoup(HttpClient可以设置代理、 设置连接超时等等功能)
所以我们使用 HttpClient 抓取网页内容,Jsoup 解析网页元素
HttpUtils
public class HttpUtils {
private PoolingHttpClientConnectionManager cm;
private ArrayList<String> agents;
public HttpUtils() {
// 创建连接池管理器
this.cm = new PoolingHttpClientConnectionManager();
// 设置连接数
this.cm.setMaxTotal(100);
// 设置每个主机(理解为网站,如:百度10个、网易10个)的最大连接数
this.cm.setDefaultMaxPerRoute(10);
//初始化 User-Agent 信息
this.agents = new ArrayList<String>();
// 添加 User-Agent 信息
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36");
agents.add("Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36");
agents.add("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
agents.add("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER");
agents.add("Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0");
agents.add("Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0");
agents.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36");
System.out.println("<--------- HttpUtils initialization success --------->");
}
/**
* 获取页面源代码
*
* @param url 网页链接
* @return 页面源代码
*/
public String doGetHtml(String url) {
// 通过连接池获取 httpClient
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
HttpGet httpGet = new HttpGet(url);
// 伪造 User-Agent(反反爬虫)
int agentNum = new Random().nextInt(agents.size());// 生成一个范围在 0-x(不包含x)内的任意正整数
httpGet.addHeader("User-Agent", agents.get(agentNum));
// 设置请求信息
httpGet.setConfig(getConfig());
// 定义 response,方便 finally 中关闭
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
// 获取并判断,状态码是否正常(正常值:200)
if (response.getStatusLine().getStatusCode() == 200) {
// 判断响应体是否为空,不为空则获取内容
if (response.getEntity() != null) {
// 获取响应体,并指定 UTF-8 编码
String content