8小时 用kotlin开发一款app

8小时 用kotlin开发一款app

整个项目所花时间:2018年1月1日10:20~2018年1月1日18:27 花了很多时间去爬数据
项目地址: https://github.com/xfhy/DeepNight-in-kotlin

下载试玩:
http://fir.im/lga9

一.项目简介

一款纯看妹子的app,素材全部来源于正经图库(如有侵权,请立马告诉本人,本人邮箱xfhy666@qq.com,我定立刻删除),本app仅做学习交流使用,勿做商用.请注意,全是正经图片,可别想歪了哈.

由于时间非常紧急,于是没有用MVP,RxJava2,Retrofit这些都没用.直接用的anko的common库,很方便就可以异步操作和UI线程切换等,为了节约点时间.

直接上图吧,哈哈,图来得直接些(本来是gif的,结果不能上传那么大的):

说实话,项目中有很多需要优化的地方,但是时间确实有点短,来不及了,很多地方命名不规范,因为我每次想命名需要花很多时间,以前我每一个命名都是仔细思考过的.然后很多地方没有注释,也是来不及了.平时我非常注重注释.

二.用到的知识点

  • kotlin 语言
    • 数据类
    • 伴生对象
    • 单例
    • 扩展
    • 闭包
  • anko
  • jsoup 爬取网页数据的库
  • Material Design 风格
  • Recyclerview 瀑布流
  • CardView
  • Glide 加载图片
  • BaseQuickAdapter 以前自己搞的一个adapter,方便快速开发
  • DrawerLayout
  • NavigationView
  • Toolbar
  • 下拉刷新,上拉加载
  • fragment懒加载

大概就是上面这些了

三.爬取数据

网站非常规律,看看jsoup用法很容易就搞到手啦,下面是详细方法.

首先,我们打开网站,查看网页源代码,可以看到各个分类的网址,待会儿我们可以根据用户选择的分类去爬对应分类的数据.

然后再来看看,每个分类首页(第一页)其实是有一些图片,我们待会儿需要筛选出这些图片的详情页地址,并且这些图片地址我们可以用来展示到app的分类首页上.其实各分类是不止一页的,它们的规律是从第二页末尾就是index_x.shtml结尾,其中x为当前页索引.http://www.msgao.com/dqfl/om/index_2.shtml

我们使用Jsoup开源库去爬取数据,关于Jsoup,其实使用起来非常简单,而且官方还非常人性化的有中文文档,地址.

首先,我们是通过以下方式连接上url

//连接
 val document: Document = Jsoup.connect(buildUrl).get()

然后我们筛选那些有图片链接的

//筛选首页全部的链接   暂时是第一页的
val htmls: Elements = document.select("a[href$=.shtml]")

//筛选是可以点击进去详情的url
htmls.forEachReversedByIndex {
    val realUrl = it.getElementsByClass("div-img")
    //不正确的全部移除
    if (realUrl.size == 0) {
        htmls.remove(it)
    }
}

接着是获取图片地址和图片标题

//外层列表的bean集合
val outLists: ArrayList<DivListImgBean> = ArrayList()
htmls.forEach {

    val divListImgBean = DivListImgBean("", "","")

    val linkElements = it.getElementsByClass("link")
    divListImgBean.detailsUrl = linkElements.attr("href")
    //获取图片地址
    val imgSrcs = it.select("img[src\$=.jpg]")
    imgSrcs.forEach {
        val src = it.attr("src")
        val alt = it.attr("alt")
        divListImgBean.src = src
        divListImgBean.text = alt
    }
    //添加bean到集合中
    outLists.add(divListImgBean)
}

加入用户点击了某个图片链接,我们就去抓取图片详情页,所有的图片链接,进行该美女的详情展示.在方法上和上面的方法大同小异.

看代码吧,比我说的更清楚.结合jsoup 开发文档和网页源码一起看哟

import com.xfhy.deeplibrary.common.LogUtil
import com.xfhy.deepnight.bean.DivListImgBean
import org.jetbrains.anko.collections.forEachReversedByIndex
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements

/**
 * @author xfhy
 * create at 2018/1/1 12:36
 * description:
 */
object NetUtils {

    /**
     * 获取外部的列表页的list
     * @param url url
     * @param index 索引  从1开始
     * @param response 回调数据
     */
    fun reqOutList(url: String, index: Int, response: ZResponse) {
        doAsync {
            try {
                //组装url
                var buildUrl = "${url}index${if (index == 1) "" else "_$index"}.shtml"

                LogUtil.e("buildUrl = $buildUrl")

                //连接
                val document: Document = Jsoup.connect(buildUrl).get()

                //筛选首页全部的链接   暂时是第一页的
                val htmls: Elements = document.select("a[href$=.shtml]")

                //筛选是可以点击进去详情的url
                htmls.forEachReversedByIndex {
                    val realUrl = it.getElementsByClass("div-img")
                    //不正确的全部移除
                    if (realUrl.size == 0) {
                        htmls.remove(it)
                    }
                }

                //外层列表的bean集合
                val outLists: ArrayList<DivListImgBean> = ArrayList()
                htmls.forEach {

                    val divListImgBean = DivListImgBean("", "","")

                    val linkElements = it.getElementsByClass("link")
                    divListImgBean.detailsUrl = linkElements.attr("href")
                    //获取图片地址
                    val imgSrcs = it.select("img[src\$=.jpg]")
                    imgSrcs.forEach {
                        val src = it.attr("src")
                        val alt = it.attr("alt")
                        divListImgBean.src = src
                        divListImgBean.text = alt
                    }
                    //添加bean到集合中
                    outLists.add(divListImgBean)
                }
                LogUtil.e(outLists.toString())
                uiThread {
                    response.onSuccess(outLists)
                }
            } catch (e: Exception) {
                uiThread {
                    response.onError(e.message)
                }
            }
        }
    }

    /**
     * 详情列表
     */
    fun reqDetails(url: String, response: ZResponse) {
        doAsync {
            try {
                //连接
                val document: Document = Jsoup.connect(url).ignoreContentType(true).get()
                val girlPictureList = document.select("div.div-num")
                val imageList: ArrayList<String> = ArrayList()
                girlPictureList.forEach {
                    if (it.hasAttr("data-src")) {
                        var imgUrl = it.attr("data-src")
                        imgUrl = imgUrl.substring(0, imgUrl.indexOf("?"))
                        imageList.add(imgUrl)
                    }
                }
                LogUtil.e(imageList.toString())
                uiThread {
                    response.onSuccess(imageList)
                }
            } catch (e: Exception) {
                uiThread {
                    response.onError(e.message)
                }

            }
        }
    }

}

四.构建UI

我是采用的侧滑风格的app,中间的数据全部采用fragment来填充的,fragment只有在显示后才加载数据(懒加载机制),不会浪费过多流量.

素材取自阿里矢量图标库.阿里妈妈MUX倾力打造的矢量图标管理、交流平台。
设计师将图标上传到Iconfont平台,用户可以自定义下载多种格式的icon,平台也可将图标转换为字体,便于前端工程师自由调整与调用。下载图标完全免费,而且还可以调整颜色和大小,更有SVG下载,简直爽翻天.对于我这种一点儿也不会制作图标的菜鸟级程序员来说,简直就是福利.

五.总结

其实,将一个没有防爬的网站撸成app还是比较简单的,基本上都是这个套路,大家也可以试试.比如内涵段子等,做成app,然后平时可以自己用,还可以给朋友用,还锻炼了自己所学的知识,何乐而不为呢.

kotlin开发起来真的很顺手,也很方便,就像平时说话一样,很顺畅.大家要学习kotlin的话,建议多看看kotlin的官方文档.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值