转载自:http://blog.csdn.net/e_one/article/details/60876076
爬虫思路
以酷安网用户粉丝较多的用户的个人中心为进口,获取该用户的全部粉丝的个人中心链接,用户头像链接和用户名,并分别放入队列。开启两个线程获取信息,一个线程获取队列中的用户的信息并放入队列,另一个线程负责从头像链接队列中取出链接并下载用户头像。
爬虫分析
用浏览器打开一个用户的粉丝列表(http://coolapk.com/u/[用户id]/contacts)
并查看源码
我们可以看到粉丝列表以HTML的ul标签显示,并且其id为dataList,ul标签中的各个li标签即为每一个用户的信息啦~再进一步分析,li标签中的img标签为用户头像。h4标签的内容即为用户名,h4标签中的a标签的href属性为用户的个人中心链接。
通过观察我们还知道:用户的粉丝列表链接=个人中心链接+ "/contacts"
这样我们就可以开始爬取头像了
用到的库
Jsoup https://jsoup.org/download
HttpClient http://hc.apache.org/downloads.cgi
代码
Main.Java
[java] view plain copy print?
- 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<String> userUrlQueue=new MyQueue<>();
- //用户头像链接队列
- private static MyQueue<String> userHeadUrlQueue=new MyQueue<>();
- //用户名队列
- private static MyQueue<String> 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
[java] view plain copy print?- package main;
- import java.util.LinkedList;
- import java.util.Queue;
- /**
- * 线程安全队列
- * @author zyw
- *
- * @param <T>
- */
- public class MyQueue<T> {
- private LinkedList<T> userUrlQueue=new LinkedList<T>();
- 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;
- }
- }