BeautifulSoup模板简单应用-提取html指定数据(api_name/api_method/api_path,请求body/请求header/pagam参数)
from bs4 import BeautifulSoup import re import os.path import itertools name='newcrm' source_file_path='./'+name+'.html' def get_apiInfo(): with open(source_file_path,encoding='utf-8') as api_file: fileInfo=api_file.read() soup = BeautifulSoup(fileInfo,'lxml') #这里没有装lxml的话,把它去掉用默认的就好 #匹配带有class属性的div标签 divList = soup.find_all('div', attrs={'class': re.compile("api-one")}) # print(len(divList)) apiInfo_list=[]#存放所有的api_list try: for alltag in divList: h3List=alltag.find_all('h3')#在每个div标签下,查找所有的h3标签(包含接口名称) pList = alltag.find_all('p') #在每个div标签下,查找所有的p标签(包含请求url与请求方法) tableList=alltag.find_all("table")#匹配div下所有线程的table标签(取出header字段/body字段) dictInfo={} api_descride_name_list,api_descride_example_list,api_descride_type_list=[],[],[] '''所有的接口描述信息:名称/描述/类型''' query_Param_name_list,query_Param_type_list,query_Param_IsNeed_list=[],[],[] query_Param_describe_list,query_Param_example_list=[],[] '''所有的query参数信息:名称/类型/是否必填/描述,主要用于get请求''' body_Param_name_list,body_Param_type_list,body_Param_IsNeed_list=[],[],[] body_Param_describe_list,body_Param_example_list=[],[] '''所有的body参数信息:名称/类型/是否必填/描述,主要用于post/put/delete请求''' header_Param_name_list,header_Param_type_list,header_Param_IsNeed_list=[],[],[] header_Param_describe_list,header_Param_example_list=[],[] '''所有的header参数信息:名称/类型/是否必填/描述''' # if divList.index(alltag)==len(divList): if not len(pList)<3:#如果请求方式/请求url为空则不执行后面的程序 api_name=h3List[0].string.strip()#匹配h3标签下的接口名称 api_method=pList[1].string.strip()#这里提取请求方式 api_path=pList[2].string.strip() #这里提取url,并去除空格 dictInfo['api_name']=api_name dictInfo['api_method']=api_method dictInfo['api_path']=api_path header_list=[]#存放header值 body_list=[]#存放body值 query_list=[]#存放query值 api_descride_list=[]#存放所有接口描述信息 # print(api_name) # print(api_method) # print(api_path) IsEmpty_str='Null_Str'#处理匹配为空时的字符串占位符 if not tableList in([],None): for table in tableList: table_title=table.tr.th.span.string#匹配table表头 table_thead=table.find_all('thead')#匹配table里的所有thead标签:字段title(描述) table_tbody=table.find_all('tbody')#匹配字段value tbody_temp_list1,tbody_temp_list2=[],[]#临时存放接口描述数据 for tbody in table_tbody: tbody_key_type=tbody.find_all('th')#匹配出字段的类型 tbody_key_field=tbody.find_all('td')#匹配出字段的value for tbody_name in tbody_key_field :#取出所有字段 if not tbody_name.string is None: tbody_key=tbody_name.string.strip() else: tbody_name=IsEmpty_str#处理为空的情况 tbody_key=tbody_name #将能够被5整除的字段放入body中(代表的是header/body) # print(tbody_name) if len(tbody_key_field)%5==0: if table_title in('Query参数名'): '''如果table的名称是Query,则添加到Query列表中''' query_list.append(tbody_key) elif table_title in('Body参数名'): '''如果table的名称是body,则添加到body列表中''' body_list.append(tbody_key) elif table_title in('Header参数名'): '''如果table的名称是header,则添加到header列表中''' header_list.append(tbody_key)#将能够被5整除的字段放入body中(代表的是header/body) elif len(tbody_key_field)%2==0 and table_title ==('参数名'): tbody_temp_list1.append(tbody_key)#剩下的放入参数名信息中,代表的是参数名描述 # print(header_list) # print(body_list) # print(tbody_temp_list1) if not tbody_key_type==[]: for tbody_type in tbody_key_type: if type(tbody_type)!=(str,int):#只处理type为tag的 if not (tbody_type.string is None) : tbody_field=tbody_type.string.strip() tbody_temp_list2.append(tbody_field) else: tbody_type=IsEmpty_str#处理为空的情况 tbody_temp_list2.append(tbody_type) # print(tbody_temp_list2) temp_num=int(len(tbody_temp_list1)/len(tbody_temp_list2)) #计算出两个list的对应关系,这里是2:1, #需要添加tbody_temp_list1key添加两次后在添加tbody_temp_list2的值 for temp_tuple in enumerate(tbody_temp_list2): #将tbody_temp_list1/tbody_temp_list2的元素添加至api_descride_list #'''temp_tuple:是一个元组,第一个参数是index,第二个是value''' for num in range(temp_num): #因为tbody_temp_list1/tbody_temp_list2是多对1, #因为接口描述里的type是单独的th标签里的值, #而其他的值是td标签里面的值,所以需要将两个列表的元素进行合并 api_descride_list.append(tbody_temp_list1[temp_tuple[0]*(temp_num)+num]) else: api_descride_list.append(temp_tuple[1]) # print(header_list) # print(body_list) # print(api_descride_list) # if not header_list in([],None):#处理header列表中字段为空的情况 for n,m in enumerate(header_list): #删除filed(不存在)的相关元素,这个是apizza导出的bug导致的 #因为列表存在多个相同的值,所以不能使用index方法来获取元素下标, #使用enumerate来获取list的值与对应的下标 if m in("是","否") :#根据m的值找到对应的下表n try: if header_list[(n+3)]==IsEmpty_str: #如果n后面的第三个元素不是一个字段,而是事先定义的为空的字符串,则删除索引后面的五个元素 for i in range(5): del header_list[n+3] except IndexError as error: pass for header_data in enumerate(header_list):#将列表中的值分别添加至各个列表 if header_data[0]==0 or header_data[0]%5==0 : header_Param_name_list.append(header_data[1]) elif header_data[0]==1 or header_data[0]%5==1 : header_Param_type_list.append(header_data[1]) elif header_data[0]==2 or header_data[0]%5==2: header_Param_IsNeed_list.append(header_data[1]) elif header_data[0]==3 or header_data[0]%5==3: header_Param_describe_list.append(header_data[1]) elif header_data[0]==4 or header_data[0]%5==4: header_Param_example_list.append(header_data[1]) if not query_list in([],None): for n,m in enumerate(query_list):#处理query列表中字段为空的情况 #因为列表可能存在多个相同的值,所以不能使用index方法来获取元素下标, #使用enumerate来获取list的值与对应的下标 if m in("是","否") :#根据m的值找到对应的下表n try: if query_list[(n+3)]==IsEmpty_str: #如果n后面的第三个元素不是一个字段,而是事先定义的为空的字符串, #则删除索引后面的五个元素 for i in range(5): del query_list[n+3] except IndexError as error: pass for query_data in enumerate(query_list):#将列表中的值分别添加至各个列表 if query_data[0]==0 or query_data[0]%5==0 : query_Param_name_list.append(query_data[1]) elif query_data[0]==1 or query_data[0]%5==1 : query_Param_type_list.append(query_data[1]) elif query_data[0]==2 or query_data[0]%5==2: query_Param_IsNeed_list.append(query_data[1]) elif query_data[0]==3 or query_data[0]%5==3: query_Param_describe_list.append(query_data[1]) elif query_data[0]==4 or query_data[0]%5==4: query_Param_example_list.append(query_data[1]) if not body_list in([],None): for n,m in enumerate(body_list):#处理body列表中字段为空的情况 #因为列表可能存在多个相同的值,所以不能使用index方法来获取元素下标, #使用enumerate来获取list的值与对应的下标 if m in("是","否") :#根据m的值找到对应的下表n try: if body_list[(n+3)]==IsEmpty_str: #如果n后面的第三个元素不是一个字段,而是事先定义的为空的字符串, #则删除索引后面的五个元素 for i in range(5): del body_list[n+3] except IndexError as error: pass for body_data in enumerate(body_list):#将列表中的值分别添加至各个列表 if body_data[0]==0 or body_data[0]%5==0 : body_Param_name_list.append(body_data[1]) elif body_data[0]==1 or body_data[0]%5==1 : body_Param_type_list.append(body_data[1]) elif body_data[0]==2 or body_data[0]%5==2: body_Param_IsNeed_list.append(body_data[1]) elif body_data[0]==3 or body_data[0]%5==3: body_Param_describe_list.append(body_data[1]) elif body_data[0]==4 or body_data[0]%5==4: body_Param_example_list.append(body_data[1]) if not api_descride_list in([],None):#处理header列表中字段为空的情况 for api_descride_data in enumerate(api_descride_list):#将列表中的值分别添加至各个列表 if api_descride_data[0]==0 or api_descride_data[0]%3==0 : api_descride_name_list.append(api_descride_data[1]) elif api_descride_data[0]==1 or api_descride_data[0]%3==1 : api_descride_example_list.append(api_descride_data[1]) elif api_descride_data[0]==2 or api_descride_data[0]%3==2: api_descride_type_list.append(api_descride_data[1]) if not header_list in(None,[]): dictInfo['Header']={} dictInfo['Header']['参数名']=header_Param_name_list dictInfo['Header']['类型']=header_Param_type_list dictInfo['Header']['必需']=header_Param_IsNeed_list dictInfo['Header']['描述']=header_Param_describe_list dictInfo['Header']['示例']=header_Param_example_list if not query_list in(None,[]): dictInfo['Query']={} dictInfo['Query']['参数名']=query_Param_name_list dictInfo['Query']['类型']=query_Param_type_list dictInfo['Query']['必需']=query_Param_IsNeed_list dictInfo['Query']['描述']=query_Param_describe_list dictInfo['Query']['示例']=query_Param_example_list if not body_list in(None,[]): dictInfo['Body']={} dictInfo['Body']['参数名']=body_Param_name_list dictInfo['Body']['类型']=body_Param_type_list dictInfo['Body']['必需']=body_Param_IsNeed_list dictInfo['Body']['描述']=body_Param_describe_list dictInfo['Body']['示例']=body_Param_example_list if not api_descride_list in(None,[]): dictInfo['接口说明']={} dictInfo['接口说明']['参数名']=api_descride_name_list dictInfo['接口说明']['描述']=api_descride_example_list dictInfo['接口说明']['类型']=api_descride_type_list # dictInfo['header_list']=header_list # dictInfo['body_list']=body_list # dictInfo['api_descride_list']=api_descride_list apiInfo_list.append(dictInfo) except Exception as error: # pass raise(error) return apiInfo_list def write_apiInfo_to_file(): source_data=get_apiInfo()#获取数据来源 print(len(source_data)) file_path='./'+name+'-apiInfo.txt' with open(file_path,'w',encoding='utf-8') as file: file.write(str(source_data)) write_apiInfo_to_file()
脑子不够用当然只能脚踏实地的做事情!