基于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计数排序和基数排序算法实例
Apr 25 Python
Python获取Windows或Linux主机名称通用函数分享
Nov 22 Python
Python基于smtplib实现异步发送邮件服务
May 28 Python
Swift 3.0在集合类数据结构上的一些新变化总结
Jul 11 Python
python使用openpyxl操作excel的方法步骤
May 28 Python
OpenCV 使用imread()函数读取图片的六种正确姿势
Jul 09 Python
Python实现快速大文件比较代码解析
Sep 04 Python
Python爬取微信小程序通用方法代码实例详解
Sep 29 Python
Python实现AES加密,解密的两种方法
Oct 03 Python
详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案
Jan 29 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
Mar 03 Python
pytorch model.cuda()花费时间很长的解决
Jun 01 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 discuz 主题表和回帖表的设计
2009/03/13 PHP
javascript两段代码,两个小技巧
2010/02/04 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
浅析javascript的间隔调用和延时调用
2014/11/12 Javascript
常用的jQuery前端技巧收集
2014/12/24 Javascript
jquery实现简单的banner轮播效果【实例】
2016/03/30 Javascript
js基于cookie记录来宾姓名的方法
2016/07/19 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
2016/08/24 Javascript
关于验证码在IE中不刷新的快速解决方法
2016/09/23 Javascript
微信公众平台开发教程(六)获取个性二维码的实例
2016/12/02 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
详解Angular4 路由设置相关
2017/08/26 Javascript
微信小程序返回多级页面的实现方法
2017/10/27 Javascript
vue中实现在外部调用methods的方法(推荐)
2018/02/08 Javascript
nodejs简单访问及操作mysql数据库的方法示例
2018/03/15 NodeJs
vue地区选择组件教程详解
2018/05/04 Javascript
vue slot与传参实例代码讲解
2019/04/28 Javascript
JS解惑之Object中的key是有序的么
2019/05/06 Javascript
Node.js API详解之 zlib模块用法分析
2020/05/19 Javascript
利用js实现简易红绿灯
2020/10/15 Javascript
javascript实现左右缓动动画函数
2020/11/25 Javascript
[02:43]2014DOTA2国际邀请赛 官方Alliance战队纪录片
2014/07/14 DOTA
使用Python对Excel进行读写操作
2017/03/30 Python
python+pyqt实现右下角弹出框
2017/10/26 Python
python3 实现一行输入,空格隔开的示例
2018/11/14 Python
Python实现去除列表中重复元素的方法总结【7种方法】
2019/02/16 Python
简单了解python的内存管理机制
2019/07/08 Python
如何使用python传入不确定个数参数
2020/02/18 Python
Keras实现DenseNet结构操作
2020/07/06 Python
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
什么是lambda函数
2013/09/17 面试题
编辑找工作求职信分享
2014/01/03 职场文书
会计专业个人自我鉴定
2014/03/21 职场文书
管理工程专业求职信
2014/08/10 职场文书
python如何在word中存储本地图片
2021/04/07 Python
教你怎么用python selenium实现自动化测试
2021/05/27 Python