以酷安网用户粉丝较多的用户的个人中心为进口,获取该用户的全部粉丝的个人中心链接,用户头像链接和用户名,并分别放入队列。开启两个线程获取信息,一个线程获取队列中的用户的信息并放入队列,另一个线程负责从头像链接队列中取出链接并下载用户头像。
用浏览器打开一个用户的粉丝列表(http://coolapk.com/u/[用户id]/contacts)
并查看源码
我们可以看到粉丝列表以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;
}
}
把用户id从小到大遍历,用正则匹配一下用户头像的URL.
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();
}
}