基于python requests selenium爬取excel vba过程解析
目的:基于办公与互联网隔离,自带的office软件没有带本地帮助工具,因此在写vba程序时比较不方便(后来发现07有自带,心中吐血,瞎折腾些什么)。所以想到通过爬虫在官方摘录下来作为参考。
目标网站:https://docs.microsoft.com/zh-cn/office/vba/api/overview/
所使工具:
python3.7,requests、selenium库
前端方面:使用了jquery、jstree(用于方便的制作无限层级菜单
设计思路:
1、分析目标页面,可分出两部分,左边时导航,右边是内容显示。
2、通过selenium对导航条进行深度遍历,取得导航条所有节点以及对应的链接,并以jstree的数据格式存储。
#导航层级为
-
...
....
3、使用requests遍历所有链接取得相应主体页面。
实现:
# #parent上级节点 #wait_text上级节点对应的xpath路径的文本项 #level,limit仅方便测试使用 # defGetMenuDick_jstree(parent,level,wait_text,limit=2): iflevel>=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') foriinchilds: k={} ifi.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()#最后收起来 exceptExceptionase: print('errormessage:',str(e),'errorparent:',parent.text,'new_wati_text:',new_wati_text,'num:',str(num)) lerror.append(parent.text) finally: returnl
#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) #WritingJSONdata withopen(r'templete\data.json','w',encoding='utf-8')asf: json.dump(data,f)
进行到这里,已经拥有了excelvba下所有的菜单信息以及对应的url。下来需要得到页面主体。
实现思路:
1、遍历所有url
2、通过url得到相应的文件名
# #根据网页地址,得到文件名,并创建相应文件夹 # defcreate_file(url): t='https://docs.microsoft.com/zh-cn/office/' #替换掉字眼,然后根据路径生成相应文件夹 url=url.replace(t,"",1) lname=url.split('/') #先判断有没有第一个文件夹 path=lname[0] ifnotos.path.isdir(path): os.mkdir(path) forlinlname[1:-1]: path=path+'\\'+str(l) ifnotos.path.isdir(path): os.mkdir(path) iflen(lname)>1: path=path+'\\'+lname[-1]+'.html' returnpath
3、访问url得到主体信息储存。
#requests模式 #循环遍历,如果错误,记录下来,以后再执行 had_lhref=[] error_lhref=[] num=1 forurlinlhref: 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') withopen(path,'w',encoding='utf-8')asf: f.write(content) exceptExceptionase: print('errormessage:',str(e),'errorurl:',url) error_lhref.append(url) ifnum%10==0: print('done:',str(num)+'/'+str(len(lhref)),'errornum:'+str(len(error_lhref))) #time.sleep(1)#睡眠一下,防止被反 num=num+1
现在,菜单信息与内容都有了,需要构建自己的主页,这里使用了jstree;2个html,index.html,menu.html。
index.html:使用frame页面框架,相对隔离。
参考文档 menu.html:
1、引入了data.json,这样在可以进行离线调用,使用ajax.get读取json的话,会提示跨域失败;
2、jstree会禁止跳转事件,所有需要通过监听"change.tree"事件来进行跳转。
Title Search