1. package com.wang.xiaowei.utils;
  2.  
  3. import com.sun.image.codec.jpeg.JPEGCodec;
  4. import com.sun.image.codec.jpeg.JPEGImageEncoder;
  5. import org.apache.http.HttpEntity;
  6. import org.apache.http.client.config.RequestConfig;
  7. import org.apache.http.client.methods.HttpGet;
  8. import org.apache.http.impl.client.CloseableHttpClient;
  9. import org.apache.http.impl.client.HttpClients;
  10. import org.apache.http.util.EntityUtils;
  11. import org.jsoup.Jsoup;
  12. import org.jsoup.nodes.Document;
  13. import org.jsoup.nodes.Element;
  14. import org.jsoup.select.Elements;
  15. import javax.imageio.ImageIO;
  16. import java.awt.*;
  17. import java.awt.image.BufferedImage;
  18. import java.io.File;
  19. import java.io.FileOutputStream;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;
  22. import java.net.URL;
  23. import java.text.SimpleDateFormat;
  24. import java.util.Date;
  25. import java.util.HashMap;
  26. import java.util.Map;
  27. import java.util.UUID;
  28.  
  29. /**
  30. * @author WXW on 2017/11/22.
  31. */
  32. public class TieBaImageDownload {
  33.  
  34. private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom()
  35. .setSocketTimeout(15000)
  36. .setConnectTimeout(15000)
  37. .setConnectionRequestTimeout(15000)
  38. .build();
  39.  
  40. /**贴吧主路径*/
  41. private static final String TB_BASE_URL = "https://tieba.baidu.com";
  42. /**用于存放url*/
  43. private static Map<String,String> URL_MAP;
  44. /**图片保存的路径*/
  45. private static final String IMAGE_SAVE_DIRECT = "E:/baiduimage/";
  46. /**HttpClient对象*/
  47. private static CloseableHttpClient httpClient = null;
  48. /**每页有多少条帖子*/
  49. private static final int EVERY_PAGE_COUNT_SIZE = 50;
  50.  
  51. /**水印图片路径*/
  52. private static final String WATER_IMAGE_PATH = "E://baiduimage//3.png";
  53. /**透明度*/
  54. private static final float WATER_IMAGE_ALPHA = 0.5F;
  55. /**X间距*/
  56. private static final int WATER_IMAGE_MARGIN_Y = 100;
  57. /**Y间距*/
  58. private static final int WATER_IMAGE_MARGIN_X = 100;
  59. /**水印图片选中角度*/
  60. private static final int WATER_IMAGE_RADIANS = 30;
  61.  
  62. /**
  63. * 获取指定贴吧的全部内容
  64. * @param key 贴吧关键字
  65. * @param maxPage 最大页码
  66. * @param onlySeeLz 是否只看楼主
  67. * @param addWaterImage 是否添加水印
  68. * @throws Exception e
  69. */
  70. public static void getHttpUrl(String key,int maxPage,boolean onlySeeLz,boolean addWaterImage) throws Exception{
  71. //初始化httpclient对象
  72. httpClient = HttpClients.createDefault();
  73.  
  74. //开始按照页面爬取内容
  75. while(maxPage > 0){
  76. System.out.println("=============正在处理第"+maxPage+"页===================");
  77. //每页有50条数据
  78. int pageIndex = (maxPage - 1) * EVERY_PAGE_COUNT_SIZE;
  79. //路径
  80. String spaderUrl = TB_BASE_URL + "/f?kw=" + key + "&ie=utf-8&pn="+ pageIndex;
  81. System.out.println("spaderUrl==== "+spaderUrl);
  82. String responseContent = getHtmlContent(spaderUrl);
  83. processHtml(responseContent,onlySeeLz);
  84. maxPage--;
  85. }
  86. httpClient.close();
  87. downLoadImage(addWaterImage);
  88. }
  89.  
  90. /***
  91. * 根据url获取页面源码内容
  92. * @param url url
  93. * @return 页面源码内容
  94. * @throws Exception e
  95. */
  96. private static String getHtmlContent(String url) throws Exception {
  97. //get方式获取页面内容
  98. HttpGet get = new HttpGet(url);
  99. get.setConfig(REQUEST_CONFIG);
  100. HttpEntity entity = httpClient.execute(get).getEntity();
  101. return EntityUtils.toString(entity, "UTF-8");
  102. }
  103.  
  104. /***
  105. * 处理html内容
  106. * @param responseContent html内容
  107. * @param onlySeeLz 是否只看楼主
  108. * @throws Exception e
  109. */
  110. private static void processHtml(String responseContent,boolean onlySeeLz) throws Exception {
  111. Document doc = Jsoup.parse(responseContent);
  112. //获取所有 class=j_th_tit 的 a标签;帖子的具体连接
  113. Elements urls = doc.select("a.j_th_tit");
  114. for (Element e : urls){
  115. //帖子标题
  116. String tText = e.text();
  117. //帖子连接
  118. String tUrl = e.attr("href");
  119. tUrl = TB_BASE_URL + "" + tUrl;
  120. //只看楼主
  121. if(onlySeeLz){
  122. tUrl = tUrl + "?see_lz=1";
  123. }
  124. //将获取到的帖子url放入Map
  125. URL_MAP.put(tText,tUrl);
  126. }
  127. }
  128.  
  129. /***
  130. * 获取每个帖子内容中的图片信息
  131. * @param addWaterImage 是否加水印
  132. * @throws Exception e
  133. */
  134. private static void downLoadImage(boolean addWaterImage) throws Exception {
  135. for (String str : URL_MAP.values()){
  136. //帖子的url
  137. System.out.println("帖子的url=== "+str);
  138. Document doc = Jsoup.connect(str).get();
  139. //帖子中 class=img.BDE_Image的元素
  140. Elements images = doc.select("img.BDE_Image");
  141. for (Element e : images){
  142. //获取图片url
  143. String imageUrl = e.attr("src");
  144. System.out.println("imageUrl============ "+imageUrl);
  145. saveImage(imageUrl,addWaterImage);
  146. }
  147. }
  148. }
  149.  
  150. /**
  151. * 将图片保存到本地
  152. * @param imageUrl imageUrl
  153. * @param addWaterImage addWaterImage
  154. * @throws Exception e
  155. */
  156. private static void saveImage(String imageUrl,boolean addWaterImage) throws Exception{
  157. //每天创建一个目录
  158. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
  159. String filePath = sdf.format(new Date());
  160. File imageFile = new File(IMAGE_SAVE_DIRECT+"//"+filePath);
  161. if(!imageFile.exists()){
  162. if (imageFile.mkdirs()){
  163. System.out.println("---------创建目录成功-------------");
  164. }
  165. }
  166. //随机生成图片名称
  167. String fileName = UUID.randomUUID().toString().replaceAll("-","");
  168. URL url = new URL(imageUrl);
  169. InputStream is = url.openStream();
  170. OutputStream os = new FileOutputStream(IMAGE_SAVE_DIRECT+"//"+filePath + "//" + fileName +".jpg");
  171. if(addWaterImage){
  172. addWaterImage(url,os);
  173. }
  174. if(!addWaterImage){
  175. saveImageWithoutWaterImage(is,os);
  176. }
  177. }
  178.  
  179. private static void saveImageWithoutWaterImage(InputStream is,OutputStream os) throws Exception{
  180. byte[] buff = new byte[1024];
  181. int readed;
  182. while ((readed = is.read(buff)) != -1) {
  183. os.write(buff, 0, readed);
  184. }
  185. is.close();
  186. os.close();
  187. }
  188.  
  189. /***
  190. * 打印水印
  191. * @param sourceImagePath 原图片路径
  192. * @param os os
  193. * @throws Exception e
  194. */
  195. private static void addWaterImage(URL sourceImagePath,OutputStream os) throws Exception{
  196. //根据图片路径生成图片对象。获取图片的宽度高度
  197. Image image = ImageIO.read(sourceImagePath);
  198. int width = image.getWidth(null);
  199. int height = image.getHeight(null);
  200.  
  201. //根据图片的宽高,生成画布,将原图画到画布
  202. BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  203. Graphics2D graphics2d = bufferedImage.createGraphics();
  204. graphics2d.drawImage(image, 0, 0, width, height, null);
  205.  
  206. //水印图片
  207. Image waterImage = ImageIO.read(new File(WATER_IMAGE_PATH));
  208. int waterImageWidth = waterImage.getWidth(null);
  209. int waterImageHeight = waterImage.getHeight(null);
  210.  
  211. //水印透明设置
  212. graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, WATER_IMAGE_ALPHA));
  213. //旋转 rotate(选中度数,圆心x坐标,圆心y坐标)
  214. graphics2d.rotate(Math.toRadians(WATER_IMAGE_RADIANS), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
  215.  
  216. // 循环打印水印图片
  217. int waterImageX = -width / 2;
  218. while(waterImageX < width * 1.5){
  219. int waterImageY = -height / 2;
  220. while(waterImageY < height * 1.5){
  221. graphics2d.drawImage(waterImage, waterImageX, waterImageY, null);
  222. waterImageY += waterImageHeight + WATER_IMAGE_MARGIN_Y;
  223. }
  224. waterImageX += waterImageWidth + WATER_IMAGE_MARGIN_X;
  225. }
  226. graphics2d.dispose();
  227.  
  228. //创建图像编码工具类
  229. JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
  230. //使用图像编码工具类,输出缓存图像到目标文件
  231. en.encode(bufferedImage);
  232. os.close();
  233. }
  234.  
  235. public static void main(String[] args){
  236. try {
  237. URL_MAP = new HashMap<>();
  238. boolean onlySeeLz = true;
  239. String key = "柳岩";
  240. int maxPage = 1;
  241. boolean addWaterImage = true;
  242. getHttpUrl(key,maxPage,onlySeeLz,addWaterImage);
  243. } catch (Exception e) {
  244. e.printStackTrace();
  245. }
  246. }
  247.  
  248. }

JAVA爬取百度贴吧图片的更多相关文章

  1. Java爬取 百度图片Google图片Bing图片

    先看看抓取的结果. 8个Java类: Startup.java - main函数 ImageCrawler.java - Crawler基类 BaiduImageCrawler.java - 百度图片 ...

  2. Python简易爬虫爬取百度贴吧图片

    通过python 来实现这样一个简单的爬虫功能,把我们想要的图片爬取到本地.(Python版本为3.6.0) 一.获取整个页面数据 def getHtml(url): page=urllib.requ ...

  3. 【Python】Python简易爬虫爬取百度贴吧图片

    通过python 来实现这样一个简单的爬虫功能,把我们想要的图片爬取到本地.(Python版本为3.6.0) 一.获取整个页面数据 def getHtml(url): page=urllib.requ ...

  4. java爬取百度首页源代码

    爬虫感觉挺有意思的,写一个最简单的抓取百度首页html代码的程序.虽然简单了一点,后期会加深的. package test; import java.io.BufferedReader; import ...

  5. Python: 爬取百度贴吧图片

    练习之代码片段,以做备忘: # encoding=utf8 from __future__ import unicode_literals import urllib, urllib2 import ...

  6. Python爬取百度贴吧图片

    一.获取URL Urllib 模块提供了读取web页面数据的接口,我们可以像读取本地文件一样读取www和ftp上的数据.首先,我们定义了一个getHtml()函数: urllib.urlopen()方 ...

  7. Python每日一练(3):爬取百度贴吧图片

    import requests,re #先把要访问URL和头部准备好 url = 'http://tieba.baidu.com/p/2166231880' head = { 'Accept': '* ...

  8. 百度图片爬虫-python版-如何爬取百度图片?

    上一篇我写了如何爬取百度网盘的爬虫,在这里还是重温一下,把链接附上: http://www.cnblogs.com/huangxie/p/5473273.html 这一篇我想写写如何爬取百度图片的爬虫 ...

  9. python爬取某个网页的图片-如百度贴吧

    python爬取某个网页的图片-如百度贴吧 作者:vpoet mail:vpoet_sir@163.com 注:随意copy,不用告诉我 #coding:utf-8 import urllib imp ...

随机推荐

  1. Android提高第九篇之GridView和SQLite实现分页表格

    实现并封装一个SQL分页表格控件,不仅支持分页还是以表格的形式展示数据.先来看看本文程序运行的动画: 这个SQL分页表格控件主要分为“表格区”和“分页栏”这两部分,这两部分都是基于GridView实现 ...

  2. CSS实现和选择器

    CSS实现和选择器 本课内容: 一.实现CSS四种方式 1,每个html标签中都有一个style样式属性,该属性的值就是css代码.(针对一个标签)2,使用style标签的方式. 一般都定义在head ...

  3. python模块——re模块(简单的计算器功能实现_eval版)

    #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" # Usage: Make a Diy Calcu ...

  4. Android之ToolBar和自定义ToolBar实现沉浸式状态栏

    沉浸式状态栏确切的说应该叫做透明状态栏.一般情况下,状态栏的底色都为黑色,而沉浸式状态栏则是把状态栏设置为透明或者半透明. 沉浸式状态栏是从android Kitkat(Android 4.4)开始出 ...

  5. android--------Retrofit+RxJava的使用

    Retrofit是Square公司开发的一款针对Android网络请求的一个当前很流行的网络请求库. http://square.github.io/retrofit/ https://github. ...

  6. 连接ACCESS

    access2000-2003数据库连接字符串: ConStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=数据库名.mdb"; ...

  7. ASP.NET的路由系统

    一.URL与物理文件的分离 1.URL与物理文件的分离 对于一个 ASP.NET Web Form应用来说,任何一个请求都对应着某个具体的物理文件.部署在Web服务器上的物理文件可以是静态的(比如图片 ...

  8. python运维之使用python进行批量管理主机

    1. python运维之paramiko 2. FABRIC 一个与多台服务器远程交互的PYTHON库和工具 3. SSH连接与自动化部署工具paramiko与Fabric 4. Python批量管理 ...

  9. 上传xslx文件设置accept的MIME 类型

    .dotx:application/vnd.openxmlformats-officedocument.wordprocessingml.template.docx:application/vnd.o ...

  10. HashTable vs HashMap(三)

    HashTable的应用非常广泛,HashMap是新框架中用来代替HashTable的类,也就是说建议使用HashMap,不要使用HashTable. 可能你觉得HashTable很好用,为什么不用呢 ...