Android 自动抓取网站图标实现分享样式的定制

news/2024/5/20 23:01:30/文章来源:https://blog.csdn.net/dnsliu/article/details/57122535

分享是一个app产生用户数据的重要来源,也是app宣传拉新的重要途径,所以对于稍微成熟一点的app分享是必不可少的模块。相信稍微接触过分享的人都清楚,分享到外部app很简单,只要接入微信、微博、QQ等提供好的sdk并按照规定好的参数正确调用api就好了。这也正是为何这些app能用美观的方式展示分享数据的原因。而普通app则只能处理并没有什么规范可言的系统提供的分享,随便来几个大家感受下……

share contents from 3rd app---> 我正在看【Stone】,分享给你,一起看吧! http://stone.netease.com/stone/download
(这个是来自UC浏览器的分享,算是很正常的也是最常见的一类)share contents from 3rd app---> http://app.ichengzivr.com/video/share-2880-40.html
(这个是来自华为自带浏览器的,只有一个链接地址,不就是没有标题嘛可以接受)share contents from 3rd app---> 我刚在网易新闻看到这个,快来围观:【冷空气影响慢慢结束 接下去一天比一天暖和】https://c.m.163.com/news/a/CE1ARK9K04098FC3.html?spss=newsapp&spsw=1更深度内容,更有趣网友,尽在 网易新闻http://www.163.com/newsapp
(这个是来自网易新闻客户端的,比别人多了一部分广告)share contents from 3rd app---> 想看更多合你口味的内容,马上下载 今日头条http://app.toutiao.com/news_article/?utm_source=link【曾荫权身穿囚衣转至监狱服刑 72岁高龄将在囚房打工】http://t.m.youth.cn/transfer/toutiao/url/picture.youth.cn/qtdb/201702/t20170224_9167724.htm?tt_group_id=6390509684017873154&tt_from=android_share&utm_medium=toutiao_android&utm_campaign=client_share
(瓦册则法克,搬出我的尼克扬标准问号脸,今日头条你都把自家广告放前面了!我服!)

这里写图片描述

各位看官也大致感受到这个充满“恶意”的世界了,拼接规则乱暂且不说想办法还是可以处理的,于是仿照钉钉、易信(安卓版),只是把分享数据当做普通文本消息发送给用户,实现方法很简单大致是,首先是写一个处理分享内容的activity,关键代码如下

private void handleShare() {// Get intent, action and MIME typeIntent intent = getIntent();String action = intent.getAction();String type = intent.getType();if (Intent.ACTION_SEND.equals(action) && type != null) {if ("text/plain".equals(type)) {String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);handleSendText(sharedText); // Handle text being sent} else if (type.startsWith("image/")) {Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); // Handle single image being sent//由于分享图片不是关键,不多说了...}}
}

然后在清单文件注册

<activityandroid:name=".module.share.activity.HandleSystemShareActivity"android:label="@string/share_to_stone"><!--接收单张图片分享--><intent-filter><action android:name="android.intent.action.SEND" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="image/*" /></intent-filter><!--接收普通文本分享--><intent-filter><action android:name="android.intent.action.SEND" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="text/plain" /></intent-filter></activity>

其他具体细节可以参考http://www.cnblogs.com/xyzlmn/p/3444376.html

做出来之后效果大概是这样子

这里写图片描述
跟普通消息没半点差别,领导看了当然不同意,问怎么不做成微信的样子,起码放个图片做下样式能看的出来是个分享消息吧?作为一个合格的程序员(严肃脸),当然不能说自己实现不了,也不可能告诉领导微信人家用户量大有话语权别人都是乖乖接了他们家sdk的。但现实就是并没有哪个应用分享内容过来的时候会带给你一个图片,要自定义样式得有个图片啊,怎么办呢。。。我们机智的产品经理提醒了我,可以用网站的favicon啊,恩,是个可行的方法。

至于什么是favicon

Favicon 收藏夹图标,是其可以让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站。收藏夹图标就是出现在浏览器地址栏左侧的那个小图标。收藏夹图标,也作网站头像。

就是这个东西
favicon

如何获取favicon呢?逆向思维,先研究如何设置的。大致有两种方法:

1.网站根目录下设置favicon.ico文件;
比如http://blog.csdn.net/favicon.ico
2.HTML代码的head标签里面加入代码:

<link href="icon文件url" rel="shortcut icon">		或者    
<link rel="shortcut icon" href="icon文件url">

其中第一种方法是最常用的,第二种则较多的用于特殊页面设置不同的图标。知道如何设置favicon,获取就有办法了。解析html相对复杂又耗时,而且大部分网站都采用第一种方案,所以优先获取网站根目录下的favicon文件,如果没有再解析html的头文件。
思路相对简单,但是实现过程中遇到各种坑,首先来看根据url获取根目录

用正则从分享内容中拆分url和标题

//用于匹配url的正则表达式
private static final String URL_REGULAR = "\\b(([\\w-]+://?|www[.])[^\\s()<>]+(?:\\([\\w\\d]+\\)|([^[:punct:]\\s]|/)))";
Pattern p = Pattern.compile(URL_REGULAR, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(sharedText);
if (m.find()) {String shareUrl = m.group();String shareTitle = sharedText.replaceAll("\\n", "").substring(0, sharedText.indexOf(shareUrl));
}

正则匹配得到分享链接之后拼接根目录地址

URL url = new URL(urlString);
// 保证从域名根路径搜索
String iconUrl = url.getProtocol() + "://" + url.getHost() + "/favicon.ico";

但其实这样得到的很可能不是根目录的地址,原因有两个,一个是有的url有重定向的情况,另外一种情况是由于分享是从移动端发起的很多的网站对wap做了适配,典型的网址类似是http://m.#host#.com,但是wap端的网站不一定会配置有favicon,比如淘宝https://m.taobao.com/favicon.ico返回404而https://www.taobao.com/favicon.ico则是正确的favicon地址。那么先看第一种重定向的情况

private String getFinalUrl(String urlString) {HttpURLConnection connection = null;try {connection = getConnection(urlString);connection.connect();// 处理301/302重定向if (connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM|| connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) {String location = connection.getHeaderField("Location");if (!location.contains("http")) {location = urlString + "/" + location;}LogUtil.i(TAG, "handle redirect before:" + urlString + "\n after: " + location);return location;}} catch (Exception e) {LogUtil.e(TAG, "handle redirect timeout,return origin url:" + urlString);} finally {if (connection != null)connection.disconnect();}return urlString;
}

然后是处理wap网站根目录不存在favicon的情况

 /*** 处理某些网站专门针对wap适配的手机版例如淘宝https://m.taobao.com/#index* http://dynamic.m.tuniu.com/** @param urlString* @return*/
private String handleWapUrl(String urlString) throws MalformedURLException {if (!TextUtils.isEmpty(urlString) && urlString.contains("://m.")) {return urlString.replaceFirst("://m.", "://www.");}if (!TextUtils.isEmpty(urlString) && urlString.contains(".m.")) {URL url = new URL(urlString);return url.getProtocol() + "://www." + urlString.substring(urlString.indexOf(".m."));}return urlString;
}

当然处理wap网站根目录不存在favicon这种情况要放在正常处理之后,总的来说就是这样的

public String getIconUrlString(String urlString) throws MalformedURLException {urlString = getFinalUrl(urlString);URL url = new URL(urlString);String iconUrl = url.getProtocol() + "://" + url.getHost() + "/favicon.ico";if (hasFavicon(iconUrl)) {return iconUrl;} else {//大部分网站做了移动端访问的适配,但wap类型的网址不一定有faviconString iconUrlNew = handleWapUrl(iconUrl);LogUtil.i(TAG, "handle wap url,before: " + iconUrl + "\n after: " + iconUrlNew);if (!TextUtils.equals(iconUrl, iconUrlNew) && hasFavicon(iconUrlNew)) {return iconUrlNew;}}return getIconUrlByRegex(urlString);
}

判断根目录是否存在favicon的方法可以采用返回码是200且contentLength>0的方法

return HttpURLConnection.HTTP_OK == connection.getResponseCode() && connection.getContentLength() > 0;

那么到此为止从网站根目录下面取favicon的方案算是讲完了,正常的网站都是可以取到的,当然也还是存在一些奇葩的网站,比如大优酷http://www.youku.com/favicon.ico根本就不是favicon地址,浏览器右键审查源文件可以看到

<head><meta charset="utf-8"><meta name="title" content="优酷-中国领先视频网站,提供视频播放,视频发布,视频搜索 - 优酷视频" />...<link rel="Shortcut Icon" href="//static.youku.com/v1.0.166/index/img/favicon.ico" />...
</head>

没错就是这句

<link rel="Shortcut Icon" href="//static.youku.com/v1.0.166/index/img/favicon.ico" />

那么如何拿到favicon地址呢,首先要获取到head标签里的内容,关键代码如下

HttpURLConnection  connection = getConnection(urlString);
connection.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));String line;
StringBuilder headBuilder = new StringBuilder();
while ((line = reader.readLine()) != null) {if (!line.contains("</head>")) {headBuilder.append(line);} else {break;}
}
return headBuilder.toString();

然后通过正则匹配含有shortcut icon的标签link标签,由于html是不区分大小写的并且rel和href和互换位置所以正则可以这样写

private static final Pattern[] ICON_PATTERNS = new Pattern[]{Pattern.compile("rel=[\"']shortcut icon[\"'][^\r\n>]+?((?<=href=[\"']).+?(?=[\"']))", Pattern.CASE_INSENSITIVE),Pattern.compile("((?<=href=[\"']).+?(?=[\"']))[^\r\n<]+?rel=[\"']shortcut icon[\"']", Pattern.CASE_INSENSITIVE)
};

匹配到favicon的url之后还有最后一个坑,那就是返回的有可能是相对路径,所以还要再做下处理

//如果是完整的链接地址则直接返回
if (iconUrl.contains("http"))return iconUrl;
//判断是否为相对路径或根路径
if (iconUrl.charAt(0) == '/') {URL url = new URL(urlString);//不包含协议的情况if (iconUrl.startsWith("//")) {iconUrl = url.getProtocol() + ":" + iconUrl;} else {iconUrl = url.getProtocol() + "://" + url.getHost() + iconUrl;}
} else {iconUrl = urlString + "/" + iconUrl;
}
return iconUrl;

到这里我们就成功获取到了嵌入在head标签里面的favicon,OK大功告成!

值得一提的是,因为上面两种获取favicon的途径都需要网络请求,有网络请求则意味着用户要等待,所以交互上要友好的做下处理。最后的成果大致如图,与前面的对比还是很强烈的。

带有样式的分享

细心地看官会发现:哎,怎么有的网站favicon模糊有的清晰咧?像上图中搜狐的明显就清晰嘛。这个问题我大致做了下调查,favicon其实是有尺寸规范的,比如window平台各浏览器最常见的尺寸是1616或者3232,而在MacOS/Safari上尺寸则可能是196196,在Google TV上则可能是9696,所以我尝试给HttpUrlConnection设置不同类型的User-Agent,但可气的是并不管用,都有点怀疑是不是各大网站偷懒了,也可能是我没找对办法,还望大前端的各位指点一下。

参考文章

【Android应用中实现系统“分享”接口 】http://blog.csdn.net/lowprofile_coding/article/details/37656255

【网页favicon.ico图标设置 】http://blog.csdn.net/zhizaibide1987/article/details/42001955

【获取网站图标Icon】 http://www.cnblogs.com/luguo3000/p/3767380.html

【Favicon 的尺寸】 https://www.coder-note.com/questions/2268204/favicon-dimensions

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_905309.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员命名必备网站|变量命名

程序员命名必备网站 话不多说&#xff0c;之间上网址 https://unbug.github.io/codelf/点击访问 方便又快捷啊兄弟们

浅谈web网站架构演变过程

前言 我们以 javaweb为例&#xff0c;来搭建一个简单的电商系统&#xff0c;看看这个系统可以如何一步步演变。 该系统具备的功能&#xff1a; 用户模块&#xff1a;用户注册和管理商品模块&#xff1a;商品展示和管理交易模块&#xff1a;创建交易和管理 阶段一、单机构建网站…

网站行为日志信息统计分析

网站行为日志信息统计分析 一、开发环境二、项目思路三、系统实现(一)、原始数据上传hdfs(二)、数据清洗&#xff08;第一遍&#xff09;(三)、数据清洗&#xff08;第二遍&#xff09;(三)、通过hive对数据分析 四、总结五、完整代码&#xff1a;(一)、pom.xml文件(二)、初始数…

Bliface借区块链定义视频网站3.0

超级解霸 能看懂这个词的多数都已当爹了&#xff0c;那是一个没有还没有在线播放的年代&#xff0c;光盘解码器是电脑的标配&#xff0c;后来逐渐有人在BBS上享视频给大家下载&#xff0c;我们暂且定为第一代 土豆 2005年4月15日土豆网正式上线&#xff0c;在线视频网站如雨后…

IE10 如何保护您的电脑免于恶意网站危害

NSS 实验室不久前发表了一份关于浏览器拦截恶意程序的 评估报告 (英文) 。在这个报告中可以看出最安全的浏览器是 Internet Explorer 10 。 IE10 可以拦截 99.1% 的已知恶意程序。日常生活中在网络上进行的社交活动、购物、工作等皆有可能会将您的个人信息透露给其他人。Micro…

2017年9月3日 实现网站的权限管理

现在各个企业管理网站对登录的账号都要进行权限管理&#xff0c;并且相当重要&#xff0c;每个账号登录进去所能看到的东西大不相同&#xff0c;下面是实现该功能的一个的一种方法。 需求&#xff1a; 权限&#xff1a;权限是使用者操作系统中功能模块的能力&#xff0c;如“角…

我的个人网站又恢复了,欢迎登陆

我的个人网站的网址是http://www.myjavaserver.com/~maqujun . 前一段日子停掉了付费的Hosting的个人站点。自己还伤心了好一整子呢。在Javaeye的Blog里还郑重其事的写了一篇哀悼我那个人网站的悼文。可今天又恢复了&#xff01;可见多变不仅仅是女人的特权&#xff0c;呵呵。其…

网站SEO关键词排名优化经验分享-建站后的推广细节

首先搜索引擎后台会有蜘蛛爬虫技术&#xff0c;根据网站的关百键词密度&#xff0c;内容更新时间上&#xff0c;网站的打开速度&#xff0c;页面跳出率度等因素来进行综合排序。 一般网站做好后&#xff0c;想获取好的收录&#xff0c;可以向搜索引擎提交收录申请&#xff0c;这…

对于网站优化该怎么去做外链?

外链是建网站做优化的重要工作之一&#xff0c;做外链质量的高低直接影响着最终的网站关键词排名&#xff0c;也影响流量和权重。 做外链其实说起来也不是很难&#xff0c;做SEO的基本都知道去哪里做这些网站的外链&#xff0c;但是难就在于这些网站的一个规则和你文章的质量上…

企业网站百度排名第一需要多少外链

网站排名百度第一&#xff0c;到底需要多少外链呢&#xff1f;这是做SEO的同学最大的疑问&#xff0c;这个问题比较宽泛&#xff0c;网站的行业不同&#xff0c;外链的需求也不一样。那么我们要如何审视这个问题呢&#xff1f; 外链计划的制定有以下几个步骤&#xff1a; 一、…

天津网站建设-文率科技天津众多网站建设中的楷模

天津网站建设-文率科技是天津企业建站的首选公司&#xff0c;我们能够为您提供全方位一站式的解决方案&#xff0c;利用我们专业的建站技术&#xff0c;优秀的设计水平&#xff0c;采用目前最先进的送搜索引擎&#xff0c;技术娴熟的人工seo优化&#xff0c;让您的网站拥有高的…

网站为什么要做外链?

SEO工作人员都知道&#xff0c;外链是SEO工作中不可缺少的部分。那么外链是如何对网站的排名起到作用的呢&#xff1f;又为什么如此重要呢&#xff1f; 什么是外链&#xff1f; 从字面意思来看&#xff0c;外链可以拆解成“外部链接”&#xff0c;是指从别的网站链接向自己网站…

网站架构之缓存应用(1)概念篇

网站缓存这个话题并不新颖&#xff0c;但是能否将它用好&#xff0c;可是一门学问&#xff0c;同一件工具在不同人的手中会做出不同的事情来。这里我来分享总结下我对于网站架构中缓存应用的一些看法和经验&#xff0c;大家有好的想法可以补充。 第一&#xff1a;缓存的…

Tomcat5.5.x配置整理 - 发布webapp到网站根目录

1。直接复制到ROOT目录下。 2.因为无法创建无名字的xml文件&#xff0c;并且在xml文件里指定path也是无效的(tomcat靠文件名字来判断的)&#xff0c; 因此必须在server.xml里写下面一段&#xff1a; 查看 复制到剪切板 打印 Xml代码 <ContextdocBase"${catalina.home}/…

仿商业网站——商品评分效果的实现

个人觉得效果还是不错的。废话不多说&#xff0c;先看看HTML的布局&#xff1a; rel"stylesheet" type"text/css" href"gradeStyle.css"/><script src"jquery-1.11.1.js"></script><script src"gradeFunction.…

仿商业网站——商品评分效果实现【提高篇】

看过之前的那一篇仿商业网站——商品评分效果的实现,就可能发现之前的那种实现方式还差一点点效果:就是当鼠标移动到每个星星上的时候,星星最好有动态的变化,如下图: 鼠标移动到星星上面后,星星的状态: 这里用到一点点CSS sprite的技术,

Yahoo——网站性能优化35条黄金守则

Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。 Excetional Performance 团队总结出了一系列可以提高网站速度的方法。可…

IIS 7 Web服务器上部署ASP.NET网站

开发环境Visual Studio 2010/2008皆可&#xff0c;数据库SQL Server 2008/2005。接下来就以这样的环境部署我们的网站&#xff0c;按下图来配置&#xff1a; 第一步&#xff0c;别偷懒&#xff0c;先看看角色添加了没&#xff0c;没有就点击右上边“添加角色”连接添加吧。 第二…

Struts 专业应用: 用 Struts 对象关系桥、Lucene和Velocity 构建网站

Struts 专业应用: 用 Struts 对象关系桥、Lucene和Velocity 构建网站要想建设一个可维护、可扩展的网站&#xff0c;必须在编写每一行代码前花大力气进行设计规划。可是&#xff0c;通过运用framework&#xff0c;大多数困难都是可以克服的。这本书展示了如何利用Jakarta Strut…

中大型网站架构的演变之路

一个成熟的网站架构并不是一开始设计就具备高可用、高伸缩、高性能等特性的&#xff0c;它是随着用户量和业务线不断增加&#xff0c;基础架构才逐渐健壮的。在发展初期&#xff0c;一般都是从0到1&#xff0c;不会一上来就整一些大而全的架构&#xff0c;也很少人这么任性。 说…