VBA可以做的事情很多,除了快速处理数据和分析数据外,还可以帮助我们下载小说,通常也就是我们所说的“爬虫”!当然,用python进行爬虫是最方便的,但是有些部分小伙是不懂编程的,只会用excel这些办公软件那么VBA可以帮助到大家。当然python爬取大型数据是非常方便的,小小一部小说还不如VBA用得顺手。
我们一起感受一下效果吧,《水浒传》就这么轻松下载了。
完整的代码如下:
Sub downLoadText() A = False '关闭提示 Dim regText As Object ‘定义一个对象存放正则表达式得到的结果 Dim strText As String ’定义一个字符对象存放存放网页内容 For i = 7070949 To 7071068 ’利用FOR循环得到小说各章的内容 URL = "; & i & ".html" With CreateObject("MSXML2.XMLHTTP") ‘引用网页请求的类 .Open "GET", URL, False .send 'strText = .responseText strText = StrConv(.ResponseBody, vbUnicode) '不用.responseText,因为XMLHTTP默认是utf-8,不能识别gb2312,会发现数据乱码。所以要获取网页二进代码,再进行字符编码。 End With With CreateObject("VBScri;) ’引用正则表达式的类来获取想要的小说文字 .Global = True '查找范围,True表示全部查找,False表示只查找第一个,默认值是False。 .Pattern = "<h1>(.*?)</h1>" ’标题的表达式 Set regText = .Execute(strText) ‘'Execute方法查找表达式的内容并返回一个数组,存放在regText对象。 titleText = regText(0).submatches(0) ’第一个零表示数组第1个值,第二个零表示 获取表达式"<h1>(.*?)</h1>"括号里面的内容,也称第一个item值。 Range("a1048576").End(xlUp).Offset(1, 0) = titleText ‘在空的表格存放内容 .Pattern = " (.*?)<br" ’段落文字的表达式 Set regText = .Execute(strText) FOR Each paragrahText In regText '利用FOR循环获取数组的每个值 Range("a1048576").End(xlUp).Offset(1, 0) = (0) ‘在空的表格存放内容 Next End With Next A = True End Sub
主要用到的三个知识点:
第一,分析网址及网页(这里演示的案例网址是)。
网址:我们可以看到《水浒传》这部小说不连序言共有120章,每一章都一个链接,分别点开网页发现其URL变化的是后面一串数字,第1章是“7070949”,第2章是“7070950”……最后一章是“7071068”,每一章都是加1。用FOR循环就可以轻松得到所有网址。
网页:这个网站的网页较为简单是静态加载方式,在第一章网页点击右键,选择“查看网页源代码”可以看到小说完整的文字。但有些网站的网页是动态加载的方式,看不到完整的内容。看到网页源代码就可以利用正则表达式获取我们想要的内容了。
第二,引用获取网页信息的类,CreateObject("VBScri;) ,常规简单用法,如下:
URL = "目标网址" With CreateObject("MSXML2.XMLHTTP") ‘引用网页请求的类 .Open "GET", URL, False .send strText = .responseText '返回网页内容 ’strText = .ResponseBody '返回网页内容 End With
有一个需要注意的地方,VBA是识别是utf-8编码数据,这个目标网站的编码是GBK,因此如果用responseText返回网页数据,读取会出现乱码,需要采用二进制数据进行返回,即ResponseBody,再用StrConv函数编码。
第三,引用正则表达式的类,With CreateObject("VBScri;) ,常规简单用法,如下:
With CreateObject("VBScri;) ’引用正则表达式的类 .Global = True '查找范围,True表示全部查找,False表示只查找第一个,默认值是False。 .Pattern = "表达内容(item)" ’表达式 Set regTexts = .Execute(strText) ‘'Execute方法查找表达式的内容并返回一个数组,存放在regText对象。 regText = regText(0).submatches(0) ’第一个零表示数组第1个值,第二个零表示 获取表达式括号里面的内容,也称第一个item值。 end with
需要说明的地方,.Execute()返回的是一个数组对象。 小说每章标题表达式.Pattern = "<h1>(.*?)</h1>" ,括号里面表示一个item,如果多个括号,如:"<h1>(.*?)回(.*?)</h1>",则有多个item,用submatches()获取其值。.*?,实心点、星号和问号三个符号组合的表达式是正则表达式较为常用的格式,基本万能。
欢迎大家评论及提意见,提更多VBA相关问题及具体项目要求。