基于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获取当前时间的方法
Jan 14 Python
python3利用Dlib19.7实现人脸68个特征点标定
Feb 26 Python
python numpy和list查询其中某个数的个数及定位方法
Jun 27 Python
Django REST framework 视图和路由详解
Jul 19 Python
vim自动补全插件YouCompleteMe(YCM)安装过程解析
Oct 21 Python
dpn网络的pytorch实现方式
Jan 14 Python
python实现飞机大战游戏(pygame版)
Oct 26 Python
python GUI库图形界面开发之PyQt5浏览器控件QWebEngineView详细使用方法
Feb 26 Python
python实现逢七拍腿小游戏的思路详解
May 26 Python
Python如何设置指定窗口为前台活动窗口
Aug 12 Python
python中类与对象之间的关系详解
Dec 16 Python
python 制作网站筛选工具(附源码)
Jan 21 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之PHP语法学习笔记1
2006/12/17 PHP
php字符串操作针对负值的判断分析
2016/07/28 PHP
可以支持多中格式的JS键盘
2007/05/02 Javascript
js 取时间差去掉周六周日实现代码
2012/12/25 Javascript
JS来动态的修改url实现对url的增删查改
2014/09/05 Javascript
jQuery中nextUntil()方法用法实例
2015/01/07 Javascript
jQuery实现平滑滚动到指定锚点的方法
2015/03/20 Javascript
JS设置cookie、读取cookie、删除cookie
2015/04/17 Javascript
BootStrap 智能表单实战系列(五) 表单依赖插件处理
2016/06/13 Javascript
使用vue.js写一个tab选项卡效果
2017/03/25 Javascript
jquery动态添加带有样式的HTML标签元素方法
2018/02/24 jQuery
Vue组件开发技巧总结
2018/03/04 Javascript
JavaScript动态加载重复绑定问题
2018/04/01 Javascript
关于layui时间回显问题的解决方法
2019/09/24 Javascript
[01:13:18]Secret vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
python类装饰器用法实例
2015/06/04 Python
Python使用正则表达式获取网页中所需要的信息
2018/01/29 Python
用python实现百度翻译的示例代码
2018/03/09 Python
对Python模块导入时全局变量__all__的作用详解
2019/01/11 Python
使用Python做定时任务及时了解互联网动态
2019/05/15 Python
Python 中的 import 机制之实现远程导入模块
2019/10/29 Python
Python reques接口测试框架实现代码
2020/07/28 Python
python collections模块的使用
2020/10/16 Python
python 用pandas实现数据透视表功能
2020/12/21 Python
Ubuntu20.04环境安装tensorflow2的方法步骤
2021/01/29 Python
html5教程实现Photoshop渐变色效果
2013/12/04 HTML / CSS
加拿大女装网上购物:Reitmans
2016/10/20 全球购物
美国球迷装备的第一来源:FOCO
2020/07/03 全球购物
声明struct x1 { . . . }; 和typedef struct { . . . }x2;有什么不同
2012/06/02 面试题
大龄毕业生求职别忘职业规划
2014/03/11 职场文书
优秀党支部书记事迹材料
2014/05/29 职场文书
机械加工与数控专业自荐书
2014/06/04 职场文书
医院节能减排方案
2014/06/13 职场文书
关于成绩下滑的自我检讨书
2014/09/20 职场文书
2015年党员公开承诺书范文
2015/01/22 职场文书
2015年质量月活动总结报告
2015/03/27 职场文书