解析出一个网页中所有的图片
来源:互联网 发布:javascript iframe src 编辑:程序博客网 时间:2024/06/05 14:44
题目是为了说明我这篇文章要实现的功能
实际上,知识点就是“正则表达式的介绍和使用”。
问题来源
在做项目的时候遇到了一个问题,就是如何从网页中解析所有的图片,注意!!!这里是“所有”。当时我的第一反应是立刻到网上寻找第三方库,但是,找到的最好的第三方库都和我的问题没有关系,最有关系的就是Java中知道的JavaScript脚本引擎ScriptEngine,可是看了半天还是没看懂这个引擎是在干嘛,所有并没有什么卵用。
既然网上没有现成的第三方库,那么就退而求其次,解析图片的没有,解析HTML的工具总会是有的吧,这里到网上随便搜一搜,就出来了一个工具HtmlParser,这个工具可以帮我们解析HTML正文,包括标签对里面的内容,比如balabala,可以解析balabala;也可以解析标签中的属性,比如可以解析img标签中的src属性,这就是一个图片的地址。
说到这里,似乎有了点头绪,总算有一些图片可以被解析出来了,就是提取img标签中的src属性中的地址,我就试着提取了一下,将提取出来的地址做了一下记录。然后用普通的文本编辑器,比如sublime,我把整个网页的源码粘贴到了编辑器中,搜索以.jpg”这五个连续字符,虽然这中方法很不严谨,但是依然可以粗略的观察到,我们所提取出来的图片地址远远少于整个网页中应该有的图片数量。继续在sublime编辑器里面观察,发现有大量的图片地址出现在JavaScript脚本中,因为我之前不熟悉JavaEE方面的开发,咋看之下存在于JavaScript脚本语言中的地址似乎是以JSON格式存放的,一分钟以后我就发现我想多了,那真的是地地道道的JavaScript。。。
前面说到我搜索了Java中的JavaScript脚本引擎的用法,原因就在这里。但是由于时间紧迫,不得不想一个稍微简单一点的办法,在同学的提议下,使用了正则表达式,准确来说是开始学习正则表达式了,这里要感叹一句,正则表达式不愧是一个很强大的工具。
程序的执行过程
//下面是简单的通过代码来进行网络连接,写的不好,欢迎指责,这里不是武汉话说的韵炸子啊,真的是欢迎指责 String url = request.getParameter("url"); HttpURLConnection connection = (HttpURLConnection) new URL(url) .openConnection(); connection.setReadTimeout(5000); connection.setRequestMethod("GET"); connection.setDoInput(true); connection.connect(); //下面是通过包装流来获取整个网页中的内容,一行一行的读取,并且进行一下处理 BufferedReader reader = new BufferedReader(new InputStreamReader( connection.getInputStream())); StringBuffer buffer = new StringBuffer(); String tmp = null; while ((tmp = reader.readLine()) != null) { buffer.append(tmp.replaceAll("\\s", "").trim()); } //这里的result就是整个网页代码,去掉了空格和空白,并且拼成了一个字符串 String result = buffer.toString(); DataOutputStream dataOutputStream = new DataOutputStream(response.getOutputStream()); //将正则表达式编译成一个模板,并且对所需要的字符串进行匹配,得到匹配类matcher Pattern pattern = Pattern .compile( "(https?:)?((\\/\\/)|(\\\\\\/\\\\\\/)){1}[\\w\\.\\/%\\=\\-\\&\\,\\\\]*?(jpg|png|jpeg){1}"); Matcher matcher = pattern.matcher(result); ArrayList<String> list = new ArrayList<String>(); //下面就是每find()一次就可以获取一个子串的开始索引和结束索引,然后用subString方法对子串进行截取,最后保存到一个容器中 while(matcher.find()) { tmp = result.substring(matcher.start(), matcher.end()); tmp = tmp.replaceAll("\\\\\\/", "/"); list.add(tmp); } //下面是多文件传输相关的代码,在这里不是重点 dataOutputStream.writeInt(list.size()); for(int i = 0; i < list.size(); i ++) { dataOutputStream.writeUTF(list.get(i)); dataOutputStream.flush(); } dataOutputStream.close(); reader.close();
三个需要学习的知识点
正则表达式的基本知识
虽然我很想向各位网友们分享我的见解,特别是初学者,但是我这篇文章的目的不是来讲正则表达式中的基本知识的,所以我向各位推荐一个慕课网的视频,这也是我入门正则表达式的视频,虽然使用的语言是PHP,但是换汤不换药,只是写法不同。
http://www.imooc.com/learn/350
Java中正则表达式的相关API
这里先介绍本文中需要使用的API和类
Pattern.compile(String s)
来进行构造,执行这个方法之后获取一个Pattern,进行下一步的操作,本方法中传递的参数就是所需要的正则表达式 Matcher 我翻译的是正则表达式的匹配类,也是通过静态的方法得到,使用方法为pattern.matcher(String s)
,这个方法中的pattern是前一个类通过上述方法得到的pattern,本方法中的s为要匹配的字符串为了避免读者还要去官方网站看英文API麻烦,我这里也列出方法的说明,也是为了给初学者节约时间
正则表达式的构成
我的构成式比较冗长,但是我觉得可以真实的反应出我的思路。 Pattern pattern = Pattern
.compile(
"(https?:)?((\\/\\/)|(\\\\\\/\\\\\\/)){1}[\\w\\.\\/%\\=\\-\\&\\,\\\\]*?(jpg|png|jpeg){1}");
下面我将表达式分成几个部分来说明我的思路
1. 最前面的(https?:)?。这里是URL开头的协议,是http或者是https,而且这两者要么有,要么没有,对应的就是给出的地址是绝对地址还是相对地址。
2. 再就是之后的((\\/\\/)|(\\\\\\/\\\\\\/)){1}
。很好理解,每个地址的http或者是https后面都要跟上//,但是由于“/”是正则表达式中的保留字符,在捕获组中会得到使用,所以,必须要执行转义。而后面为什么还要跟上很难看的(\\\\\\/\\\\\\/)
,这是因为,我发现在百度中搜索资源,得到的图片可能会是下面的一种奇怪的格式。 http:\/\/www.baidu.com\/afdsa\/fdafda.jpg
由于有了上面这种奇葩的格式,才诞生了上面一串奇怪的正则表达式(\\\\\\/\\\\\\/)
。
3. 再就是之后的[\\w\\.\\/%\\=\\-\\&\\,\\\\]*?
,这里面规定了哪些字符是可以在URL中存在的,如果既在URL中允许存在,又是正则表达式中的保留字符,记得一定要进行转义。至于哪些是URL中的保留字符,可以参看知乎中的一个回答https://www.zhihu.com/question/24474922。还有后面的*?
,这就是懒惰匹配,什么意思呢,很容易懂,就是如果你不加这个懒惰匹配,那么正则表达式默认的是贪婪匹配,那么会从整个字符串的第一个http一直匹配到整个字符串的最后一个jpg,这很明显是错的,使用了*?
,那么就会匹配和任何一个http最近的右侧的jpg,这样就可以顺利的取出字串啦。
4. 最后一个(jpg|png|jpeg){1}
,看字面意思也能够猜出来,就是要以jpg或者png或者jpeg结尾即可。
- 解析出一个网页中所有的图片
- Tesseract.js 一个几乎能识别出图片中所有语言的JS库
- 解析某个网页中所有的超链接
- 用pyqt写的一个可以下载网页中所有图片的程序
- 程序算出一个文件夹中所有文件的行数
- php实现读取出一个文件夹中所有的文件
- 用Ruby下载一个网页上的所有图片
- Python抓一个网页上的所有图片
- 快速保存网页中所有图片的方法
- 快速保存网页中所有图片的方法
- 快速保存网页中所有图片的方法
- 快速保存网页中所有图片的方法
- 快速保存网页中所有图片的方法
- 正则表达式获取网页中所有图片的路径
- 一行代码抓取网页中所有的图片
- 一次性提取网页中所有图片的代码
- 快速保存网页中所有图片的方法
- 快速保存网页中所有图片的方法
- 约瑟夫环
- 找链表的中间结点和倒数第k个结点(链表笔试题面试题)
- 刷刷笔试题~(4)编程
- bfs广度优先搜索
- SICP 练习1.7
- 解析出一个网页中所有的图片
- 关于JAVA中使用nbtstat获取地址报错
- PyQt5:将窗口放在屏幕中间(6)
- Retrofit实现App更新
- HDU1195 BFS或者DP
- CSS盒子模型各属性层级及基础知识
- OpenCV Python 直方图
- Ajax XMLHttpRequest对象的三个属性以及open和send方法
- iOS开发之runloop