目的:基于办公与互联网隔离,自带的office软件没有带本地帮助工具,因此在写vba程序时比较不方便(后来发现07有自带,心中吐血,瞎折腾些什么)。所以想到通过爬虫在官方摘录下来作为参考。
目标网站:https://docs.microsoft.com/zh-cn/office/vba/api/overview/
所使工具:
前端方面:使用了jquery、jstree(用于方便的制作无限层级菜单
设计思路:
1、分析目标页面,可分出两部分,左边时导航,右边是内容显示。
2、通过selenium对导航条进行深度遍历,取得导航条所有节点以及对应的链接,并以jstree的数据格式存储。
1
2
3
4
5
|
# 导航层级为
< ul >
< li >
< a >...
< span >....
|
3、使用requests遍历所有链接取得相应主体页面。
实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#
# parent 上级节点
# wait_text 上级节点对应的xpath路径的文本项
# level,limit 仅方便测试使用
#
def GetMenuDick_jstree(parent,level,wait_text,limit = 2 ):
if level > = limit: return []
parent.click()
l = []
num = 1
new_wati_text = wait_text + '/following-sibling::ul' # 只需要等待ul出来就可以了/li[' + str(ele_num) + ']'
try :
wait.until(EC.presence_of_element_located((By.XPATH,new_wati_text)))
# 查询子节点所有的 a节点和span节点(子菜单)
childs = parent.find_elements_by_xpath( 'following-sibling::ul/li/span | following-sibling::ul/li/a' )
for i in childs:
k = {}
if i.get_attribute( 'role' ) = = None :
k[ 'text' ] = i.text
# 如果是子菜单,进行深度遍历
k[ 'children' ] = GetMenuDick_jstree(i,level + 1 ,new_wati_text + '/li[' + str (num) + ']/span' ,limit)
else :
# 网页访问的Url无Html后缀,需要加上。去除无相关地址,形成相对路径。
url_text = str (i.get_attribute( 'href' )).replace( 'https://docs.microsoft.com/zh-cn/office/' , ' ',1) + ' .html'
k[ 'text' ] = i.text
k[ 'a_attr' ] = { "href" :url_text, "target" : "showframe" }
lhref.append( str (i.get_attribute( 'href' )))
num = num + 1
l.append(k)
parent.click() # 最后收起来
except Exception as e:
print ( 'error message:' , str (e), 'error parent:' ,parent.text, ' new_wati_text:' ,new_wati_text, 'num:' , str (num))
lerror.append(parent.text)
finally :
return l
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# data菜单,lhref为后续需要访问的地址。
# 找到第一个excel节点,从excel开始
data = []
lhref = []
lerror = []
k = {}
browser.get(start_url)
browser.set_page_load_timeout( 10 ) #超时设置
xpath_text = '//li[contains(@class,"tree")]/span[text()="Excel"][1]'
cl = browser.find_element_by_xpath(xpath_text)
k = { 'text' : 'Excel' }
k[ 'children' ] = GetMenuDick_jstree(cl, 1 ,xpath_text, 20 )
data.append(k)
# Writing JSON data
with open (r 'templete\data.json' , 'w' , encoding = 'utf-8' ) as f:
json.dump(data, f)
|
进行到这里,已经拥有了excel vba下所有的菜单信息以及对应的url。下来需要得到页面主体。
实现思路:
1、遍历所有url
2、通过url得到相应的文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#
# 根据网页地址,得到文件名,并创建相应文件夹
#
def create_file(url):
t = 'https://docs.microsoft.com/zh-cn/office/'
# 替换掉字眼,然后根据路径生成相应文件夹
url = url.replace(t,"", 1 )
lname = url.split( '/' )
# 先判断有没有第一个文件夹
path = lname[ 0 ]
if not os.path.isdir(path):
os.mkdir(path)
for l in lname[ 1 : - 1 ]:
path = path + '\\' + str (l)
if not os.path.isdir(path):
os.mkdir(path)
if len (lname) > 1 :
path = path + '\\' + lname[-1] + ' .html'
return path
|
3、访问url得到主体信息储存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# requests模式
# 循环遍历,如果错误,记录下来,以后再执行
had_lhref = []
error_lhref = []
num = 1
for url in lhref:
try :
had_lhref.append(url)
path = create_file(url)
resp = requests.get(url,timeout = 5 ,headers = headers) # 设置访问超时,以及http头
resp.encoding = 'utf-8'
html = etree.HTML(resp.text)
c = html.xpath( '//main[@id="main"]' )
# tostring获取标签所有html内容,是字节类型,要decode为字符串
content = html_head + etree.tostring(c[ 0 ], method = 'html' ).decode( 'utf-8' )
with open (path, 'w' , encoding = 'utf-8' ) as f:
f.write(content)
except Exception as e:
print ( 'error message:' , str (e), 'error url:' ,url)
error_lhref.append(url)
if num % 10 = = 0 :
print ( 'done:' , str (num) + '/' + str ( len (lhref)), 'error num:' + str ( len (error_lhref)))
#time.sleep(1) # 睡眠一下,防止被反
num = num + 1
|
现在,菜单信息与内容都有了,需要构建自己的主页,这里使用了jstree;2个html,index.html,menu.html。
index.html:使用frame页面框架,相对隔离。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<!DOCTYPE html>
< html >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" >
< title >参考文档</ title >
< script src = "js/jquery.min.js" > </ script >
</ head >
< frameset rows = "93%,7%" >
< frameset cols = "20%,80%" frameborder = "yes" framespacing = "1" >
< frame src = "menu.html" name = "menuframe" />
< frame id = "showframe" name = "showframe" />
</ frameset >
< frameset frameborder = "no" framespacing = "1" >
< frame src = "a.html" />
</ frameset >
</ frameset >
</ html >
|
menu.html:
1、引入了data.json,这样在可以进行离线调用,使用ajax.get读取json的话,会提示跨域失败;
2、jstree会禁止<a>跳转事件,所有需要通过监听"change.tree"事件来进行跳转。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< title >Title</ title >
< script src = "js/jquery.min.js" ></ script >
< link rel = "stylesheet" href = "themes/default/style.min.css" rel = "external nofollow" />
< script src = "js/jstree.min.js" ></ script >
< script type = "text/javascript" src = "data.json" ></ script >
</ head >
< body >
< div >
< form id = "s" >
< input type = "search" id = "q" />
< button type = "submit" >Search</ button >
</ form >
< div id = "container" >
</ div >
< div id = "container" ></ div >
< script >
$(function () {
$('#container').jstree({
"plugins": ["search", "changed"],
'core': {
'data': data,
}
});
});
$('#container').on("changed.jstree", function (e, data) {
//console.log(data.changed.selected.length); // newly selected
//console.log(data.changed.deselected); // newly deselected
if (data.changed.selected.length > 0){
// 说明转换了,获取url
var url = data.node.a_attr.href
// console.log(url)
if (url == "#"){
}else{
parent[data.node.a_attr.target].location.href = url
}
}else{
}
})
$("#s").submit(function (e) {
e.preventDefault();
$("#container").jstree(true).search($("#q").val());
});
</ script >
</ div >
</ body >
</ html >
|
以上,得到最后的本地版网页excel vba参考工具。最后,部分office自带本地版的vba参考工具,有点白干一场。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/cycxtz/p/13303306.html