基于VBA for Excel批量下载图片教程系列(七)——获取网页Title和图片链接
| 分类: EXCEL |
上一篇文章主要介绍了如何使用XMLHTTP对象获取网页源代码,并推荐了一个用于编码转换的函数,特别是后者对于获取正确的网页Title很重要。
【本文主要内容】:利用上文获取的HTML网页源代码,从中获取网页的标题(Title)和图片链接,并将图片链接存储在数组中。
【本文知识点】
-
1、如何利用HTML的标签获取特定元素;
-
2、Instr函数和Mid函数的用法;
-
3、构造函数判别连接中是否包含图片格式的后缀名。
为了讲解方便,我在自己的个人博客建立了一个简单的独立页面,下面的内容将以 A TEST FOR
VBA
这个页面为例。
当获取了HTML文档后,为了后续的处理方便,我通常会根据
和标签将源码分割成两部分。当然,这样的分割其实并不需要,仅仅是为了处理方便或者纯粹是个人习惯。不过在这里,我却是想要如此处理,因为通过这样的一个分割过程,会让我们更加熟悉Instr函数的使用方法。
1 Instr Mid函数
1.1 函数的基本语法
InStr([start, ]string1, string2[, compare]) '返回一字符串在另一字符串中最先出现的位置
Mid(String,start[,Length]) '截取并返回字符串某一起始位置开始的特定长度的字符串
有时还会用到Mid函数的简化版:
Left(String,Length) '截取并返回字符串从左第一个字符开始的特定长度的字符串
Rigth(String,Length) '截取并返回字符串从右第一个字符开始的特定长度的字符串
至于上述函数的具体用法将在下面的例子中给出。
1.2 利用Instr和Mid函数获取Head、body部分
在上文中,我们将获取的HTML代码存放在变量HtmlCode中,所以下面的例子将以HtmlCode为起点。
Public Function Get_HtmlHead(HtmlCode As String, HtmlHead As String)
Dim HtmlHead_Start As Long
Dim HtmlHead_End As Long
HtmlHead_Start = InStr(HtmlCode, "
") 'instr函数,待查询字符串位于前,而查询字符串位于之后
HtmlHead_End = InStr(HtmlCode, "")
HtmlHead = Mid(HtmlCode, HtmlHead_Start, HtmlHead_End - HtmlHead_Start Len(""))
End Function
Public Function Get_HtmlBody(HtmlCode As String, HtmlBody As String)
Dim HtmlBody_Start As Long
Dim HtmlBody_End As Long
HtmlBody_Start = InStr(HtmlCode, "
) HtmlBody_End = InStr(HtmlCode, "")
HtmlBody = Mid(HtmlCode, HtmlBody_Start, HtmlBody_End
-
HtmlBody_Start Len(""))
End Function Sub test()
Dim HTMLAddress As
String,
HtmlCode As String, HtmlHead
As String,
HtmlBody As String HTMLAddress =
"http://5iyk.me/test-for-vba/" Call
Get_Html(HTMLAddress, HtmlCode)
Call Get_HtmlHead(HtmlCode,
HtmlHead) Call
Get_HtmlBody(HtmlCode, HtmlBody) Cells(1,
1) =
HtmlCode Cells(1, 2) = HtmlHead
Cells(1, 3) =
HtmlBody End Sub
2 从HtmlHead中获取网页Title
在基于VBA for
Excel批量下载图片教程系列(六)——获取网页源代码中简单提到了HTML文档的构成,其中就有的说明,这两个标签之间的内容便是HTML网页的名称,用于在浏览器的左上角位置显示。
我们获取网页Title的目的是在根目录下建立以Title为名的文件夹,用于存放该网页中的图片及其他需要的文件。
Public Function Get_HtmlTitle(HtmlHead As String, HtmlTitle As String)
Dim HtmlTitle_Start As Long
Dim HtmlTitle_End As Long
HtmlTitle_Start = InStr(HtmlHead, ")
HtmlTitle_End = InStr(HtmlHead, "")
HtmlTitle = Mid(HtmlHead, HtmlTitle_Start Len("), HtmlTitle_End - HtmlTitle_Start - Len("))
End Function
Sub test()
Dim HTMLAddress As String, HtmlCode As String, HtmlHead As String, HtmlBody As String, HtmlTitle As String
HTMLAddress = "http://5iyk.me/test-for-vba/"
Call Get_Html(HTMLAddress, HtmlCode)
Cells(1, 1) = HtmlCode
Call Get_HtmlHead(HtmlCode, HtmlHead)
Call Get_HtmlBody(HtmlCode, HtmlBody)
Call Get_HtmlTitle(HtmlHead, HtmlTitle)
Cells(1, 1) = HtmlCode
Cells(1, 2) = HtmlHead
Cells(1, 3) = HtmlBody
Cells(1, 4) = HtmlTitle
End Sub
3 从body中获取图片链接
我们在上一节中讲过,HTML文档的Body部分,是在浏览器中被渲染后展现在我们面前的东西,我们看到的文字、图片等内容就是由body部分决定的。因此,我们只需要在body部分中去获取图片的链接即可。
在HTML中,图片元素的形式一般如下:
</</span>p>
'http://oiu7tz5i9.bkt.clouddn.com/161.jpg.jpg' type='image' onclick="window.open();return false;">

……
等等。
但是,不同形式的图片元素的表达式中均有一个相同的地方,即:
src="图片链接"
而我们要获取的,恰恰正是上面一行代码中双引号中的“图片链接”。以 http://5iyk.me/test-for-vba/ 为例,该页面中的图片元素如下:
http://oiu7tz5i9.bkt.clouddn.com/161.jpg"" alt=""pic1"" /></<span class="hljs-keyword">p>""
""http://oiu7tz5i9.bkt.clouddn.com/162.jpg"" alt=""pic2"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/163.jpg"" alt=""pic3"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/164.jpg"" alt=""pic4"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/165.jpg"" alt=""pic5"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/166.jpg"" alt=""pic6"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/167.jpg"" alt=""pic7"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/168.jpg"" alt=""pic8"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/169.jpg"" alt=""pic9"" /></<span class="hljs-keyword">p>
""http://oiu7tz5i9.bkt.clouddn.com/170.jpg"" alt=""pic10"" /></<span class="hljs-keyword">p>
下面,我们就要将真正的图片链接取出并存放在一个数组中。
Public Function Get_PicAddress(HtmlBody As String, PicAddress() As String) '获取图片链接,并将其存储在PicAddress()中
Dim tmpArray() As String '用于临时储存的字符串数组
Dim PicNum As Long '图片链接的数量
Dim i As Long
tmpArray() = Split(HtmlBody) '使用空格符号将HtmlBody打散后存入临时数组tmpArray中
For i = 0 To UBound(tmpArray)
If (InStr(tmpArray(i), "src") = 1) Then
PicNum = PicNum 1
ReDim Preserve PicAddress(1 To PicNum)
PicAddress(PicNum) = Mid(tmpArray(i), 6, Len(tmpArray(i)) - 6)
End If
Next i
End Function
运行结果如下:
http://upload-images.jianshu.io/upload_images/4290551-d89e91ae23af65aa.gif?imageMogr2/auto-orient/stripfor
为了方便,我将上述代码获取的PicAddress()数组的元素给出如下:
http://oiu7tz5i9.bkt.clouddn.com/content/images/2016/12/logo-1-1.png
http://oiu7tz5i9.bkt.clouddn.com/161.jpg
http://oiu7tz5i9.bkt.clouddn.com/162.jpg
http://oiu7tz5i9.bkt.clouddn.com/163.jpg
http://oiu7tz5i9.bkt.clouddn.com/164.jpg
http://oiu7tz5i9.bkt.clouddn.com/165.jpg
http://oiu7tz5i9.bkt.clouddn.com/166.jpg
http://oiu7tz5i9.bkt.clouddn.com/167.jpg
http://oiu7tz5i9.bkt.clouddn.com/168.jpg
http://oiu7tz5i9.bkt.clouddn.com/169.jpg
http://oiu7tz5i9.bkt.clouddn.com/170.jpg
//cdn.bootcss.com/jquery/1.11.3/jquery.min.js">
//cdn.bootcss.com/fitvids/1.1.0/jquery.fitvids.min.js">
"/assets/js/index.js?v=5f7b8f7e71"">
"
由此我们可以看出,PicAddress数组中的元素可以分为以下三种:
-
(1)网站的logo,.png格式;
-
(2)真正的图片链接,16*.jpg,170.jpg;
-
(3)外链的js或者服务器本地的js等。
我们需要获取的图片链接却是(2)中的,而(1)和(3)中的却是需要剔除的。如何剔除这些链接,我的想法是分为两步进行。
4 判断链接是否为图片格式
常见的图片的后缀名为.png、.jpg、.jpeg、.gif等,一般地,我们可以通过链接中是否含有上述的图片格式后缀名来判别链接是否为图片。
下面的函数用于判断某个字符串中是否含有图片格式的后缀名:
Public Function CheckPicFile(tmpString As String) As String '检查字符串中是否含有图片文件的后缀名,如有,则返回该后缀名的函数值
If InStr(tmpString, "jpg") > 0 Then
CheckPicFile = "jpg"
ElseIf InStr(tmpString, "jpeg") > 0 Then
CheckPicFile = "jpeg"
ElseIf InStr(tmpString, "png") > 0 Then
CheckPicFile = "png"
ElseIf InStr(tmpString, "gif") > 0 Then
CheckPicFile = "gif"
End If
End Function
在Get_PicAddress函数中调用CheckPicFile函数(下面仅给出修改后的Get_PicAddress函数):
Public Function Get_PicAddress(HtmlBody As String, PicAddress() As String) '获取图片链接,并将其存储在PicAddress()中
Dim tmpArray() As String '用于临时储存的字符串数组
Dim PicNum As Long '图片链接的数量
Dim i As Long
tmpArray() = Split(HtmlBody) '使用空格符号将HtmlBody打散后存入临时数组tmpArray中
For i = 0 To UBound(tmpArray)
If (InStr(tmpArray(i), "src") = 1) And (CheckPicFile(tmpArray(i)) <> "") Then 'tmpArray(i)包含"src"且包含图片格式后缀名
PicNum = PicNum 1
ReDim Preserve PicAddress(1 To PicNum)
PicAddress(PicNum) = Mid(tmpArray(i), 6, Len(tmpArray(i)) - 6)
End If
Next i
End Function
运行结果如下:
http://upload-images.jianshu.io/upload_images/4290551-006d70218d952eba.gif?imageMogr2/auto-orient/stripfor
下面为目前PicAddress()数组中的元素:
http://oiu7tz5i9.bkt.clouddn.com/content/images/2016/12/logo-1-1.png
http://oiu7tz5i9.bkt.clouddn.com/161.jpg
http://oiu7tz5i9.bkt.clouddn.com/162.jpg
http://oiu7tz5i9.bkt.clouddn.com/163.jpg
http://oiu7tz5i9.bkt.clouddn.com/164.jpg
http://oiu7tz5i9.bkt.clouddn.com/165.jpg
http://oiu7tz5i9.bkt.clouddn.com/166.jpg
http://oiu7tz5i9.bkt.clouddn.com/167.jpg
http://oiu7tz5i9.bkt.clouddn.com/168.jpg
http://oiu7tz5i9.bkt.clouddn.com/169.jpg
http://oiu7tz5i9.bkt.clouddn.com/170.jpg
至此,所有的图片链接均被我们筛选出来存储在数组中,现在的问题是,如果我们不需要网站的logo,有时候我们更不希望将body标签中的广告图片下载下来,该怎么办?
我一点也不想在这里留一个尾巴,但又不得不在此留下这个尾巴,因为要解决这个问题,以及伴随这个问题出现的一系列问题,我将放到这个工具的基本功能完成后再补充,这些问题包括:
-
如何筛选不需要的图片,如网站logo、广告图片等;
-
如何剔除小尺寸图片,如头像,也包括logo,该问题与上一个问题有部分的重叠,但解决的方法可能有所差异,以及自定义下载尺寸最小的图片,即小于该尺寸的图片将不被保留;
-
如何剔除重复下载的图片。
因此,关于获取图片链接的工作到此基本告一段落,接下来的一节便是如何下载图片。
5 总结
虽然本文的主要内容是如何获取网页Title和图片链接,但在讲解这两部分内容的过程中,穿插了几个重要的知识点,需要掌握和熟练运用,如
- Instr和Mid函数的使用;
- 加深对ReDim Preserve的理解和应用,
- 利用instr函数构造新的函数判别字符串中是否含有图片格式的后缀名。
最后,给出本文的材料:https://pan.baidu.com/s/1pL2hykj

加载中…