吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 24939|回复: 108
收起左侧

[Java 原创] 【Java】网络爬虫-爬取美女图集

    [复制链接]
皮皮虾自己走 发表于 2018-2-23 15:18
本帖最后由 wushaominkk 于 2018-5-7 17:05 编辑

看到论坛中有不少爬取网站中美女图片的帖子,不过都是Python版的,于是乎就想给大家发一个JAVA版的网络爬虫教程。

目标网站:http://www.mmjpg.com/hot/

爬虫其实很简单的,只需用到两个外部库 -Jsoup 和 htmlnuit

一般最常用的就是Jsoup,当然了如果碰到了需要执行JavaScript和AJAX的网站那就需要用到 htmlnuit这个强大的库了,这个两个配合那可谓是无可匹敌!

网站分析:这个网站用到了AJAX 所以说两个库都需要用到:

1.png

对于这两个库的使用很简单的!



首先看下项目结构:

2.png

首先是Jar包: 引用的有:jsoup、htmlnuit、RxJAVA、OkHttp

parse包中主要是网页解析器类

HttpUtil类是网络请求的工具类

RequestThread类作为网络请求给一个URl地址并自动转化为所需要的Bean对象的集合并返回

OkHttp类是作为OkHttp的单例类

BaseParse是一个网页解析器的抽象模板

ParsePicture2 类是作为本次帖子所使用的网页解析器 ,对于1 嘛 嘿嘿老司机自行补脑 :

[Java] 纯文本查看 复制代码
public class ParsePicture2 extends BaseParse<List<PictureBean>, PictureBean> {
   private static final String [i]ROOT_URL [/i]= "http://www.mmjpg.com";

   public static void main(String[] a) throws Exception {

   }

   @Override
   public int getPager(String html) {
      Elements div = Jsoup.parse(html).getElementsByClass("page");
      Elements a = div.select("a");
      if(a.size()==0)
         return 1;
      String pager = a.get(a.size() - 1)
            .attr("href")
            .replaceAll("\\D", "");
      return pager == null || pager.isEmpty() ? 1 : Integer.valueOf(pager);
   }

   @Override
   public List<PictureBean> getMessage(String html) {
      List<PictureBean> data = new ArrayList<>();
      Elements li = Jsoup.parse(html).getElementsByClass("pic").select("li");
      for (Element e : li) {
         Element a = e.selectFirst("a");
         String title = a.selectFirst("img").attr("alt");
         String url = a.attr("href");
         PictureBean bean = new PictureBean(title, url);
         data.add(bean);
      }
      return data;
   }

   @Override
   public synchronized String getDetail(PictureBean obj) {
      String url = obj.getPictureList().get(0);
      //初始化参数
      WebClient webClient = new WebClient();
      webClient.getOptions().setCssEnabled(false);
      webClient.getOptions().setJavaScriptEnabled(true);
      //设置支持AJAX特TM重要的
      webClient.setAjaxController(new NicelyResynchronizingAjaxController());
      webClient.getOptions().setTimeout(5000);
      webClient.getOptions().setThrowExceptionOnScriptError(false);
      webClient.getCookieManager().setCookiesEnabled(true);
      webClient.getOptions().setUseInsecureSSL(true);
      try {
         HtmlPage page = webClient.getPage(url);

         //如果第一层(getMessage())没有得到标题那么再这里重新获取
         if(obj.getTitle()==null || obj.getTitle().isEmpty()){
            List<HtmlElement> list = page.getBody().getElementsByAttribute("div", "class", "article");
            String title = list.get(0).getElementsByTagName("h2").get(0).asText();
            obj.setTitle(title);
         }
         HtmlElement element = page.getHtmlElementById("opic");
         [i]/*
[/i][i]         [/i][i]这里是执行[/i][i]JavaScript[/i][i]的代码[/i][i]
[/i][i]         String clickAttribute = element.getOnClickAttribute();
[/i][i]         ScriptResult result = page.executeJavaScript(clickAttribute);
[/i][i]         HtmlPage page1 = (HtmlPage) result.getNewPage();*/
[/i][i]         [/i]HtmlPage page1 = element.click();
         List<HtmlElement> content = page1
               .getBody()
               .getElementsByAttribute("div", "class", "content")
               .get(0)
               .getElementsByTagName("img");
         for (HtmlElement h : content) {
            String src = h.getAttribute("src");
            obj.getPictureList().add(src);
         }
      } catch (IOException e) {
         System.[i]err[/i].println("出错:" + e.getMessage());
         return null;
      } finally {
         webClient.close();
      }
      if (obj.getPictureList().size() == 0)
         return null;
      return "SUCCESS";

   }

   @Override
   public String switchPager(String url, int index) {
      //http://www.mmjpg.com/home/20
      String path = url.substring(0, url.lastIndexOf("/") + 1);
      if (index == 1)
         return url;
      return path + index;
   }

   @Override
   public void execute() {
      ExecutorService service = getExecutorService();
      service.execute(new RequestThread(this, "http://www.mmjpg.com/hot/"));
      //service.execute(new RequestThread(this, ROOT_URL));
      service.shutdown();
   }
}


方法的说明:

public int getPager(String html)

此方法作为要获取有多少页码


public List<PictureBean> getMessage(String html)

此方法作为爬取网页中的连接地址以及标题  --也就是说爬的是首页


public synchronized String getDetail(PictureBean obj)

此方法作为根据爬取后的连接地址然后第二次爬取,这次爬取的就是所有的图片了  --就是说爬的是首页中的每一个图集的地址


public String switchPager(String url, int index)

此方法作为根据index 自动返回新的需要爬取的页码地址


public void execute()

执行爬取操作




网络请求 自动转为List对象类:
[Java] 纯文本查看 复制代码
public class RequestThread extends Thread {
   private BaseParse mParse;
   private String mUrl;
   private SimpleDateFormat simpleDateFormat;

   public RequestThread(BaseParse parse, String url) {
      this.mParse = parse;
      this.mUrl = url;
      this.simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
   }

   @Override
   public void run() {
      try {
         execute();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   private void execute() throws Exception {
      int pagerCount = mParse.getPager(HttpUtil.doGetForResult(mUrl));
      System.[i]out[/i].println("总页数:"+pagerCount);
      for (int i = 1; i <= pagerCount; i++) {
         String currentUrl = mParse.switchPager(mUrl, i);
         Observable.create((ObservableOnSubscribe<List>) observableEmitter -> {
            List message = mParse.getMessage(HttpUtil.doGetForResult(currentUrl));
            if (message.size() != 0) {
               observableEmitter.onNext(message);
               observableEmitter.onComplete();
            } else {
               observableEmitter.onError(new NullPointerException("长度为0,连接:"+currentUrl));
            }
         })
               .map(ts -> {
                  List data = new ArrayList();
                  for (Object s : ts) {
                     String detail = mParse.getDetail(s);
                     if(detail!=null)
                        data.add(s);
                  }
                  return data;
               })
               .subscribeOn(Schedulers.io())
               .subscribe(new Observer<List>() {
                  @Override
                  public void onSubscribe(Disposable disposable) {

                  }

                  @Override
                  public void onNext(List ts) {
                     String date = simpleDateFormat.format(System.currentTimeMillis());
                     for (Object s : ts)
                        System.[i]out[/i].println(date + "--" + s.toString());
                     Main.DATA.addAll(ts);
                  }

                  @Override
                  public void onError(Throwable throwable) {
                     System.[i]err[/i].println(throwable.getMessage());
                  }

                  @Override
                  public void onComplete() {

                  }
               });
      }
   }
}


/**
* 网络请求
*/


Main方法:
[Java] 纯文本查看 复制代码
public static void main(String[] args) throws Exception {
//    new ParsePicture1().execute();
      new ParsePicture2().execute();

      Scanner sc = new Scanner(System.[i]in[/i]);
      String in = sc.nextLine();
      /**
       * 输入exit退出程序
       * 输入do 开始下载图片到本地
       * 输入其他查看当前爬取了多少条目
       */
      while (!in.equals("exit")) {
         System.[i]out[/i].println("总条数:" + DATA.size());
         if (in.equals("do"))
            downloadImage();
         in = sc.nextLine();
      }

   }

爬取过程的部分预览:

3.png


部分下载预览:

5.png





最后需要补充的 介于大家用的编译器可能不同

所以这次打包就不上传整个项目 而是单独提取出来src 文件 和 lib Jar包文件

大家在使用的时候先自己新建一个JAVA项目然后拷贝这些文件到的项目中去,记得别忘了添加jar包的引入哦!

重要的是 项目中使用的Java 8


还有就是你在爬取的时候在控制台会打印图片的下载地址你直接打开会发现,所有图片都是一样的嘿嘿,因为这个网站加了防盗链 下载的时候因为加入了

con.addRequestProperty("Referer",referer);

一个请求头  引用百度搜的一句话:

{


使用HTTP协议。利用referer做防盗链
我们在网页里访问站外的图片的时候,在图片本站是可以看得,在外头就不能看了
因为header信息中的referer元素。
}
看下我下载的方法会发现这个一句话:
inputStream = HttpUtil.getStream(bean.getPictureList().get(index),
                                                                bean.getPictureList().get(0));
就是第二个参数,具体的请自己好好研究下源码吧!


如果您觉得很不错,就请多给点分吧!

百度云下载地址:
链接: https://pan.baidu.com/s/1dHatqhV 密码: tn9v

免费评分

参与人数 35吾爱币 +30 热心值 +34 收起 理由
lxw + 1 我很赞同!
skyskin + 1 + 1 谢谢@Thanks!
serry + 1 + 1 我很赞同!
wentwent + 1 + 1 谢谢@Thanks!
czxtzh + 1 + 1 谢谢@Thanks!
MoneyOpen + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hanping0402 + 1 + 1 能直接编译成软件么。小白不懂这个啊
孤独的明月 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
我真的成功了吗 + 1 还在学java入门的我前来观摩大神
li99774 + 1 + 1 网站收藏了
吾爱妹子涛 + 1 + 1 我很赞同!
fkhk_0415 + 1 + 1 我很赞同!
zhuchaogan + 1 + 1 热心回复!
萋小磊 + 2 + 1 拿走了
luxiangfei + 1 + 1 谢谢@Thanks!
jornlin + 1 + 1 我很赞同!
java2018 + 1 + 1 用心讨论,共获提升!
yuirking + 1 谢谢@Thanks!
codegitz + 1 + 1 谢谢@Thanks!
sqdashen + 1 + 1 我爱学习
xiaolj + 1 + 1 学习技术不忘福利,这破操作666
buhuiba11 + 1 + 1 获取的网站算是福利吧!!!
断弯刀 + 1 感谢
Mr_GiraffeY + 1 + 1 我很赞同!
big猫 + 1 + 1 我很赞同!
bxy + 1 + 1 用心讨论,共获提升!
xman55555 + 1 + 1 我很赞同!
zhouyu0701 + 1 + 1 我很赞同!
昔年谁是谁非 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
qwe2913207 + 1 用心讨论,共获提升!
changjiang + 1 + 1 我很赞同!
1807410681 + 1 + 1 谢谢@Thanks!
332178891 + 1 + 1 谢谢@Thanks!
wshenm + 1 + 1 用心讨论,共获提升!
萌萌哒的小白 + 1 这个必须收藏!!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

energy28555 发表于 2018-2-23 15:41 来自手机
要那么多图片没用,还是没有女朋友啊~
nred 发表于 2018-3-22 14:19
萌萌哒的小白 发表于 2018-2-23 15:49
谢谢!总想学但是又懒得去找!!

总页数:1
鍑洪敊:Connect to www.mmjpg.com:80 [www.mmjpg.com/118.193.159.249] failed: connect timed out
鍑洪敊:Connect to www.mmjpg.com:80 [www.mmjpg.com/118.193.159.249] failed: connect timed out
连接失败了 有别的网站可以爬吗?或者这个可以爬别的网站吗?
博爵 发表于 2018-2-23 15:33
a86054950 发表于 2018-2-23 15:35
博爵 发表于 2018-2-23 15:33
你们要那么多美女图片干什么用

撸啊 做壁纸
Defender 发表于 2018-2-23 15:36
同问,要那么多的美女图片干什么?
m1617641027 发表于 2018-2-23 15:38 来自手机
学习一下
Dxx22 发表于 2018-2-23 15:40
研究一下1
恶梦玩家 发表于 2018-2-23 15:42
正想学习爬虫过来看看大神.
YanZhou 发表于 2018-2-23 15:48
不会用。。。。
萌萌哒的小白 发表于 2018-2-23 15:49
谢谢!总想学但是又懒得去找!!

免费评分

参与人数 1热心值 +1 收起 理由
haanzcx + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 20:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表