Java爬取网页图片

首先需要下载相关的依赖包,我用的是eclipse,直接百度maven然后搜索相应的依赖放到pom文件中就行了。

爬取的网址为:http://info.sporttery.cn/roll/fb_list.php?s=&c=%CF%FA%C1%BF%B9%AB%B8%E6&2

代码的大致步骤为:

1.先用URL和openStream将销量公告所有时期的网页下载到本地,由于可能会有很多页,所以就需要先知道page数再按照page逐页下载。

2.用indexOf("html")提取本地的HTML文件,并按照名称排序(这里涉及到page10和page2的排序规则,正常的是2在前面,但因为是字符串所以page10排在了前面,所以需要特殊处理,处理方法见listHtmlFiles方法)。

3.用Jsoup解析HTML文件,将每周公告对应的链接保存到linkedHref中

4.用scanner输入需要爬取的起始日期和截止日期,并用matchHtml方法提取该时间段的每周销量公告对应的链接

5.用Jsoup解析所需爬取的HTML文件,将图片对应的链接保存到PhotoHtmlList中。

6.用URL链接图片地址,并用ByteArrayOutputStream将图片保存为jpg格式。

7.用delete方法删除已下载到本地的HTML文件。


完整代码如下:

package com.xlh.bd.internal.service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Scanner;


import org.apache.commons.io.FileUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class SpiderXlggService {
/**
* 爬取销量公告数据
*/
public static String startDate = null; //起始日期
public static String endDate = null;   //截止日期
public static List<String> linkedHref = new ArrayList<String>();
public static String url = "http://info.sporttery.cn/roll/fb_list.php?c=%CF%FA%C1%BF%B9%AB%B8%E6&&page=";
public static List<String> urlList = new ArrayList<String>(); //网页列表
public static List<String> PhotoHtmlList = new ArrayList<String>(); //图片网页列表
public static List<String> timeList = new ArrayList<String>(); //时间列表
public static int pageCount = 0;

public void getAllUrlList() throws IOException{
String url2 = url +1;
    Document doc = Jsoup.connect(url2).get(); //从URL直接加载 HTML 文档
        Elements links = doc.getElementsByClass("m-page");        
        for (Element element : links) {
        Elements links2 = element.getElementsByTag("a");//得到<td>...</td>里面的内容
        String linkText = null;
        for (Element element2 : links2) {
        linkText = element2.attr("href"); //读取href的值        
        }
        int first = linkText.indexOf("page=");
            int last = linkText.indexOf("&&");
            pageCount = (int) Math.ceil(Double.parseDouble(linkText.substring(first+"page=".length(), last)));
            System.out.println("共有"+pageCount+"页需要爬取,请耐心等耐!");
        }
    }

public class ReadAllHtml extends Thread {
private String s = null;
public ReadAllHtml(String s){
       this.s = s ;
   }
public void run(){
System.out.println("正在下载"+s);
for (int i=1; i<=pageCount; i++) {
String url2 = url + i;
System.out.println("Page" + i + "starts!");
try {
      File dest = new File("page" + i +".html"); 
               InputStream is; //接收字节输入流
FileOutputStream fos = new FileOutputStream(dest); //字节输出流

    URL temp = new URL(url2); //加载网页
           is = temp.openStream();  
           
           BufferedInputStream bis = new BufferedInputStream(is);//为字节输入流加缓冲            
           BufferedOutputStream bos = new BufferedOutputStream(fos);//为字节输出流加缓冲


           int length;    
           byte[] bytes = new byte[1024*20];
           while((length = bis.read(bytes, 0, bytes.length)) != -1){
               fos.write(bytes, 0, length);
           }
           bos.close();
           fos.close();
           bis.close();
           is.close();
sleep(10); //间隔0.01秒
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

public static List<File> listHtmlFiles(String path){
        File file = new File(path); //读取本地html的路径        
        File[] array = file.listFiles(); //用于存储路径下的文件名
        List<File> array2 = new ArrayList<File>();
        for(int i=0;i<array.length;i++){
            if(array[i].isFile()&&array[i].getName().indexOf("html")>-1){
            array2.add(array[i]);
            }        
        }
        List<Integer> num = new ArrayList<Integer>();
        for(int i=0;i<array2.size();i++){
        String string = array2.get(i).toString();
        int first = string.indexOf("page");
            int last = string.indexOf(".");
        num.add(Integer.parseInt(string.substring(first+"page".length(), last)));
        }
        Collections.sort(num); //按值排序
        List<String> num2 = new ArrayList<String>();
        for (Integer integer : num) {
        num2.add("page"+String.valueOf(integer)+".html");
}
        List<File> array3 = new ArrayList<File>();
        for(int i=0;i<num2.size();i++){
        for (File file2 : array2) {
        if(file2.toString().contains(num2.get(i))) array3.add(file2);
}
        }
return array3;
}

    public static void getLocalhtml(String path) { //解析本地的html 
    List<File> array = listHtmlFiles(path);
        //循环读取并解析这些文件
        for(int i=0; i<array.size(); i++){
            try{
                //文件名字
                System.out.println("正在解析网址:" + array.get(i).getName()+"!");
                //下面开始解析本地的html
                Document doc = Jsoup.parse(array.get(i), "gb2312"); 
                Elements links = doc.getElementsByClass("List_L FloatL");//分离出class="List_L FloatL"的所有东西
                for (Element link : links) {
                    Elements links2 = link.getElementsByTag("li");  
                    for (Element element : links2) {
                    Elements links3 = element.getElementsByTag("a");//得到<td>...</td>里面的内容
                    for (Element element3 : links3) {
                            String linkText2 = element3.attr("href");//得到<th>...</th>里面的内容
                            if(!linkText2.contains("销量公告")) linkedHref.add(linkText2);
                        } 
   
}
                System.out.println(array.get(i).getName()+"解析完毕!");
             } catch (Exception e) {
                    System.out.println("网址:" + array.get(i).getName() + "解析出错");
                    e.printStackTrace();
                    continue;
                }
        }
//        for (String string:linkedHref) {
// System.out.println(string);
// }
    }
    
    public static void matchHtml() throws IOException{
    DateFormat format2 = new SimpleDateFormat("yyyy/MMdd"); //字符串时间格式
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入起始日期,格式为yyyy/MMdd:");
    startDate = sc.next();
Date date = null;
try {
date = (Date)format2.parse(startDate);
} catch (ParseException e) {
System.out.println("起始日期输入格式错误");
e.printStackTrace();
}
   
    Scanner sc2 = new Scanner(System.in);
    System.out.println("请输入截止日期,格式为yyyy/MMdd:");
    endDate = sc2.next();
    Date date2 = null;
try {
date2 = (Date)format2.parse(endDate);
} catch (ParseException e) {
System.out.println("截止日期输入格式错误");
e.printStackTrace();
}
    sc.close();
    sc2.close();
    Calendar dd = Calendar.getInstance(); //定义日期实例
    dd.setTime(date);
    while(dd.getTime().before(date2)){ //不包括endDate
    String str = format2.format(dd.getTime()); //日期转换为字符串        
    dd.add(Calendar.DATE, 1); //天数加1
    for(String string:linkedHref){
        if(string.contains(str)) {
        urlList.add(string); //网页列表
            timeList.add(str.substring(5));
        }
    }
    }
//     for (String string : urlList) {
//     System.out.println(string);
// }
    }
        
    public static void writeExcel(String path) throws IOException{ //将网页链接写入excel
    //创建一个文件
File file2 = new File(path+"urlList.xlsx");
file2.createNewFile();
//将excel数据存盘
FileOutputStream stream2 = FileUtils.openOutputStream(file2);
//创建excel工作簿(最后需要往里写数据)
XSSFWorkbook workbook2 = new XSSFWorkbook();
XSSFSheet sheet2 = workbook2.createSheet();//创建sheet
System.out.println("正在写入excel!");
for (int i = 0; i < urlList.size(); i++) { //创建行
XSSFRow row2 = sheet2.createRow(i);
XSSFCell cell2 = row2.createCell(0);
cell2.setCellValue(urlList.get(i));
}
workbook2.write(stream2);
stream2.close();
workbook2.close();
System.out.println("写入完毕!");
    }


    public static void deleteHtml(String path){ //删除path下的html文件
    File file = new File(path);
    File[] files = file.listFiles();
    for (File file2 : files) {
if(file2.getName().indexOf("html")>-1) file2.delete();
}
    }
    
    public class ReadNeedHtml extends Thread {
private String s = null;
public ReadNeedHtml(String s){
       this.s = s ;
   }
public void run(){
System.out.println("正在下载"+s);
for (int i=0; i<urlList.size(); i++) {
String url2 = urlList.get(i);
System.out.println(timeList.get(i) + "starts!");
try {
      File dest = new File(timeList.get(i)+".html"); 
               InputStream is; //接收字节输入流
FileOutputStream fos = new FileOutputStream(dest); //字节输出流

    URL temp = new URL(url2); //加载网页
           is = temp.openStream();  
           
           BufferedInputStream bis = new BufferedInputStream(is);//为字节输入流加缓冲            
           BufferedOutputStream bos = new BufferedOutputStream(fos);//为字节输出流加缓冲


           int length;    
           byte[] bytes = new byte[1024*20];
           while((length = bis.read(bytes, 0, bytes.length)) != -1){
               fos.write(bytes, 0, length);
           }
           bos.close();
           fos.close();
           bis.close();
           is.close();
sleep(10); //间隔0.01秒
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

public static List<File> listHtmlFiles2(String path){
        File file = new File(path); //读取本地html的路径        
        File[] array = file.listFiles(); //用于存储路径下的文件名
        List<File> array2 = new ArrayList<File>();
        for(int i=0;i<array.length;i++){
            if(array[i].isFile()&&array[i].getName().indexOf("html")>-1){
            array2.add(array[i]);
            }        
        }
        Collections.sort(array2); //按名称排序
return array2;
}
    
    public static void getPhotoHtml(String path) { //解析本地的html 
    List<File> array = listHtmlFiles2(path);
        //循环读取并解析这些文件
        for(int i=0; i<array.size(); i++){
            try{
                //文件名字
                System.out.println("正在解析网址:" + array.get(i).getName()+"!");
                //下面开始解析本地的html
                Document doc = Jsoup.parse(array.get(i), "gb2312"); 
                Elements links = doc.getElementsByClass("jc-article");//分离出class="jc-article"的所有东西
                for (Element link : links) {                    
                    Elements links3 = link.getElementsByTag("img");//得到<td>...</td>里面的内容
                    for (Element element3 : links3) {
                            String linkText2 = element3.attr("src");//得到<th>...</th>里面的内容
                            PhotoHtmlList.add(linkText2);
                        } 
}
                System.out.println(array.get(i).getName()+"解析完毕!");
             } catch (Exception e) {
                    System.out.println("网址:" + array.get(i).getName() + "解析出错");
                    e.printStackTrace();
                    continue;
                }
        }
//        for (String string:PhotoHtmlList) {
// System.out.println(string);
// }
    }
    
    public static void DownloadPhoto(List<String> PhotoHtmlList) throws IOException { //下载图片
    for (int i = 0; i < PhotoHtmlList.size(); i++) {
    String strUrl = PhotoHtmlList.get(i);
        //构造URL
        URL url = new URL(strUrl);


        //构造连接
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();


        //打开连接
        conn.connect();
        //打开这个网站的输入流
        InputStream inStream = conn.getInputStream();


        //用这个做中转站 ,把图片数据都放在了这里,再调用toByteArray()即可获得数据的byte数组
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //用这个是很好的,不用一次就把图片读到了文件中
        //要是需要把图片用作其他用途呢?所以直接把图片的数据弄成一个变量,十分有用
        //相当于操作这个变量就能操作图片了


        byte [] buff = new byte[1024]; //网址图片较小,1024Byte足够了
        //1024Byte=1KB,分配1KB的缓存
        //这个就是循环读取,是一个临时空间,多大都没关系
        //byte[]的大小,说明你一次操作最大字节是多少
        int len = 0;        
        while((len=inStream.read(buff))!=-1){//读取图片数据
        outStream.write(buff,0,len);
        }
        inStream.close();
        outStream.close();
        //把图片数据填入文件中
        File file = new File(timeList.get(i)+".jpg");


        FileOutputStream op = new FileOutputStream(file);
        op.write(outStream.toByteArray());
        op.close();
}
    }
    
    public static void main(String[] args) throws ParseException, IOException, InterruptedException {
    SpiderXlggService ss = new SpiderXlggService();
    ss.getAllUrlList();
    ReadAllHtml rt = ss.new ReadAllHtml("爬取所有销量公告!");
    rt.start();
    try {
    rt.join(); //保证网页读取完毕
    } catch (InterruptedException e) {
    e.printStackTrace();
     }
    String path = "D:\\xlh\\1zhangliang\\mgr后台项目\\bd_internal_api\\src\\";
    getLocalhtml(path); //解析路径下的所有html
    matchHtml(); //匹配需要提取的html
    writeExcel(path); //将需提取的html保存到excel    
    deleteHtml(path); //删除所有html文件
   
    ReadNeedHtml rt2 = ss.new ReadNeedHtml("爬取所需销量公告!");
    rt2.start();
    try {
    rt2.join(); //保证网页读取完毕
    } catch (InterruptedException e) {
    e.printStackTrace();
     }
    getPhotoHtml(path);
    DownloadPhoto(PhotoHtmlList);
    deleteHtml(path); //删除所有html文件
    }

}

发布了49 篇原创文章 · 获赞 95 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/Trisyp/article/details/78292797