基于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解释执行原理分析
Aug 22 Python
Python实现控制台输入密码的方法
May 29 Python
详解python的几种标准输出重定向方式
Aug 15 Python
Python中使用多进程来实现并行处理的方法小结
Aug 09 Python
Python OpenCV 直方图的计算与显示的方法示例
Feb 08 Python
Python数据持久化shelve模块用法分析
Jun 29 Python
5款Python程序员高频使用开发工具推荐
Apr 10 Python
Python开发之基于模板匹配的信用卡数字识别功能
Jan 13 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
Mar 10 Python
Ubuntu18.04安装 PyCharm并使用 Anaconda 管理的Python环境
Apr 08 Python
使用Python matplotlib作图时,设置横纵坐标轴数值以百分比(%)显示
May 16 Python
openstack中的rpc远程调用的方法
Jul 09 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
4月1日重磅发布!《星际争霸II》6.0.0版本更新
2020/04/09 星际争霸
DedeCMS dede_channeltype表字段注释
2010/04/07 PHP
PHP加密3DES报错 Call to undefined function: mcrypt_module_open() 如何解决
2016/04/17 PHP
ThinkPHP5.0框架使用build 自动生成模块操作示例
2019/04/11 PHP
JavaScript 获取用户客户端操作系统版本
2009/08/25 Javascript
javascript 设为首页与加入收藏兼容多浏览器代码
2011/01/11 Javascript
jquery操作复选框(checkbox)的12个小技巧总结
2014/02/04 Javascript
javascript实现汉字转拼音代码分享
2015/04/20 Javascript
简单介绍JavaScript的变量和数据类型
2015/06/03 Javascript
Jquery调用iframe父页面中的元素及方法
2016/08/23 Javascript
js实现文本上下来回滚动
2017/02/03 Javascript
js实现下拉框效果(select)
2017/03/28 Javascript
JavaScript实现音乐自动切换和轮播
2017/11/05 Javascript
vue 通过下拉框组件学习vue中的父子通讯
2017/12/19 Javascript
layer弹出层父子页面事件相互调用方法
2018/08/17 Javascript
JS中数据结构与算法---排序算法(Sort Algorithm)实例详解
2019/06/17 Javascript
Vue实现push数组并删除的例子
2019/11/01 Javascript
微信小程序动态添加和删除组件的现实
2020/02/28 Javascript
react 生命周期实例分析
2020/05/18 Javascript
javascript利用canvas实现鼠标拖拽功能
2020/07/23 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
addEventListener()和removeEventListener()追加事件和删除追加事件
2020/12/04 Javascript
python 列表中[ ]中冒号‘:’的作用
2019/04/30 Python
python地震数据可视化详解
2019/06/18 Python
Python PyQt5 Pycharm 环境搭建及配置详解(图文教程)
2019/07/16 Python
Python的Tkinter点击按钮触发事件的例子
2019/07/19 Python
python 函数中的参数类型
2020/02/11 Python
20行Python代码实现一款永久免费PDF编辑工具的实现
2020/08/27 Python
移动HTML5前端框架—MUI的使用
2017/12/18 HTML / CSS
俄罗斯皮肤健康中心:Pharmacosmetica.ru
2020/02/22 全球购物
CK加拿大官网:Calvin Klein加拿大
2020/03/14 全球购物
初三化学教学反思
2014/01/23 职场文书
国庆放假通知怎么写
2015/07/30 职场文书
2016年安全生产先进个人事迹材料
2016/02/29 职场文书
Oracle数据库中通用的函数实例详解
2022/03/25 Oracle
SpringBoot接入钉钉自定义机器人预警通知
2022/07/15 Java/Android