Java实现简易爬虫--抓取酷安网用户头像

方法一:


爬虫思路

以酷安网用户粉丝较多的用户的个人中心为进口,获取该用户的全部粉丝的个人中心链接,用户头像链接和用户名,并分别放入队列。开启两个线程获取信息,一个线程获取队列中的用户的信息并放入队列,另一个线程负责从头像链接队列中取出链接并下载用户头像。

爬虫分析

用浏览器打开一个用户的粉丝列表(http://coolapk.com/u/[用户id]/contacts)

 Java实现简易爬虫--抓取酷安网用户头像_第1张图片

并查看源码

 Java实现简易爬虫--抓取酷安网用户头像_第2张图片

我们可以看到粉丝列表以HTML的ul标签显示,并且其id为dataList,ul标签中的各个li标签即为每一个用户的信息啦~再进一步分析,li标签中的img标签为用户头像。h4标签的内容即为用户名,h4标签中的a标签的href属性为用户的个人中心链接。

通过观察我们还知道:用户的粉丝列表链接=个人中心链接+ "/contacts"

这样我们就可以开始爬取头像了

用到的库

Jsoup:

作用:解析和操作HTML元素。下载地址:https://jsoup.org/download

HttpClient:

作用:下载图片。下载地址: http://hc.apache.org/downloads.cgi

代码

Main.java

package main;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

public class Main {

	//浏览器UA
	private static String UA="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
	//主机地址
	private static final String HOST="http://coolapk.com";
	//头像本地保存地址
	private static final String SAVE_PAYH="D:/coolapk/";
	//指示UserThread是否在运行
	private static boolean isRun=false;
	//用户中心界面队列
	private  static MyQueue userUrlQueue=new MyQueue<>();
	//用户头像链接队列
	private static MyQueue userHeadUrlQueue=new MyQueue<>();
	//用户名队列
	private static MyQueue userNameQueue=new MyQueue<>();
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		userUrlQueue.put("http://coolapk.com/u/12202/contacts");//入口链接
		java.io.File f=new java.io.File(SAVE_PAYH);
		//如果文件夹不存在,则创建
		if(!f.exists())
		{
			f.mkdirs();
		}
		start();
	}

	/**
	 * 开始
	 */
	private static void start()
	{
		new UserThread().start();
		new HeadThread().start();
	}
	
	/**
	 * 获取相关的链接
	 * @throws Exception
	 */
	private static void getUserUrl() throws Exception {
		String url=userUrlQueue.poll();
		if(url!=null){
			isRun=true;
			Connection connection=Jsoup.connect(url);
			connection.userAgent(UA);
			Document document=connection.get();
			
			Element ulElement=document.getElementById("dataList");
			org.jsoup.select.Elements liElements=ulElement.getElementsByTag("li");
			if (liElements==null) {
				return;
			}
			for(Element li:liElements){
				if(li==null)
					continue;
				//获取用户头像链接
				String userHeadUrl=li.getElementsByTag("img").first().attr("src");
				//获取一个用户的粉丝列表的url
				String userUrl=HOST+li.getElementsByTag("h4").first()
						.getElementsByTag("a").first()
						.attr("href")+"/contacts";
				//获取一个用户的用户名
				String userName=li.getElementsByTag("h4").first()
						.getElementsByTag("a").first().text();
				//本地已保存就不再加入队列
				if(!new File(SAVE_PAYH+userName+".jpg").exists()){
					userUrlQueue.put(userUrl);
					userHeadUrlQueue.put(userHeadUrl);
					userNameQueue.put(userName);
				}
			}
			//队列空了,isRun=false
			isRun=false;
		}

	}
	/**
	 * 获取图片并保存到本地
	 * @param imgUrl
	 * @param localPath
	 * @throws Exception
	 */
	private static void getImage(String imgUrl,String localPath) throws Exception {
		//System.out.println(imgUrl);
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpGet httpget= new HttpGet(imgUrl);
		CloseableHttpResponse resp=httpclient.execute(httpget);
		InputStream inputStream=resp.getEntity().getContent();
		FileOutputStream fileOutputStream=new FileOutputStream(localPath);
		byte[] buf=new byte[1024];
		int len=0;
		while ((len=inputStream.read(buf))!=-1) {
			fileOutputStream.write(buf, 0, len);
			fileOutputStream.flush();
		}
		inputStream.close();
		fileOutputStream.close();
		
	}
	/**
	 * 获取链接线程
	 * @author zyw
	 *
	 */
	public static class UserThread  extends Thread{
	
		@Override
		public void run() {
			// TODO Auto-generated method stub
			//如果队列userUrlQueue不为空
			while (!userUrlQueue.isEmpty()) {
				try {
					getUserUrl();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
	}
	/**
	 * 获取头像线程
	 * @author zyw
	 *
	 */
	public static class HeadThread  extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			//如果队列userHeadUrlQueue不为空,或者UserThread在工作
			while (!userHeadUrlQueue.isEmpty()||isRun) {
				try {
					String imgUrl=userHeadUrlQueue.poll();
					String userName=userNameQueue.poll();
					getImage(imgUrl, SAVE_PAYH+userName+".jpg");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
	}
	
}

MyQueue.java

package main;
import java.util.LinkedList;
import java.util.Queue;

/**
 * 线程安全队列
 * @author zyw
 *
 * @param 
 */
public class MyQueue {
	 private LinkedList userUrlQueue=new LinkedList();
	 private Object lock=new Object();
	 
	 /**
	  * 获取队列是否为空
	  * @return
	  */
	 public boolean isEmpty() {
		return userUrlQueue.isEmpty();
	}
	 
	 /**
	  * 将一个元素插入队列尾
	  * @param t
	  */
	 public void put(T t) {
		 synchronized (lock) {
			userUrlQueue.addLast(t);
		}
	}
	 
	 /**
	  * 队列头取出一个元素
	  * @return
	  */
	 public T  poll() {
		 T t=null;
		 synchronized (lock) {
			 t=(T) userUrlQueue.removeFirst();
		 }
		return t;
	}
}

效果图

Java实现简易爬虫--抓取酷安网用户头像_第3张图片


方法二:


爬虫思路

把用户id从小到大遍历,用正则匹配一下用户头像的URL.

代码

Worm.java

package main;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
importorg.apache.http.client.methods.CloseableHttpResponse;
importorg.apache.http.client.methods.HttpGet;
importorg.apache.http.impl.client.CloseableHttpClient;
importorg.apache.http.impl.client.HttpClients;
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 Worm {
       privatestatic final String SAVE_PAYH="D:/coolapk1/";
       privatefinal static String URL="http://www.coolapk.com/u/";
       publicstatic void main(String[] args) throws IOException {
              //TODO Auto-generated method stub
              java.io.Filef=new java.io.File(SAVE_PAYH);
              //如果文件夹不存在,则创建
              if(!f.exists())
              {
                     f.mkdirs();
              }
              getHeads();
       }
       /**
        * 获取头像
        * @throws IOException
        */
       privatestatic void getHeads() throws IOException {
              //遍历用户id获取头像
              for(inti=10001;i<870000;i++)
              {
                     try{
                     Connectionconnection=Jsoup.connect(URL+i);
                     Documentdoc=connection.get();
                     Elementselements=doc.select(".username");//得到用户名
                     Elementelement=elements.first();
                     Stringusername=element.html();
                     Stringhtml=doc.html();
                     //利用正则表达式取头像链接
                     Patternpattern=Pattern.compile("http://avatar.coolapk.com/data/([^\"]*)");
                     Matchermatcher=pattern.matcher(html);
                     if(matcher.find())
                     {
                            StringimgUrl=matcher.group(0);
                            imgUrl=imgUrl.replaceAll("middle","big");//替换成大头像链接
                            getImage(imgUrl,SAVE_PAYH+i+"_"+username+".jpg");
                     }
 
                     }
                     catch(Exceptione)
                     {
                            e.printStackTrace();
                     }
              }
       }
       /**
        * 获取图片并保存到本地
        * @param imgUrl
        * @param localPath
        * @throws Exception
        */
       privatestatic void getImage(String imgUrl,String localPath) throws Exception {
              //System.out.println(imgUrl);
              CloseableHttpClienthttpclient = HttpClients.createDefault();
              HttpGethttpget= new HttpGet(imgUrl);
              CloseableHttpResponseresp=httpclient.execute(httpget);
              InputStreaminputStream=resp.getEntity().getContent();
              FileOutputStreamfileOutputStream=new FileOutputStream(localPath);
              byte[]buf=new byte[1024];
              intlen=0;
              while((len=inputStream.read(buf))!=-1) {
                     fileOutputStream.write(buf,0, len);
                     fileOutputStream.flush();
              }
              inputStream.close();
              fileOutputStream.close();
             
       }
}

效果图

Java实现简易爬虫--抓取酷安网用户头像_第4张图片

源码下载: https://github.com/luoyesiqiu/CoolapkWorm

总结:使用方法一有助于理解爬虫过程,方法二则比较稳定

你可能感兴趣的:(爬虫)