基于python requests selenium爬取excel vba过程解析


Posted in Python onAugust 12, 2020

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

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

所使工具:

python3.7,requests、selenium库

前端方面:使用了jquery、jstree(用于方便的制作无限层级菜单

设计思路:

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

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

# 导航层级为
<ul>
  <li>
    <a>...
    <span>....

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

实现:

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

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

# 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页面框架,相对隔离。

<!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"事件来进行跳转。

<!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参考工具,有点白干一场。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python k-近邻算法实例分享
Jun 11 Python
20招让你的Python飞起来!
Sep 27 Python
关于Python元祖,列表,字典,集合的比较
Jan 06 Python
Python实现的微信公众号群发图片与文本消息功能实例详解
Jun 30 Python
Python使用getpass库读取密码的示例
Oct 10 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
Nov 09 Python
对pandas的算术运算和数据对齐实例详解
Dec 22 Python
彻底理解Python中的yield关键字
Apr 01 Python
Python3.5装饰器典型案例分析
Apr 30 Python
解决pycharm运行程序出现卡住scanning files to index索引的问题
Jun 27 Python
python 追踪except信息方式
Apr 25 Python
在python里使用await关键字来等另外一个协程的实例
May 04 Python
PyCharm+PyQt5+QtDesigner配置详解
Aug 12 #Python
Python自动发送和收取邮件的方法
Aug 12 #Python
Selenium webdriver添加cookie实现过程详解
Aug 12 #Python
Python如何设置指定窗口为前台活动窗口
Aug 12 #Python
Python面向对象实现方法总结
Aug 12 #Python
Python命名空间及作用域原理实例解析
Aug 12 #Python
python将字典内容写入json文件的实例代码
Aug 12 #Python
You might like
用PHP和ACCESS写聊天室(四)
2006/10/09 PHP
phpMyAdmin2.11.6安装配置方法
2008/08/24 PHP
解析PHP中的unset究竟会不会释放内存
2013/07/18 PHP
php广告加载类用法实例
2014/09/23 PHP
PHP基于imap获取邮件实例
2014/11/11 PHP
详解WordPress开发中get_header()获取头部函数的用法
2016/01/08 PHP
利用PHP抓取百度阅读的方法示例
2016/12/18 PHP
详解在YII2框架中使用UEditor编辑器发布文章
2018/11/02 PHP
Yii框架日志操作图文与实例详解
2019/09/09 PHP
浅谈laravel aliases别名的原理
2019/10/24 PHP
通用javascript脚本函数库 方便开发
2009/10/13 Javascript
nullJavascript中创建对象的五种方法实例
2013/05/07 Javascript
javascript 实现 原路返回
2015/01/21 Javascript
javascript中innerText和innerHTML属性用法实例分析
2015/05/13 Javascript
JavaScript对象属性检查、增加、删除、访问操作实例
2015/07/08 Javascript
javascript从定义到执行 你不知道的那些事
2016/01/04 Javascript
javascript每日必学之循环
2016/02/19 Javascript
jQuery实现页面顶部下拉广告
2016/12/30 Javascript
浅谈PDF.js使用心得
2018/06/07 Javascript
bootstrap select2插件用ajax来获取和显示数据的实例
2018/08/09 Javascript
在axios中使用params传参的时候传入数组的方法
2018/09/25 Javascript
深入理解es6块级作用域的使用
2019/03/28 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
[01:04:48]VGJ.S vs TNC Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
python实现简单ftp客户端的方法
2015/06/28 Python
Python学习笔记之集合的概念和简单使用示例
2019/08/22 Python
Python 如何优雅的将数字转化为时间格式的方法
2019/09/26 Python
匈牙利最大的健身制造商和销售商:inSPORTline
2018/10/30 全球购物
制定岗位职责的原则
2013/11/08 职场文书
应届医学毕业生求职信分享
2013/12/02 职场文书
母校寄语大全
2014/04/10 职场文书
秘书英文求职信
2014/04/16 职场文书
材料物理专业求职信
2014/09/01 职场文书
母亲节寄语大全
2015/02/27 职场文书
英语教师求职信范文
2015/03/20 职场文书
如何用 Python 子进程关闭 Excel 自动化中的弹窗
2021/05/07 Python