前面写了一个爬取花瓣的,再写一个爬取Lofter的。

一、分析lofter主页信息

lofter为用户提供了海量前台模板来使用,不同的模板网页内容也不一样,但是所有的用户都会有一个归档页面,并且所有用户的归档页面是一样的。我们只需要分析和爬取归档页面的内容即可。使用java爬取lofter博主图片-明亮

二、分析页面的网络请求

lofter的归档页面也是用的ajax异步加载,清空网络请求后下拉查看新的网络请求参数。下拉后的第一个网络请求就是我们关注的重点,点击查看该请求的详细内容,里面的请求头和请求参数都是我们要用到的。

使用java爬取lofter博主图片-明亮

请求参数总结如下:

callCount=1# 固定
scriptSessionId=${scriptSessionId}187# 固定
httpSessionId=# 固定
c0-scriptName=ArchiveBean# 固定
c0-methodName=getArchivePostByTime# 固定
c0-id=0# 固定
c0-param0=boolean:false# 固定
c0-param1=number:4520906# 用户ID,可从用户主页源码获取
c0-param2=number:1521342313224# 时间戳,使用当前时间即可
c0-param3=number:50# 单次请求博客篇数,可以按需求修改
c0-param4=boolean:false# 固定
batchId=822456# 6位随机数,爬取时可以固定

 

三、查看回执内容

回执内容为一个json字符串,其中permalink为每个文章的链接地址。我们只需要把文章链接提取出来,然后遍历每篇文章里面的图片即可。

使用java爬取lofter博主图片-明亮

四、分析文章页面

文章链接规律为http://博客名称.lofter.com/post/文章ID,每个文章内的图片独有的属性是bigimgsrc,我们只需要把文章里的所有bigimgsrc提取出来去下载即可。

使用java爬取lofter博主图片-明亮

五、话不多说,上代码

使用下面的代码只需要设置博客名称、要爬取的文章篇数、图片下载地址即可使用。

package net.limingliang.www;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



public class Lofter {
	
	/**
	 *只需要设置下面三个参数就可以爬取
	 *譬如主页地址:http://unicornwj.lofter.com
	 *那么博客名称为unicornwj
	 */
	//博客名称
	private static String blogName = "unicornwj";
	//爬取博客篇数
	private static int num = 1000;
	//图片下载路径
	private static String downloadPath = "/Users/limingliang/Downloads";
	
	
	
	//获取博客ID正则
    private static final String BLOGID_REG = "blogId=.*?\"";
    //获取文章ID正则
    private static final String POSTURL_REG = "permalink=\".*?\"";
    //获取文章图片正则
    private static final String IMGURL_REG = "bigimgsrc=\".*?\"";
    
	public static void main(String[] args) {
		try {
			Lofter lofter = new Lofter();
			//根据博客名称获取博客ID
			String blogId = lofter.getBlogId(blogName);
			//模拟post请求
			String jsonData = lofter.postSend(blogId);
			//获取文章列表
			List<String> postIds = lofter.getPostIds(jsonData);
			//遍历文章列表并下载文章中的图片
			for(String postId : postIds) {
				//获取文章页面
				String postHtml = lofter.getHtml("http://" + blogName + ".lofter.com/post/" + postId);
				//获取文章图片列表
				List<String> imgUrl = lofter.getImageUrl(postHtml);
				lofter.Download(imgUrl);
				System.out.println(11);
				
			}
			System.out.println(blogId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 根据首页地址获取博客id
	 * @param blogUrl
	 * @return
	 */
	private String getBlogId(String blogUrl) throws Exception{
		String html = this.getHtml("http://"+blogUrl+".lofter.com/");
		Matcher matcher = Pattern.compile(BLOGID_REG).matcher(html);
		while(matcher.find()) {
			//抓取到的内容为:blogId=3384409",需要截取
			String postId = matcher.group();
			return postId.substring(postId.indexOf("=")+1, postId.indexOf("\""));
		}
		return "";
	}
	
	/**
	 * 	模拟post请求
	 * 	callCount=1       						# 固定
		scriptSessionId=${scriptSessionId}187   	# 固定
		httpSessionId=    						# 固定
		c0-scriptName=ArchiveBean       			# 固定
		c0-methodName=getArchivePostByTime      	# 固定
		c0-id=0           						# 固定
		c0-param0=boolean:false					# 固定
		c0-param1=number:4520906        			# 用户ID,可从用户主页源码获取
		c0-param2=number:1521342313224  			# 时间戳,使用当前时间即可
		c0-param3=number:50       				# 单次请求博客篇数,可以按需求修改
		c0-param4=boolean:false   				# 固定
		batchId=822456            				# 6位随机数,爬取时可以固定
	 * @param blogId
	 * @return
	 * @throws Exception
	 */
	private String postSend(String blogId) throws Exception{
		//设置参数
		String payload = 	"callCount=1\n"
							+"scriptSessionId=${scriptSessionId}187\n"
							+"httpSessionId=\n"
							+"c0-scriptName=ArchiveBean\n"
							+"c0-methodName=getArchivePostByTime\n"
							+"c0-id=0\n"
							+"c0-param0=boolean:false\n"
							+"c0-param1=number:"+blogId+"\n"
							+"c0-param2=number:"+new Date().getTime()+"\n"
							+"c0-param3=number:"+num+"\n"
							+"c0-param4=boolean:false\n"
							+"batchId=574722\n";
				
				
		StringBuffer jsonString;
		URL url = new URL("https://"+blogName+".lofter.com/dwr/call/plaincall/ArchiveBean.getArchivePostByTime.dwr");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        connection.setRequestProperty("Host", blogName+".lofter.com");
        connection.setRequestProperty("Origin", "http://"+blogName+".lofter.com");
        connection.setRequestProperty("Referer", "http://"+blogName+".lofter.com/view");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36	");
        	
        OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        jsonString = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            jsonString.append(line);
        }
        br.close();
        connection.disconnect();
        System.out.println(jsonString.toString());
		return jsonString.toString();
	}
	
	/**
	 * 获取文章id
	 * @param html
	 * @return
	 * @throws Exception
	 */
	private List<String> getPostIds(String html) throws Exception {
		List<String> list = new ArrayList<String>();
		Matcher matcher = Pattern.compile(POSTURL_REG).matcher(html);
		while(matcher.find()) {
			//抓取到的格式为permalink="33a459_baabbb8" 需要截取
			String postId = matcher.group();
			System.out.println(postId.substring(postId.indexOf("=")+2, postId.lastIndexOf("\"")));
			list.add(postId.substring(postId.indexOf("=")+2, postId.lastIndexOf("\"")));
		}
		return list;
	}
	
    /**
     * 获取ImageUrl地址
     * @param html
     * @return
     */
    private List<String> getImageUrl(String html){
        Matcher matcher=Pattern.compile(IMGURL_REG).matcher(html);
        List<String>listimgurl=new ArrayList<String>();
        while (matcher.find()){
        		String src = matcher.group();
        		System.out.println(src.substring(src.indexOf("http"), src.length()-1));
            listimgurl.add(src.substring(src.indexOf("http"), src.length()-1));
        }
        return listimgurl;
    }
    /**
     * 下载图片
     * @param listImgSrc
     */
    private void Download(List<String> listImgUrl) throws Exception{
        //开始时间
        Date begindate = new Date();
        for (String url : listImgUrl) {
            //开始时间
            Date begindate2 = new Date();
            URL uri = new URL(url);
            InputStream in = uri.openStream();
            String path = downloadPath + "/" + blogName;
            File file = new File(path);
            if(!file.exists()) {
            		file.mkdirs();
            }
            FileOutputStream fo = new FileOutputStream(new File(path + "/"+new Date().getTime()+".jpg"));
            byte[] buf = new byte[1024];
            int length = 0;
            System.out.println("开始下载:" + url);
            while ((length = in.read(buf, 0, buf.length)) != -1) {
                fo.write(buf, 0, length);
            }
            in.close();
            fo.close();
            //结束时间
            Date overdate2 = new Date();
            double time = overdate2.getTime() - begindate2.getTime();
            System.out.println("耗时:" + time / 1000 + "s");
        }
        Date overdate = new Date();
        double time = overdate.getTime() - begindate.getTime();
        System.out.println("下载文件数:"+listImgUrl.size()+",总耗时:" + time / 1000 + "s");
    }
	/**
	 * 获取HTML内容
	 * @param url
	 * @return
	 * @throws Exception
	 */
    private String getHtml(String url)throws Exception{
        URL url1=new URL(url);
        URLConnection connection=url1.openConnection();
        InputStream in=connection.getInputStream();
        InputStreamReader isr=new InputStreamReader(in);
        BufferedReader br=new BufferedReader(isr);

        String line;
        StringBuffer sb=new StringBuffer();
        while((line=br.readLine())!=null){
            sb.append(line,0,line.length());
            sb.append('\n');
        }
        br.close();
        isr.close();
        in.close();
        return sb.toString();
    }

}