最近和朋友们一起看悬疑电影,会百度了解信息并把想看的电影写在记事本中,突然萌生了一个想法,能不能写一个简单的程序每次自动下载记事本中想看的电影。因此用了一个下午和一个晚上的时间学习和编写了一个简单的Java爬虫程序。
Jsoup爬取电影数据并筛选下载
1、目标网站分析
首先对于要爬取的网站进行分析,经尝试发现,网站中大概有不到59000个电影,每个电影对应的网页是相应编号.html,我猜测这是这个电影对应的数据库id,部分编号页面无法打开,可能是因为政策或者一些限制下架,每个页面中对应的类名相同,因此循环59000次对对应页面的电影信息进行爬取。
个人喜欢看清晰度比较高的电影,所以只抓取大小为GB级的电影。
写好后在服务器上运行代码爬取到服务器的数据库中,同时服务器mysql开启远程数据库,方便后面筛选代码的进行(由于没有多线程爬取,可能运行会很慢,我运行了大概两天)
2、编写jsoup爬虫代码
具体参考这篇文章:
https://www.cnblogs.com/youqc/p/10251485.html
package downloadmovie;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Pattern;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class getJson {
//根据url获取数据
public Document getHtmlTextByUrl(String url){
Document document=null;
try{
int i=(int)(Math.random()*1000);做一个随机延时,防止网站屏蔽
while (i!=0) {
i--;
}
document=Jsoup.connect(url)
.data("query","Java")
.userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36")
.cookie("auth", "token")
.timeout(300000).post();
}catch(Exception e){
e.printStackTrace();
try{
document=Jsoup.connect(url).timeout(5000000).get();
}catch(Exception e1){
e1.printStackTrace();
}
}
return document;
}
//根据元素属性获取某个元素内的elements列表
public Element getElementByClass(Document document,String className){
Element element=null;
//System.out.println(document.select(className));
Elements es2 = document.select(className);
if(es2.size()>0&&es2!=null)
{
element=es2.get(0);
}
return element;
}
public ArrayList<String []> getMovies(String url,String type){
ArrayList<String[]> result=new ArrayList<String[]>();
String classtype="."+type;
//从网络上获取网页
Document document=getHtmlTextByUrl(url);
if (document!=null) {
Element element=getElementByClass(document,classtype);// ul
if(element!=null){
//System.out.println(element);
for(Element e:element.children()){// 依次循环每个元素,也就是一个li
if(e!=null&&e.children().size()>=2){// 一个li包含两个a标签
//System.out.println("first");
//System.out.println(e.children().get(1));//取第二个a标签
String magnet = e.children().get(1).select("a").attr("href");
String temp= e.children().get(1).select("a").text();
//System.out.println(temp);
String[] message=temp.split(" ");
String fullname=message[0];
if(fullname.contains(".")){
String Chinesename=fullname.substring(0, fullname.indexOf(".",fullname.indexOf(".")));
//System.out.println(Chinesename);
if(message.length>=2){
String size=message[1];
if(message.length>=3)
{
String danwei=message[2];
//System.out.println(fullname+"///"+size+"///"+danwei);
//if(danwei.equals("GB"))System.out.println("yes");
if(isNumber(size) && danwei.equals("GB"))
{
String []movies = new String[4];
movies[0]=Chinesename;
movies[1]=fullname;
movies[2]=size;
movies[3]=magnet;
/*for(int i=0;i<movies.length;i++){
System.out.println(movies[i]);
}*/
result.add(movies);
}
}}}
}
}
}
}
return result;
}
public static void main(String[] args) {
DBManager.createtable();
int pages;
for(pages=1;pages<59000;pages++){
String url="https://www.bttiantangok.com/movie/"+pages+".html";
String type="dlist";
ArrayList<String []> movies = new ArrayList<String []>();
movies = new getJson().getMovies(url, type);
//System.out.println(new getJson().getMovies(url, type).isEmpty());
if(movies!=null&movies.size()>0){
for(String []movie : movies)
{
//System.out.println(moviemessage(movie));
Movie m = new Movie(1, movie[0], movie[1], String.valueOf(pages), movie[2], movie[3]);
DBManager.insert(m);
}
System.out.println("已经爬取了第"+pages+"个电影!");
}
//System.out.println(new getJson().getMovies(url, type));
/*DBManager.createtable();
Movie movie= new Movie(3,"chineseName", "fullName", "number", "size", "magnet");
DBManager.insert(movie);*/
}
}
public static boolean isNumber(String str){
if (null == str || "".equals(str)) {
return false;
}
Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
return pattern.matcher(str).matches();
}
public static String moviemessage(String []movie)
{
String result="";
for(int i=0; i<movie.length;i++)
{
result+=movie[i];
result+=" ";
}
return result;
}
}
总体思想就是在chrome浏览器中f12键查看标签信息,逐步获取子项的信息,进行相应的处理后存入数据库中。
对于本次实战来说就是获取dlist类下每个li的第二个a标签
效果图如下:
3、从远程数据库中获取数据并筛选下载电影
这部分比较简单,首先读取txt文件中的电影内容,检测移动硬盘电影目录中如果没有该文件夹就自动创建,循环对每个电影从数据库中进行选取(由于只有10万级的数据,所以Select也比较快),然后将电影分为两个List并排序,如果有12G以下的电影就下载最大的那个,否则就下载12G以上电影中最小的那个。将每个电影的magnet拼接,并复制到剪贴板中。
一开始想直接调用接口使电影下载到对应的目录中,但目前只发现打开迅雷的cmd命令,但没找到参数设置的格式。(参考了几篇python爬虫的文章,里面也讲到下载文件夹这一参数并无作用)见:
https://blog.csdn.net/qq_38188725/article/details/83713689
因此只能每次打开迅雷,迅雷会自动感应磁链,然后手工按顺序下载到对应文件夹中。。。
如果有朋友知道迅雷的命令行参数,恳请留言告知
4、总结
总体而言这一问题实现起来比较简单,也没有使用maven,mybatis等,直接引入jar包,工程及jar包在:
仅供学习与交流