艺赛旗 RPA8.0全新首发免费下载 点击下载
http://www.i-search.com.cn/index.html?from=line1

在进行月末客户清账的流程设计时,其中一个步骤是导出电子表格或者网页并从中筛选数据。

页面如下:
艺赛旗(RPA)【SAP】四种方式筛选特别总帐标志既含A又含空的科目-编程之家

另外,如果是网页格式的文件,用浏览器打开可能是这样的(后缀名为mhtml):
艺赛旗(RPA)【SAP】四种方式筛选特别总帐标志既含A又含空的科目-编程之家

也可能是这样的(后缀名为htm):
艺赛旗(RPA)【SAP】四种方式筛选特别总帐标志既含A又含空的科目-编程之家

对于红框中的每一个单元格,我们需要判断其中的值,如果红框(上一个黄色行与下一个黄色行中间的那些行)中既有A又有空单元格(比如第一个红框中最后一项是空单元格,前面都是A),那么我们就取箭头指向的科目,如果红框中全是A或者全是空则排除那个科目(比如第二个红框中全是A,就排除箭头所指的科目)

思路
首先读取“凭证编号”这一列中的空值,获取所有黄色行所在的索引。然后依次遍历黄色行中间的每一块白色行,将“特别总帐标志”中的每一个值放入集合中,对于每一块白色行都判断一下集合的长度,如果为2则说明那个科目是我们需要的。

方法一(针对导出的是xlsx格式)
import pandas as pd

def parse_excel(path):
df = pd.read_excel(path)
index = df[df[df.columns[3]].isnull()].index[:-1].tolist()
subjects = []
try:
set_index = set()
for x in range(index[0]):
set_index.add(str(df[df.columns[6]].ix[x]))
if len(set_index) == 2:
subjects.append(df[df.columns[0]].ix[index[0] + 1][-8:]) # 这里的-8是因为科目一共为8位数,前面的科目两个字我们不需要

    for j in range(1, len(index)//2):set_index = set()for x in range(index[j*2-1] + 1, index[j*2]):set_index.add(str(df[df.columns[6]].ix[x]))if len(set_index) == 2:subjects.append(df[df.columns[0]].ix[index[j*2] + 1][-8:])
except:pass
return subjects

方法二(针对导出的是第一种mhtml格式)
import pandas as pd

def parse_html1(path):
df = pd.read_html(path, header=0)[0]
index = df[df[‘凭证编号’].isnull()].index[:-1].tolist()
subjects = []
try:
set_index = set()
for x in range(index[0]):
set_index.add(str(df[‘特别总帐标志’].ix[x]))
if len(set_index) == 2:
subjects.append(df[‘已清项目/未清项目符号’].ix[index[0] + 1][-8:])

    for j in range(1, len(index)//2):set_index = set()for x in range(index[j*2-1] + 1, index[j*2]):set_index.add(str(df['特别总帐标志'].ix[x]))if len(set_index) == 2:subjects.append(df['已清项目/未清项目符号'].ix[index[j*2] + 1][-8:])
except:pass
return subjects

方法三(针对导出的是第二种htm格式)
前面两种都使用了pandas这个第三方库,但是对于第二种有很多个表的网页格式,pandas就无能为力了,我们只能换一种思路,通过直接获取其html源码并将其转换为树结构,这里我们使用BeautifulSoup这个库

from bs4 import BeautifulSoup

def parse_html2(path):
with open(path, ‘r’, encoding = ‘utf-8’) as html:
soup = BeautifulSoup(html, ‘lxml’)
tables = soup.find_all(‘table’)
tem_list = []
for table in tables[:-1]:
tbodys = table.find_all(‘tbody’)
tem_set = set([])
for tr in tbodys[1].find_all(‘tr’):
string = tr.find_all(‘td’)[6].string
tem_set.add(string)
if len(tem_set) == 2:
subject = tbodys[3].find(‘tr’).find_all(‘td’)[0].find_all(‘font’)[2].string[3:11]
tem_list.append(subject)
return tem_list
方法四(针对导出的是第一种mhtml格式)
from bs4 import BeautifulSoup

def parse_html3(path):
with open(path, ‘r’, encoding = ‘utf-8’) as html:
soup = BeautifulSoup(html, ‘lxml’)
trs = soup.find_all(‘tr’)[1:-1]
index = []
subjects = []
for i in range(len(trs)):
td = trs[i].find_all(‘td’)[3].string
if td is None:
index.append(i)
# print(index)
set_index = set()
try:
for x in range(index[0]):
set_index.add(trs[x].find_all(‘td’)[6].string)
if len(set_index) == 2:
subjects.append(trs[index[0] + 1].find_all(‘td’)[0].string[-8:])

        for j in range(1, len(index)//2):set_index = set()for x in range(index[j*2-1] + 1, index[j*2]):set_index.add(trs[x].find_all('td')[6].string)if len(set_index) == 2:subjects.append(trs[index[j*2] + 1].find_all('td')[0].string[-8:])except:pass
return subjects

处理网页时BeautifulSoup和pandas速度对比(方法二和方法四)
import time
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np

path = r’C:\Users\lenovo\Documents\SAP\SAP GUI\4152 70.MHTML’ # 总共八千多行数据

def parse_html3(path): # 方法四
time_start = time.time()
with open(path, ‘r’, encoding = ‘utf-8’) as html:
soup = BeautifulSoup(html, ‘lxml’)
trs = soup.find_all(‘tr’)[1:-1]
index = []
subjects = []
for i in range(len(trs)):
td = trs[i].find_all(‘td’)[3].string
if td is None:
index.append(i)
# print(index)
set_index = set()
try:
for x in range(index[0]):
set_index.add(trs[x].find_all(‘td’)[6].string)
if len(set_index) == 2:
subjects.append(trs[index[0] + 1].find_all(‘td’)[0].string[-8:])

        for j in range(1, len(index)//2):set_index = set()for x in range(index[j*2-1] + 1, index[j*2]):set_index.add(trs[x].find_all('td')[6].string)if len(set_index) == 2:subjects.append(trs[index[j*2] + 1].find_all('td')[0].string[-8:])except:pass
time_end = time.time()
print('BeautifulSoup用时{}秒'.format(time_end - time_start))
return subjects

def parse_html1(path): # 方法二
time_start = time.time()
df = pd.read_html(path, header=0)[0]
index = df[df[‘凭证编号’].isnull()].index[:-1].tolist()
subjects = []
try:
set_index = set()
for x in range(index[0]):
set_index.add(str(df[‘特别总帐标志’].ix[x]))
if len(set_index) == 2:
subjects.append(df[‘已清项目/未清项目符号’].ix[index[0] + 1][-8:])

    for j in range(1, len(index)//2):set_index = set()for x in range(index[j*2-1] + 1, index[j*2]):set_index.add(str(df['特别总帐标志'].ix[x]))if len(set_index) == 2:subjects.append(df['已清项目/未清项目符号'].ix[index[j*2] + 1][-8:])
except:pass
time_end = time.time()
print('pandas用时{}秒'.format(time_end - time_start))
return subjects

parse_html3(path)
parse_html1(path)
运行结果如下:
艺赛旗(RPA)【SAP】四种方式筛选特别总帐标志既含A又含空的科目-编程之家

经过测试发现pandas慢的主要原因是pd.read_html()这个函数花了太多时间,因此对于html格式的数据尽量还是使用BeautifulSoup来处理。