Java爬虫初学——爬取BT电影天堂电影的磁力链接并筛选下载

时间:2024-03-07 18:12:32

最近和朋友们一起看悬疑电影,会百度了解信息并把想看的电影写在记事本中,突然萌生了一个想法,能不能写一个简单的程序每次自动下载记事本中想看的电影。因此用了一个下午和一个晚上的时间学习和编写了一个简单的Java爬虫程序。

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包在:

工程及jar包

仅供学习与交流