Android 网络图片查看器HappyLook开发

  • 一、前言
  • 二、框架介绍
    • 1、Jsoup简介
    • 2、EventBus简介
    • 3、RecyclerView及Glide
  • 三、具体实现
    • 1、需求确认
    • 2、引入依赖
    • 3、UI布局
    • 4、网页解析
    • 5、功能实现
    • 6、总结

一、前言

有时候浏览网站图片感觉不是很方便,不是广告太多就是要一个个翻页。我们都知道用Python做数据的爬取挺方便的,所以我想Java有没有类似的方法可以获取网页图片数据然后在Android端上显示。
答案肯定是有的,所以我就搞出来了,老规矩先看看效果:

图片来源:摄图网照片

应用主界面 >

查看图片详情 >

二、框架介绍

1、Jsoup简介

Jsoup 是Java的一个HTML解析工具,可直接解析某个URL地址、HTML文本内容,功能如下:

(1)从一个URL,文件或字符串中解析HTML

(2)使用DOM或CSS选择器来查找、取出数据使用DOM或CSS选择器来查找、取出数据

(3)可操作HTML元素、属性、文本可操作HTML元素、属性、文本

主要类:Jsoup类提供了连接,清理和解析HTML文档的方法;Document 获取HTML文档;Element 获取、操作HTML节点。详情见官网

2、EventBus简介

EventBus是由greenrobot组织开发的一个Android事件发布/订阅轻量级框架,通过解耦发布者和订阅者简化Android事件传递。EventBus可以代替Android传统的Intent、Handler、Broadcast或接口函数,在Fragment、Activity、Service线程之间传递数据以及执行方法。详情见源码

3、RecyclerView及Glide

RecyclerView就不用多说了,主要用于数据的列表展示。
Glide 是一款强大的Android图片加载和缓存库,可高效地加载网络图片、本地图片、资源ID图片等格式的图片文件,代码简洁好用。详情见郭霖大神博客

三、具体实现

1、需求确认

以摄图网照片网址为例:https://699pic.com/photo/
可以看到其首页有各个分类的照片,点击某一项可看到其详情图片页

图片详情页包含了图片主题、图片数量等内容
eeeee… 这小龙虾把我都看饿了 T-T

总额言之!我们只需要实现首页的分类预览以及详情展示即可,其他信息可根据个人需求获取。。

2、引入依赖

确定好开发所需的框架后,在项目中的app / build.gradle下导入依赖:
导入Jsoup、EventBus、Glide以及SpinKit一个动画加载库,用于网络请求时显示动画效果

implementation 'org.jsoup:jsoup:1.13.1'
implementation 'org.greenrobot:eventbus:3.2.0'
implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation 'com.github.ybq:Android-SpinKit:1.4.0'

3、UI布局

项目的需求比较简单,首页分类图片的显示,在主布局文件中使用RecyclerView做首页图片预览即可。
activity_main.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><!--自定义标题栏--><RelativeLayoutandroid:id="@+id/tool_bar"android:background="@color/blue"android:layout_width="match_parent"android:layout_height="50dp"><TextViewandroid:id="@+id/tag_name"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:textColor="@color/white"android:text="HappyLook"/></RelativeLayout><!--加载动画--><com.github.ybq.android.spinkit.SpinKitViewandroid:id="@+id/load_view"android:layout_width="80dp"android:layout_height="80dp"android:layout_centerInParent="true"style="@style/SpinKitView.CubeGrid"/><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/main_recycler"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/tool_bar"android:padding="8dp" />
</RelativeLayout>

然后是一个点击查看图片详情的界面,包含了返回按钮、图片名称(数量)
sec_layout.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!--自定义标题栏--><RelativeLayoutandroid:id="@+id/pic_bar"android:background="@color/blue"android:layout_width="match_parent"android:layout_height="50dp"><!--返回按钮--><ImageViewandroid:id="@+id/btn_back"android:layout_width="35dp"android:layout_height="35dp"android:layout_centerVertical="true"android:layout_marginStart="10dp"android:src="@mipmap/ic_back"/><!--图片分类--><TextViewandroid:id="@+id/pic_name"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:textColor="@color/white"android:text="火锅烧烤"/></RelativeLayout><androidx.recyclerview.widget.RecyclerViewandroid:layout_centerHorizontal="true"android:layout_below="@id/pic_bar"android:id="@+id/pic_recycler_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:padding="8dp"/><com.github.ybq.android.spinkit.SpinKitViewandroid:id="@+id/pic_load_view"android:layout_width="70dp"android:layout_height="70dp"android:layout_centerInParent="true"style="@style/SpinKitView.Circle"android:visibility="gone"/>
</RelativeLayout>

4、网页解析

解析网页获取元素,就是通过网页特有的标签属性对所需元素进行定位。这是关键的一步,使用浏览器开发者模式定位获取所需的元素,我用的是谷歌浏览器按F12就能进入,其他浏览器应该也差不多。图片分类首页进入开发者模式后就点击左上角Element一栏,开始元素定位:

1、div class=“img-show” 整个网页显示分类图片的预览的地方
2、div class=“pl-list” 每一项的图片分类
3、href=" " 该类图片的详情链接地址
4、data-original=" " 预览封面的图片地址
5、alt=" " 图片分类主题

然后点击进入到图片详情页获取元素
1、li class=“list” 每张图片项
2、 img src=" " data-original=" " 图片的地址(两个获取哪个都可以)

最后获取该类图片的页数
"div pager-linkPage" 图片页数列表
"a href=" " 页数链接

以上就是我们需要获取的所有元素。

5、功能实现

这里我介绍几个主要的类和方法,其他比较常用的东西就不多说了。项目Demo地址我会在文章末尾给大家放出来,如果有感兴趣的朋友可以去看一看。

根据网页解析所得到的元素,我们先建立一个bean文件夹并在里面新建一个Pictures类,包括图片详情链接、预览图链接以及分类名称三个变量。Pictures.java如下:

/*** Created by qzh.* Date: 2021/4/19*/
public class Pictures {private String picUrl; //图片详情链接private String preViewImg; //预览图链接private String picName; //分类名称public String getPicUrl() {return picUrl;}public void setPicUrl(String picUrl) {this.picUrl = picUrl;}public String getPreViewImg() {return preViewImg;}public void setPreViewImg(String preViewImg) {this.preViewImg = preViewImg;}public String getPicName() {return picName;}public void setPicName(String picName) {this.picName = picName;}
}

然后新建一个Tools.java工具类,用于解析网页获取数据、发送事件等操作。
sendMeaasge() 封装消息发送方法,使用EventBus来发送传递数据给主线程,一个带数据,一个不带数据。

  /*** EventBus发送消息* @param what 事件标签*/public static void sendMessage(int what){Message message = new Message();message.what = what;EventBus.getDefault().post(message);}/*** EventBus发送消息* @param what 事件标签* @param obj 数据对象*/public static void sendMessage(int what , Object obj){Message message = new Message();message.what = what;message.obj = obj;EventBus.getDefault().post(message);}

InitData() 函数主要通过Jsoup来对网址链接进行解析 在子线程中进行,connect连接网址、timeout设置请求超时限制,使用get方法获取Docment实例,大家可以打印里面的数据看看,出来的是body的文本类型。
然后根据解析类型来执行不同的方法:getMainData() 获取首页数据,getPicData() 获取照片详情数据。

/*** 初始化网页数据* @param mUrl 解析链接* @param type 解析类型:0是首页,1是图片详情页*/public static void initData( String mUrl , int type){new Thread(() -> {try {Document document = Jsoup.connect(mUrl).timeout(5000).get();if (0 == type){if (list != null){list.clear();}getMainData(document);}else if (1 == type){if (mList != null){mList.clear();}getPicData(document);}}catch (Exception e){e.printStackTrace();sendMessage(1008613);}}).start();}

getMainData() 获取首页数据:
根据我们上面所定位的标签获取相应元素,每一个elements对象对应这一个类型的照片,根据其数量生成对应的Pictures实例,并添加到列表中,最后使用自定义的sendMessage() 向主线程发送事件和数据。

    /*** 定位首页元素,获取分类预览封面、标题、链接* 生成 Pictures 实例* @param document Jsoup文档类解析网页body*/private static void getMainData(Document document ){Elements elements = document.select("div.pl-list");for (Element element : elements){String preImg = element.select("img").attr("data-original");String name = element.select("img").attr("alt");String url = element.select("a").attr("href");Pictures pictures = new Pictures();pictures.setPreViewImg(preImg);pictures.setPicName(name);pictures.setPicUrl(url);list.add(pictures);}sendMessage(10086, list);}

getPicData() 获取图片详情数据:
使用getPicSrc() 方法获取每张图片的链接,getPageLink() 方法获取翻页并返回翻页链接数量,之后循环获取每页中的具体照片链接,最后使用sendMessage() 向主线程发送消息和数据

/*** 获取所有照片数据* 若当前类图片存在翻页,则循环获取其他页数照片数据* @param document Jsoup文档类解析网页body*/private static void getPicData(Document document) {mList = getPicSrc(document);List<String> linkList = getPageLink(document);if (linkList.size() != 0 ){for (int i = 0 ; i < linkList.size() ; i++){try {Document doc = Jsoup.connect(linkList.get(i)).timeout(5000).get();mList.addAll(getPicSrc(doc));}catch (Exception e){e.printStackTrace();sendMessage(1008613);}}}Log.d(TAG, "照片数量: "+ mList.size());sendMessage(1008611 , mList);}

接下来就是实现MainActivity里的方法了:
onCreate() 方法里调用initView() 声明控件,并调用Tools.initData() 获取网页数据,要注意的是在使用EventBus之前需要对订阅者(当前上下文)进行注册,在活动销毁的时候取消注册。

 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();Tools.initData(Tools.photoUrl,0);}@Overrideprotected void onStart() {super.onStart();if (!EventBus.getDefault().isRegistered(this)){ EventBus.getDefault().register(this); //注册当前上下文}}@SuppressLint("WrongViewCast")public void initView(){recyclerView = findViewById(R.id.main_recycler);tagName = findViewById(R.id.tag_name);loadView = findViewById(R.id.load_view);GridLayoutManager layoutManager = new GridLayoutManager(this,2);recyclerView.setLayoutManager(layoutManager);adapter = new MainAdapter(this ,this);}@Overrideprotected void onDestroy() {super.onDestroy();EventBus.getDefault().unregister(this); //活动销毁注销}

在应用加载完首页分类的图片后,需要点击进入到图片详情页面中,这时候需要在适配器中写一个监听接口,然后再MainActivity中实现:(这里适配器贴个接口代码,具体实现可参考Demo)

MainAdapter.java

/*** Created by qzh.* Date: 2021/4/17*/
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder>  {private final ItemClickListener mListener;public interface ItemClickListener{void clickListener(View v ,String categoryName/*图片分类名称*/, String moreUrl/*该类图片链接*/);}}

MainActivity.java 中实现接口,获取类名以及链接,再次调用Tools.initData() 获取图片详情页,最后结果通过sendMessage() 返回

   @Overridepublic void clickListener(View v, String categoryName, String moreUrl) {loadView.setVisibility(View.VISIBLE);recyclerView.setVisibility(View.INVISIBLE);picName = categoryName;Tools.initData(moreUrl , 1);}

然后是消息接收处理,使用EventBus发送过来的消息在MainActivty中的处理如下:
将该处理函数声明为主线程接收模式 @Subscribe(threadMode = ThreadMode.MAIN) 这样就会接收来自Tools里的信息,然后根据msg.what执行相应的操作:

10086: 获取首页图片数据,这里需要把msg.obj对象转化一下变成 Pictures 的列表对象 然后更新到适配器中显示出来。

1008611: 获取图片详情页数据,将图片类型名称以及数据列表传到 SecActivity中显示出来。

后面两个方法就是对UI进行简单的控制

    @Subscribe(threadMode = ThreadMode.MAIN)public void handleMessage(@NonNull Message msg) {switch (msg.what){case 10086:loadView.setVisibility(View.INVISIBLE);adapter.setList((List<Pictures>)msg.obj);recyclerView.setAdapter(adapter);break;case 1008611:loadView.setVisibility(View.INVISIBLE);ArrayList<String> mList = (ArrayList<String>)msg.obj;Intent intent = new Intent(MainActivity.this,SecActivity.class);intent.putExtra("picName",picName);intent.putStringArrayListExtra("picUrl", mList);startActivity(intent);break;case 1008612:recyclerView.setVisibility(View.VISIBLE);break;case 1008613:Toast.makeText(this, "出现错误!!", Toast.LENGTH_SHORT).show();break;}}

点击某个分类图片执行1008611下的方法,启动SecActivity 显示图片详情。
SecActivity.java 如下:
获取图片类型名称、图片数据以及图片数量,最后显示出来

  @Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.sec_layout);picName = getIntent().getStringExtra("picName");mList = getIntent().getStringArrayListExtra("picUrl");initView();}private void initView() {picRecyclerView = findViewById(R.id.pic_recycler_view);btn_Back = findViewById(R.id.btn_back);pic_Name = findViewById(R.id.pic_name);picLoadView = findViewById(R.id.pic_load_view);btn_Back.setOnClickListener(view -> {Tools.sendMessage(1008612);finish();});String title = picName +" ("+mList.size()+"p) ";pic_Name.setText(title);adapter = new SecAdapter(SecActivity.this , mList);manager = new LinearLayoutManager(this);picRecyclerView.setLayoutManager(manager);picRecyclerView.setAdapter(adapter);}@Overridepublic void onBackPressed() {Tools.sendMessage(1008612);super.onBackPressed();}

6、总结

总的来说项目实现起来不难,功能比较简单,主要是使用Jsoup作为网页解析获取数据,EventBus作为通信工具在不同线程中传递信息和数据,再用RecyclerView 和Glide显示出来。后面有时间的话就继续添加完善功能,比如 网址选择,图片下载等,感兴趣的朋友可以尝试搞一下。
最后附上 Demo下载地址《《《

ok,打完收工~

Android 使用Jsoup解析网页批量获取图片相关推荐

  1. jsoup html转义处理,jsoup解析网页出现转义符问题

    https://www.oschina.net/question/996055_136438 *************************************** 我要解析这个网页  htt ...

  2. Jsoup解析网页html

    Jsoup解析网页html 解析网页demo: 利用Jsoup获取截图中的数据信息: html代码片段: 1 <!-- 当前基金档案\计算\定投\开户 start --> 2 <di ...

  3. asp自动解析网页中的图片地址,并将其保存到本地服务器

    程序实现功能:自动将远程页面的文件中的图片下载到本地. 程序代码 <% '将本文保存为 save2local.asp '测试:save2local.asp?url=http://ent.sina ...

  4. html页面添加优酷视频,通过jsoup解析页面html获取优酷页面视频列表

    通过jsoup解析页面html获取优酷页面视频列表 作者: javaboy2012 Email:yanek@163.com qq:    1046011462 代码如下: package com.ya ...

  5. 网页批量下载图片-怎么一键快速下载网页图片的工具

    网页批量下载图片,今天给大家分享一款免费图片批量下载软件,支持任意格式的图片批量下载,只需要输入关键词或批量导入网页链接即可批量下载图片.每个人都可以拥有各种高清图源.支持批量图片压缩/放大/添加水印 ...

  6. 通过jsoup解析页面html获取优酷页面视频列表

    通过jsoup解析页面html获取优酷页面视频列表 作者: javaboy2012 Email:yanek@163.com qq:    1046011462 代码如下: package com.ya ...

  7. Android基础进阶 - 调用拍照、获取图片

    本篇给大家带来的是拍照回传的初级使用,用的同样是数据回传的方式,首先 startActivityForResult 确定 Action.requestCode,之后重写 onActivityResul ...

  8. Android利用Jsoup解析html 开发网站客户端小记。

    这些天业余时间比较多,闲来无事,想起了以前看过开发任意网站客户端的一篇文章,就是利用jsoup解析网站网页,通过标签获取想要的内容.好了废话不多说,用到的工具为 jsoup-1.7.2.jar包,具体 ...

  9. Android:加载网图时精确获取图片格式

    一.开始挖坑 项目中有一个点击查看大图的需求,并且在大图模式下支持手势缩放,所以,我们必然会用到 chrisbanes 大神的 PhotoView,主要使用的是其中的PhotoView 和 Photo ...

最新文章

  1. 关于I2C协议和SPI协议学习之中的补充修改
  2. [转帖]2015年时微软Win3.1崩溃迫使巴黎奥利机场短暂关闭
  3. maven项目调试debug错误Source not found.
  4. 金山安全报告:二月漏洞频出 网站挂马猖獗
  5. RN性能优化以及事件监听
  6. android中常用正则表达式
  7. 镁光ssd管理工具 linux,镁光C400固态硬盘08TH固件及升级软件
  8. 当不知轴承型号时如何寻找轴承故障频率_知课堂 | 快速计算轴承特征频率
  9. Android 双屏显示分析
  10. 大业达公司裁员风云2
  11. 移动机器人c语言程序设计,机器人辅助C程序设计
  12. Hashtable的深拷贝
  13. 5GNR中PDCCH的polar编码
  14. GOF23设计模式之桥接模式
  15. window电脑访问Android照片,解决JPEG照片在windows无法打开
  16. 用户输入自己的【姓名 年龄 爱好】 + 加CP【姓名 年龄 爱好】,点击按钮,页面显示该用户的信息 点击提交按钮,JSON显示用户信息+副本信息(副本初始值是{})
  17. aop实现原理 - JDK动态代理(实例+源码解析)
  18. 15 | 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?
  19. java向上转型_Java向上转型
  20. 锚杆拉拔试验弹性模量计算_锚杆抗拔试验相关规范的若干问题探讨

热门文章

  1. IntentService总结
  2. Django+vue-echarts可视化显示
  3. Excel for Mac 快捷键
  4. PDF转换为word,java
  5. 迈动互联“三位一体”智慧医院系统建设不断创新
  6. C++实现带头结点单链表
  7. [游戏AI]实现掩蔽行为的策略
  8. 机关工勤计算机考试成绩查询,河南省机关事业单位工勤技能岗位考试成绩查询...
  9. python可以做web_Python3.0版本做web可以吗?
  10. Java实现简单推优投票程序