前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次 excel vba 参考手册爬虫实战,不必要的一次爬虫。

记一次 excel vba 参考手册爬虫实战,不必要的一次爬虫。

作者头像
forxtz
发布2020-10-10 17:06:12
2.2K0
发布2020-10-10 17:06:12
举报
文章被收录于专栏:源懒由码源懒由码

目的:基于办公与互联网隔离,自带的office软件没有带本地帮助工具,因此在写vba程序时比较不方便(后来发现07有自带,心中吐血,瞎折腾些什么)。所以想到通过爬虫在官方摘录下来作为参考。

目标网站:https://docs.microsoft.com/zh-cn/office/vba/api/overview/

所使工具:

python3.7,requests、selenium库

前端方面:使用了jquery、jstree(用于方便的制作无限层级菜单:https://blog.csdn.net/jason_renyu/article/details/79168940)

设计思路:

1、分析目标页面,可分出两部分,左边时导航,右边是内容显示。

2、通过selenium对导航条进行深度遍历,取得导航条所有节点以及对应的链接,并以jstree的数据格式存储。

代码语言:javascript
复制
# 导航层级为
<ul>
   <li>
       <a>...
       <span>....

3、使用requests遍历所有链接取得相应主体页面。

实现:

代码语言:javascript
复制
#
#  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
代码语言:javascript
复制

# 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得到相应的文件名

代码语言:javascript
复制
#
#   根据网页地址,得到文件名,并创建相应文件夹
#
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得到主体信息储存。

代码语言:javascript
复制
# 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页面框架,相对隔离。

代码语言:javascript
复制
<!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"事件来进行跳转。

代码语言:javascript
复制
<!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" />
    <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].kk = url
                    }
                }else{

                }
            })

            $("#s").submit(function (e) {
                e.preventDefault();
                $("#container").jstree(true).search($("#q").val());
            });
        </script>
    </div>
</body>

</html>

以上,得到最后的本地版网页excel vba参考工具。最后,部分office自带本地版的vba参考工具,有点白干一场。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档