使用Jsoup包抓取豆瓣Top250电影信息

Java制作爬虫程序主要用到的网页解析工具Jsoup,而在Python使用的是漂亮汤,Jsoup能向JS和JQuery一样获取网页文件的模型(dom),是解析网页文件的有力工具,使用方法见:Jsoup详解(一)——Jsoup详解

Jsoup的使用方法和JS基本相同,进入豆瓣Top250界面:


找到链接地址:

String[] url=new String[25];
		//进入Top250的界面,抓取单个电影的网址
		Document document=Jsoup.connect("https://movie.douban.com/top250?start="+j*25).get();
        Elements bd=document.select("div.hd");
        for(int i=0;i<bd.size();i++)
        {
    
    
        	Elements info=bd.get(i).select("a[href]");
        	url[i]=info.attr("href");
        }
        return url;

节这我们需要一个函数,向这个函数传递URL后可以获得网页的全部信息。
如果文本在标签之内,选择这个标签后,text方法提取文本即可,如果不在,比如,在<br>之前,这样的内容属于文本节点,可找邻近的节点,然后使用nextSibling()等方法获得文本节点。需要注意的是:
1、Document:文件对象模型(dom)
2、Elements:元素对象集合
3、Node:节点对象
这三者从大到小排列,一般的节点对象没有text方法,用outhtml方法获取它的值,除了文本节点。

//抓取电影名
		String name=document.select("span[property=v:itemreviewed]").text();
		info[0]=name;
		//抓取导演名
		String director=document.select("a[rel='v:directedBy']").text();
		info[1]=director;
		//抓取编剧
		String pl=document.select("span.attrs").get(1).text();
		info[2]=pl;
		//抓取演员名
		String actor=document.select("span.attrs").get(2).text();
		info[3]=actor;
		//抓取电影类型
		String type=document.select("span[property='v:genre']").text();
		info[4]=type;
		//对是否含有官方网站进行讨论
		int i=4;
		if(document.select("span.pl").get(i).text().contains("官方网站"))
		{
    
    
			i++;
		}
		//抓取产地国家,它的内容是国家标签的下一个节点
		String country=document.select("span.pl").get(i).nextSibling().outerHtml();
		info[5]=country;
		//抓取语言
		String lan=document.select("span.pl").get(i+1).nextSibling().outerHtml();
		info[6]=lan;
		//抓取时长
		String runTime=document.select("span[property='v:runtime']").text();
		info[7]=runTime;
		//抓取别名
		String otherName=document.select("span.pl").get(i+4).nextSibling().outerHtml();
		info[8]=otherName;
		//抓取评价人数
		String peoNum=document.select("span[property='v:votes']").text();
		info[9]=peoNum;
		//抓取介绍
		String intro=document.getElementById("link-report").text();
		info[10]=intro;

这里是抓取豆瓣电影信息的过程




抓取信息后,我们将其放入一个表格中,这里使用的是poi包,它抓门用来处理文档,docx,xlsx等。

private static void writeRow(int i ,String[] row,File file) throws InvalidFormatException, IOException
	{
    
    
		Workbook workBook=new XSSFWorkbook(new FileInputStream(file));
		//获得Top250Sheet,前提是有这个sheet,没有会报错
		Sheet sheet=workBook.getSheet("Top250");
		Row r=sheet.createRow(i);
		for(int k=0;k<row.length;k++)
		{
    
    
			r.createCell(k).setCellValue(row[k]);
		}
		//将数据写进表格
		workBook.write(new FileOutputStream(file));
		
	}

对每一页遍历,即可获取所有电影的网址
总的代码如下

package spider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class DoubanTop250 
{
    
    
	
	public static void main(String[] args) throws InterruptedException, IOException, InvalidFormatException 
	{
    
    
		File file=new File("Top250.xlsx");
		//写好表格标题
		String[] title= {
    
    "电影名","导演","编剧","演员","类型","国家","语言","时长","别名","评价人数","简介"};
		writeRow(0,title,file);
		//遍历,抓取Top250电影信息
		for(int k=0	;k<10;k++) {
    
    
			//抓取每页所有电影的网址
		String[] url=getMovieUrl(k);
//		String item=url[0];
//		System.out.println(getInfos(item)[8]);
		for(int i=0;i<=24;i++)
		{
    
    
			String[] list =getInfos(url[i]);
			//防止豆瓣把你IP禁了
			Thread.sleep(500);
			writeRow(i+1+k*25,list, file);
		}
		}
	}
	//抓取每个电影的链接的函数
	private static String[] getMovieUrl(int j) throws IOException
	{
    
    
		String[] url=new String[25];
		//进入Top250的界面,抓取单个电影的网址
		Document document=Jsoup.connect("https://movie.douban.com/top250?start="+j*25).header("user-agent", "Chrome").get();
        Elements bd=document.select("div.hd");
        for(int i=0;i<bd.size();i++)
        {
    
    
        	Elements info=bd.get(i).select("a[href]");
        	url[i]=info.attr("href");
        }
        return url;
	}
	//获取每个电影的信息,使用的是Jsoup包
	private static String[] getInfos(String url) 
	{
    
    
		//豆瓣电影这个界面十分复杂,情况很多
		try
		{
    
    
		Document document=Jsoup.connect(url).get();
		String info[]=new String[11];
		//抓取电影名
		String name=document.select("span[property=v:itemreviewed]").text();
		info[0]=name;
		//抓取导演名
		String director=document.select("a[rel='v:directedBy']").text();
		info[1]=director;
		//抓取编剧
		int j=1;
		if(document.select("span.attrs").size()>2) {
    
    
		String pl=document.select("span.attrs").get(j).text();
		info[2]=pl;
		//抓取演员名
		String actor=document.select("span.attrs").get(j+1).text();
		info[3]=actor;
		}else if(document.select("span.attrs").size()==2)
		{
    
    
			info[2]=null;
			info[3]=document.select("span.attrs").get(j).text();
		}else
		{
    
    
		    info[2]=null;
		    info[3]=null;
		}
		//抓取电影类型
		String type=document.select("span[property='v:genre']").text();
		info[4]=type;
		//对是否含有官方网站进行讨论
		int i=4;
		if(document.select("span.pl").get(i).text().contains("官方网站"))
		{
    
    
			i++;
		}
		//抓取产地国家,它的内容是国家标签的下一个节点
		String country=document.select("span.pl").get(i).nextSibling().outerHtml();
		info[5]=country;
		//抓取语言
		String lan=document.select("span.pl").get(i+1).nextSibling().outerHtml();
		info[6]=lan;
		//抓取时长
		String runTime=document.select("span[property='v:runtime']").text();
		info[7]=runTime;
		//抓取别名
		String otherName=document.select("span.pl").get(i+4).nextSibling().outerHtml();
		info[8]=otherName;
		//抓取评价人数
		String peoNum=document.select("span[property='v:votes']").text();
		info[9]=peoNum;
		//抓取介绍
		String intro=document.getElementById("link-report").text();
		info[10]=intro;
		return info;
		//出现异常,不要抛出,会导致程序中断
		}catch (IOException e) {
    
    
			// TODO: handle exception
			return null;
		}
	}
	
	//向表格中写数据,使用POI包
	private static void writeRow(int i ,String[] row,File file) throws InvalidFormatException, IOException
	{
    
    
		Workbook workBook=new XSSFWorkbook(new FileInputStream(file));
		//获得Top250Sheet,前提是有这个sheet,没有会报错
		Sheet sheet=workBook.getSheet("Top250");
		Row r=sheet.createRow(i);
		for(int k=0;k<row.length;k++)
		{
    
    
			r.createCell(k).setCellValue(row[k]);
		}
		//将数据写进表格
		workBook.write(new FileOutputStream(file));
		
	}
}

效果图

猜你喜欢

转载自blog.csdn.net/m0_47202518/article/details/108549784