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

爬虫思路

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

爬虫分析

用浏览器打开一个用户的粉丝列表(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<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

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;
	}
}

效果图

时间: 2024-10-10 17:39:07

Java实现简易爬虫--抓取酷安网用户头像的相关文章

php+phpquery简易爬虫抓取京东商品分类

这是一个简单的php加phpquery实现抓取京东商品分类页内容的简易爬虫.phpquery可以非常简单地帮助你抽取想要的html内容,phpquery和jquery非常类似,可以说是几乎一样:如果你有jquery的基础的话你可以迅速地上手. 1.下载phpquery并置于web根目录下的phpQuery文件夹 phpquery下载:https://code.google.com/p/phpquery/downloads/list phpquery教程可在这里查看:https://code.go

JAVA使用Gecco爬虫 抓取网页内容

JAVA 爬虫工具有挺多的,但是Gecco是一个挺轻量方便的工具. 先上项目结构图. 这是一个 JAVASE的 MAVEN 项目,要添加包依赖,其他就四个文件.log4j.properties 加上三个java类. 1.先配置log4j.properties log4j.rootLogger = error,stdout,D,E log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Targe

Java豆瓣电影爬虫——抓取电影详情和电影短评数据

一直想做个这样的爬虫:定制自己的种子,爬取想要的数据,做点力所能及的小分析.正好,这段时间宝宝出生,一边陪宝宝和宝妈,一边把自己做的这个豆瓣电影爬虫的数据采集部分跑起来.现在做一个概要的介绍和演示. 动机 采集豆瓣电影数据包括电影详情页数据和电影的短评数据. 电影详情页如下图所示 需要保存这些详情字段如导演.编剧.演员等还有图中右下方的标签. 短评页面如下图所示 需要保存的字段有短评所属的电影名称,每条评论的详细信息如评论人名称.评论内容等. 数据库设计 有了如上的需求,需要设计表,其实很简单,

Python爬虫抓取技术的门道

web是一个开放的平台,这也奠定了web从90年代初诞生直至今日将近30年来蓬勃的发展.然而,正所谓成也萧何败也萧何,开放的特性.搜索引擎以及简单易学的html.css技术使得web成为了互联网领域里最为流行和成熟的信息传播媒介:但如今作为商业化软件,web这个平台上的内容信息的版权却毫无保证,因为相比软件客户端而言,你的网页中的内容可以被很低成本.很低的技术门槛实现出的一些抓取程序获取到,这也就是这一系列文章将要探讨的话题-- 网络爬虫 . 有很多人认为web应当始终遵循开放的精神,呈现在页面

爬虫抓取网页相似度判断

爬虫抓取网页过程中,会产生很多的问题,当然最重要的一个问题就是重复问题,网页的重复抓取.最简单的方式就是对url去重.已经抓取过的url不再抓取.但是其实在实际业务中是需要对于已经抓取过的URL进行再次抓取的.例如 BBS .bbs存在大量的更新回复,但是url不会发生改变. 一般情况下的url去重方式,就是判断url是否抓取过,如果抓取过就不再抓取,或者是在一定时间内不再抓取.. 我的需求也是这样的, 所以首先做的就是url去重. 在爬虫发现链接,加入待抓取队列的时候,会对url进行验证,是否

htmlunit+fastjson抓取酷狗音乐 qq音乐链接及下载

上次学了jsoup之后,发现一些动态生成的网页内容是无法抓取的,于是又学习了htmlunit,下面是抓取酷狗音乐与qq音乐链接的例子: 酷狗音乐: import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.UUID; import

python 爬虫抓取心得

quanwei9958 转自 python 爬虫抓取心得分享 urllib.quote('要编码的字符串') 如果你要在url请求里面放入中文,对相应的中文进行编码的话,可以用: urllib.quote('要编码的字符串') query = urllib.quote(singername) url = 'http://music.baidu.com/search?key='+query response = urllib.urlopen(url) text = response.read()

爬虫技术(四)-- 简单爬虫抓取示例(附c#代码)

这是我的第一个爬虫代码...算是一份测试版的代码.大牛大神别喷... 通过给定一个初始的地址startPiont然后对网页进行捕捉,然后通过正则表达式对网址进行匹配. List<string> todo :进行抓取的网址的集合 List<string> visited :已经访问过的网址的集合 下面实现的是,给定一个初始地址,然后进行爬虫,输出正在访问的网址和已经访问的网页的个数. 需要注意的是,下面代码实现的链接匹配页面的内容如图一.图二所示: 图一: 图二: 简单代码示范如下:

Python3简单爬虫抓取网页图片

现在网上有很多python2写的爬虫抓取网页图片的实例,但不适用新手(新手都使用python3环境,不兼容python2),所以我用Python3的语法写了一个简单抓取网页图片的实例,希望能够帮助到大家,并希望大家批评指正. 1 import urllib.request 2 import re 3 import os 4 import urllib 5 #根据给定的网址来获取网页详细信息,得到的html就是网页的源代码 6 def getHtml(url): 7 page = urllib.r