最近和朋友們一起看懸疑電影,會百度瞭解信息並把想看的電影寫在記事本中,突然萌生了一個想法,能不能寫一個簡單的程序每次自動下載記事本中想看的電影。因此用了一個下午和一個晚上的時間學習和編寫了一個簡單的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包在:
僅供學習與交流