当前位置:首页>python>Python/财务自动化之发票自动识别与查重

Python/财务自动化之发票自动识别与查重

  • 2026-06-21 23:37:38
Python/财务自动化之发票自动识别与查重

之前有朋友问,能不能做个发票自动提取并制表的自动化工具,因为平时总要手动录发票号、金额、公司名,几十张下来眼睛都花了,还怕重复报销。

今天我用常见的增值税发票做了一个demo,供大家学习参考。

首先,市面上能做信息读取的工具很多,像PaddleOCR、百度OCR、腾讯云OCR等等都是不错的选择。但咱们现在不是提倡用AI模型嘛,所以这篇就用智谱AI的开源OCR模型做演示。

能直接理解发票的版面结构,不用自己训练也能提取关键字段。除了发票以外,它也可以用来识别别的文件,比如合同、行程单之类的。

基于对财务发票的数据安全考虑,我选择了本地部署模型的方式。所以需要先在电脑上装两个东西:Ollama和GLM-OCR模型。Ollama可以去官网下载(地址问AI),装好Ollama之后在命令行里拉取GLM-OCR模型就行(命令也问AI)。

一、环境搭一下

用Trae的朋友可以让它自己配一下环境,小白用这个还是很方便的。环境搭好后,把待处理的发票放到桌面“发票”文件夹里,老规矩,放桌面好找。

二、配几个参数
除了表的名称和放发票的文件夹名称,其他的通常不需要改;
OLLAMA_API_URL = "http://localhost:11434/api/generate" # Ollama API地址(默认本地)MODEL_NAME = "glm-ocr" # 模型名称DESKTOP_PATH = Path.home() / "Desktop"OUTPUT_EXCEL = DESKTOP_PATH / "发票汇总表.xlsx" # 查重表名称INVOICE_FOLDER = DESKTOP_PATH / "发票" # 桌面文件夹名称PDF_DPI = 200                    # PDF转图片清晰度MAX_IMAGE_SIZE = 1600            # 图片长边限制REQUEST_TIMEOUT = 180

三、Excel表头定一下

最终汇总表要显示哪些字段,先定好。

COLUMN_NAMES_MAP = {    'invoice_number''发票号码''is_duplicate''是否重复',    'invoice_date''开票日期''invoice_type''发票类型',    'total_amount''价税合计(元)''tax_amount''税额(元)',    'amount_without_tax''不含税金额(元)''seller_name''销售方名称',    'seller_tax_id''销售方税号''buyer_name''购买方名称',    'buyer_tax_id''购买方税号''recognition_time''识别时间',    'source_file''源文件''page_number''页码'}EXCEL_COLUMNS_ORDER = [    'is_duplicate''invoice_number''invoice_date''invoice_type',    'total_amount''tax_amount''amount_without_tax',    'seller_name''seller_tax_id''buyer_name''buyer_tax_id',    'recognition_time''source_file''page_number']

四、把文件转成AI能读的格式

发票文件可能是PDF也可能是图片,需要统一转成GLM-OCR能看懂的格式。

# ==================== 图片处理 ====================def pdf_to_base64(pdf_path):    images = []    pdf_doc = None    try:        pdf_doc = fitz.open(pdf_path)        for page_num in range(len(pdf_doc)):            page = pdf_doc[page_num]            zoom = PDF_DPI / 72            mat = fitz.Matrix(zoom, zoom)            pix = page.get_pixmap(matrix=mat, alpha=False)            img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)            if max(img.size) > MAX_IMAGE_SIZE:                ratio = MAX_IMAGE_SIZE / max(img.size)                img = img.resize((int(img.width * ratio), int(img.height * ratio)), Image.Resampling.LANCZOS)            buf = io.BytesIO()            img.save(buf, format='JPEG', quality=90, optimize=True)            images.append(base64.b64encode(buf.getvalue()).decode('utf-8'))        return images    except Exception as e:        print(f"  ❌ PDF处理失败: {e}")        return []    finally:        if pdf_doc:            pdf_doc.close()def image_to_base64(image_path):    try:        img = Image.open(image_path)        if img.mode in ('RGBA''LA''P'):            rgb_img = Image.new('RGB', img.size, (255255255))            if img.mode == 'P':                img = img.convert('RGBA')            rgb_img.paste(img, mask=img.split()[-1if img.mode in ('RGBA''LA'else None)            img = rgb_img        if max(img.size) > MAX_IMAGE_SIZE:            ratio = MAX_IMAGE_SIZE / max(img.size)            img = img.resize((int(img.width * ratio), int(img.height * ratio)), Image.Resampling.LANCZOS)        buf = io.BytesIO()        img.save(buf, format='JPEG', quality=90, optimize=True)        return base64.b64encode(buf.getvalue()).decode('utf-8')    except Exception as e:        print(f"  ❌ 图片处理失败: {e}")        return None

五、调用GLM-OCR识别

def call_ocr(image_base64, prompt):    payload = {        "model": MODEL_NAME, "prompt": prompt, "images": [image_base64],        "stream"False,        "options": {"temperature"0"top_p"0.9"num_predict"2048}    }    resp = requests.post(OLLAMA_API_URL, json=payload, timeout=REQUEST_TIMEOUT)    return resp.json().get('response''').strip()

六、提取、解析与校验

先用通用提示词把发票全文提取出来,再用正则挨个匹配。如果某些字段没取到,再用针对性提示词做第二轮补充。

全文提取:

def extract_all_text(image_base64):    prompt = """请识别这张发票中的所有文字,按从上到下、从左到右顺序逐行输出。只输出原文,不要添加任何解释或JSON格式。"""    text = call_ocr(image_base64, prompt)    # 清理一下可能混进来的描述文字    text = re.sub(r'^(以下是|识别结果|文字内容|OCR结果)[::]\s*''', text, flags=re.IGNORECASE)    text = re.sub(r'^```\w*\s*|```$''', text)    return text.strip()

字段解析(核心规则):

发票号码:假设通常为20位数字串;

m = re.search(r'发票号码[::\s]*(\d{20})', text) or re.search(r'(?<!\d)(\d{20})(?!\d)', text)
开票日期:通常为年月日格式
m = re.search(r'开票日期[::\s]*(\d{4}[年/-]\d{1,2}[月/-]\d{1,2}日?)', text)if not m:    m = re.search(r'(\d{4}年\d{1,2}月\d{1,2}日|\d{4}-\d{1,2}-\d{1,2})', text)

然后把识别出来的金额去掉乱码字符,规整成数字;税号取18位纯数字字母串。如果税额和不含税金额搞反了(税额比不含税还大),自动交换;最后用“价税合计=不含税+税额”校验。

七、查重逻辑

用发票号码做唯一标识,和已有记录比对。号码已存在就在重复里标“是”。

def check_duplicate(df, new_records, new_record):    num = new_record.get('invoice_number''')    if not num:        return False    # 先查已有的汇总表    for _, row in df.iterrows():        if str(row.get('invoice_number''')) == num:            return True    # 再查本轮新增的    for rec in new_records:        if rec.get('invoice_number''') == num:            return True    return False
最后把结果保存到Excel中即可。
以下为完整demo代码,仅供学习参考使用;识别的发票、文件等需为已获授权文件。实际使用时,发票格式和查重要求可能不一样,需根据实际情况调整,可以让AI帮忙优化一下。
import osimport jsonimport reimport base64import ioimport timefrom datetime import datetimefrom pathlib import Pathimport requestsimport pandas as pdfrom openpyxl import load_workbookfrom openpyxl.styles import PatternFill, Font, Alignment, Border, Sideimport fitzfrom PIL import Image# ==================== 配置 ====================OLLAMA_API_URL = "http://localhost:11434/api/generate"MODEL_NAME = "glm-ocr"DESKTOP_PATH = Path.home() / "Desktop"OUTPUT_EXCEL = DESKTOP_PATH / "发票汇总表.xlsx"INVOICE_FOLDER = DESKTOP_PATH / "发票"PDF_DPI = 200MAX_IMAGE_SIZE = 1600REQUEST_TIMEOUT = 180# ==================== Excel表头 ====================COLUMN_NAMES_MAP = {    'invoice_number''发票号码''is_duplicate''是否重复',    'invoice_date''开票日期''invoice_type''发票类型',    'total_amount''价税合计(元)''tax_amount''税额(元)',    'amount_without_tax''不含税金额(元)''seller_name''销售方名称',    'seller_tax_id''销售方税号''buyer_name''购买方名称',    'buyer_tax_id''购买方税号''recognition_time''识别时间',    'source_file''源文件''page_number''页码'}EXCEL_COLUMNS_ORDER = [    'is_duplicate''invoice_number''invoice_date''invoice_type',    'total_amount''tax_amount''amount_without_tax',    'seller_name''seller_tax_id''buyer_name''buyer_tax_id',    'recognition_time''source_file''page_number']# ==================== 图片处理 ====================def pdf_to_base64(pdf_path):    images = []    pdf_doc = None    try:        pdf_doc = fitz.open(pdf_path)        for page_num in range(len(pdf_doc)):            page = pdf_doc[page_num]            zoom = PDF_DPI / 72            mat = fitz.Matrix(zoom, zoom)            pix = page.get_pixmap(matrix=mat, alpha=False)            img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)            if max(img.size) > MAX_IMAGE_SIZE:                ratio = MAX_IMAGE_SIZE / max(img.size)                img = img.resize((int(img.width * ratio), int(img.height * ratio)), Image.Resampling.LANCZOS)            buf = io.BytesIO()            img.save(buf, format='JPEG', quality=90, optimize=True)            images.append(base64.b64encode(buf.getvalue()).decode('utf-8'))        return images    except Exception as e:        print(f"  ❌ PDF处理失败: {e}")        return []    finally:        if pdf_doc:            pdf_doc.close()def image_to_base64(image_path):    try:        img = Image.open(image_path)        if img.mode in ('RGBA''LA''P'):            rgb_img = Image.new('RGB', img.size, (255255255))            if img.mode == 'P':                img = img.convert('RGBA')            rgb_img.paste(img, mask=img.split()[-1if img.mode in ('RGBA''LA'else None)            img = rgb_img        if max(img.size) > MAX_IMAGE_SIZE:            ratio = MAX_IMAGE_SIZE / max(img.size)            img = img.resize((int(img.width * ratio), int(img.height * ratio)), Image.Resampling.LANCZOS)        buf = io.BytesIO()        img.save(buf, format='JPEG', quality=90, optimize=True)        return base64.b64encode(buf.getvalue()).decode('utf-8')    except Exception as e:        print(f"  ❌ 图片处理失败: {e}")        return None# ==================== OCR调用 ====================def call_ocr(image_base64, prompt):    payload = {        "model": MODEL_NAME, "prompt": prompt, "images": [image_base64],        "stream"False,        "options": {"temperature"0"top_p"0.9"num_predict"2048}    }    try:        resp = requests.post(OLLAMA_API_URL, json=payload, timeout=REQUEST_TIMEOUT)        resp.raise_for_status()        return resp.json().get('response''').strip()    except:        return ""# ==================== 识别逻辑 ====================def extract_all_text(image_base64):    prompt = """请识别这张发票中的所有文字,按从上到下、从左到右顺序逐行输出。只输出原文,不要添加任何解释或JSON格式。"""    text = call_ocr(image_base64, prompt)    if text:        text = re.sub(r'^(以下是|识别结果|文字内容|OCR结果)[::]\s*''', text, flags=re.IGNORECASE)        text = re.sub(r'^```\w*\s*|```$''', text)        return text.strip()    return ""def parse_fields(text):    """从全文提取字段,关键正则都针对发票结构优化"""    if not text:        return {}    result = {}    # 发票号码(20位)    m = re.search(r'发票号码[::\s]*(\d{20})', text) or re.search(r'(?<!\d)(\d{20})(?!\d)', text)    if m:        result['invoice_number'] = m.group(1)    # 开票日期    m = re.search(r'开票日期[::\s]*(\d{4}[年/-]\d{1,2}[月/-]\d{1,2}日?)', text)    if not m:        m = re.search(r'(\d{4}年\d{1,2}月\d{1,2}日|\d{4}-\d{1,2}-\d{1,2})', text)    if m:        result['invoice_date'] = re.sub(r'[年月]''-', m.group(1)).replace('日''')    # 金额:优先找"价税合计(小写)"    m = re.search(r'价税合计[((]小写[))]\s*[¥¥]\s*(\d+\.?\d{0,2})', text)    if m:        result['total_amount'] = f"{float(m.group(1)):.2f}"    # 提取所有两位小数,按大小分配    all_money = sorted(set(float(x) for x in re.findall(r'(?<!\d)(\d+\.\d{2})(?!\d)', text) if float(x) > 0))    if len(all_money) >= 3:        if 'total_amount' not in result:            result['total_amount'] = f"{all_money[-1]:.2f}"        result['amount_without_tax'] = f"{all_money[-2]:.2f}"        result['tax_amount'] = f"{all_money[0]:.2f}"    elif len(all_money) == 2:        if 'total_amount' not in result:            result['total_amount'] = f"{all_money[-1]:.2f}"        result['tax_amount'] = f"{all_money[0]:.2f}"        result['amount_without_tax'] = f"{all_money[-1] - all_money[0]:.2f}"    # 划分买卖双方区域    if '销售方' in text:        parts = text.split('销售方'1)        buyer_section, seller_section = parts[0], parts[1]    else:        lines = text.split('\n')        mid = len(lines) // 2        buyer_section = '\n'.join(lines[:mid])        seller_section = '\n'.join(lines[mid:])    # 购买方名称:必须在"名称:"之后、税号关键词之前,排除明显噪声    m = re.search(r'名称[::]\s*([^\n]{1,40}?)\s*(?:统一社会信用代码|纳税人识别号|$)', buyer_section)    if m:        name = m.group(1).strip(':: ')        # 排除发票标题类噪声        noise = ['电子发票''普通发票''增值税''发票号码''开票日期''旅客运输服务''货物或应税劳务']        if name and name not in noise and not re.match(r'^[\d\s.,,。::]+$', name):            result['buyer_name'] = name    # 购买方税号    m = re.search(r'(?:纳税人识别号|统一社会信用代码)[//]?\s*[::]\s*([0-9A-Za-z]{18})', buyer_section)    if m:        result['buyer_tax_id'] = m.group(1).upper()    # 销售方名称:在销售方区域找"名称:"    m = re.search(r'名称[::]\s*([^\n]{1,40}?)\s*(?:统一社会信用代码|纳税人识别号|地址|电话|开户行|$)', seller_section)    if m:        name = m.group(1).strip(':: ')        noise = ['电子发票''普通发票''备注''收款人''复核人''开票人']        if name and name not in noise and not re.match(r'^[\d\s.,,。::]+$', name) and len(name) >= 2:            result['seller_name'] = name    # 销售方税号    m = re.search(r'(?:纳税人识别号|统一社会信用代码)[//]?\s*[::]\s*([0-9A-Za-z]{18})', seller_section)    if m:        result['seller_tax_id'] = m.group(1).upper()    else:        # 全局搜索18位码,排除银行账号上下文        buyer_tid = result.get('buyer_tax_id''')        for tid in re.findall(r'(?<!\d)([0-9A-Za-z]{18})(?!\d)', text.upper()):            if tid != buyer_tid:                pos = text.find(tid)                if not any(kw in text[max(0, pos-30):pos] for kw in ['银行''账号''开户']):                    result['seller_tax_id'] = tid                    break    return resultdef targeted_extract(image_base64, field_name):    """精准提取缺失字段"""    prompts = {        'total_amount''请找出"价税合计(小写)"金额。只返回JSON:{"total_amount":"金额"}',        'tax_amount''请找出"合计"行"税额"列,通常最小。只返回JSON:{"tax_amount":"税额"}',        'amount_without_tax''请找出"合计"行"金额"列(不含税)。只返回JSON:{"amount_without_tax":"金额"}',        'buyer_name''请找购买方"名称",个人填"个人"。只返回JSON:{"buyer_name":"名称"}',        'buyer_tax_id''请找购买方税号(18位),个人无则""。只返回JSON:{"buyer_tax_id":"税号"}',        'seller_name''请找销售方公司全名。只返回JSON:{"seller_name":"名称"}',        'seller_tax_id''请找销售方税号(18位)。只返回JSON:{"seller_tax_id":"税号"}',    }    if field_name not in prompts:        return ""    text = call_ocr(image_base64, prompts[field_name])    if not text:        return ""    m = re.search(r'\{[^{}]*\}', text)    if m:        try:            return json.loads(m.group()).get(field_name, '').strip()        except:            pass    return ""def clean_and_validate(data):    """清理和校验数据"""    cleaned = {}    for f in ['invoice_number''invoice_date''total_amount''tax_amount',              'amount_without_tax''seller_name''seller_tax_id''buyer_name''buyer_tax_id']:        v = str(data.get(f, '')).strip()        if not v:            cleaned[f] = ''            continue        if 'amount' in f:            v = re.sub(r'[^\d.]''', v)            if v.count('.') > 1:                v = v.split('.')[0] + '.' + ''.join(v.split('.')[1:])            try:                cleaned[f] = f"{float(v):.2f}" if v else ''            except:                cleaned[f] = ''        elif 'tax_id' in f:            m = re.search(r'([0-9A-Z]{18})', re.sub(r'[^0-9A-Za-z]''', v).upper())            cleaned[f] = m.group(1if m else ''        elif f == 'invoice_number':            m = re.search(r'(\d{20})', re.sub(r'[^\d]''', v))            cleaned[f] = m.group(1if m else ''        else:            cleaned[f] = v    # 金额修复    try:        total = float(cleaned.get('total_amount'0or 0)        without = float(cleaned.get('amount_without_tax'0or 0)        tax = float(cleaned.get('tax_amount'0or 0)        if tax > without > 0:            cleaned['tax_amount'], cleaned['amount_without_tax'] = cleaned['amount_without_tax'], cleaned['tax_amount']            tax, without = without, tax        if total > 0 and without > 0 and tax > 0:            if abs(total - without - tax) > 0.05:                cleaned['amount_without_tax'] = f"{round(total - tax, 2):.2f}"    except:        pass    code = cleaned.get('invoice_number''')    if code:        if code[:2] == '13':            cleaned['invoice_type'] = '电子发票(专用发票)'        else:            cleaned['invoice_type'] = '电子发票(普通发票)'    else:        cleaned['invoice_type'] = ''    return cleaneddef recognize(image_base64):    text = extract_all_text(image_base64)    if not text:        return None    data = parse_fields(text)    required = ['total_amount''amount_without_tax''tax_amount''buyer_name''seller_name''seller_tax_id']    missing = [f for f in required if f not in data or not data[f]]    if missing:        print(f"    补充识别: {'/'.join(missing)}")        for f in missing:            val = targeted_extract(image_base64, f)            if val:                data[f] = val                time.sleep(0.3)    return clean_and_validate(data)# ==================== 查重和保存 ====================def check_duplicate(df, new_records, new_record):    num = new_record.get('invoice_number''')    if not num:        return False    for _, row in df.iterrows():        if str(row.get('invoice_number''')) == num:            return True    for rec in new_records:        if rec.get('invoice_number''') == num:            return True    return Falsedef save_excel(df):    try:        df_display = df[EXCEL_COLUMNS_ORDER].copy()        df_display.columns = [COLUMN_NAMES_MAP[k] for k in EXCEL_COLUMNS_ORDER]        df_display.to_excel(OUTPUT_EXCEL, index=False)        wb = load_workbook(OUTPUT_EXCEL)        ws = wb.active        hf = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")        hfont = Font(color="FFFFFF", bold=True, size=11)        tb = Border(left=Side(style='thin'), right=Side(style='thin'),                     top=Side(style='thin'), bottom=Side(style='thin'))        dfill = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")        for cell in ws[1]:            cell.fill = hf            cell.font = hfont            cell.alignment = Alignment(horizontal="center", vertical="center")            cell.border = tb        for row in range(2, ws.max_row + 1):            is_dup = ws.cell(row=row, column=1).value            for col in range(1, ws.max_column + 1):                cell = ws.cell(row=row, column=col)                cell.border = tb                if is_dup == '是':                    cell.fill = dfill                cell.alignment = Alignment(horizontal="right" if col in (567else "left", vertical="center")        for col_cells in ws.columns:            max_len = 0            for cell in col_cells:                if cell.value:                    max_len = max(max_len, sum(2 if '\u4e00' <= c <= '\u9fff' else 1 for c in str(cell.value)))            ws.column_dimensions[col_cells[0].column_letter].width = min(max_len + 350)        ws.freeze_panes = 'A2'        wb.save(OUTPUT_EXCEL)        return True    except Exception as e:        print(f"❌ 保存失败: {e}")        return False# ==================== 主程序 ====================def main():    print("\n" + "=" * 50)    print("  发票OCR识别系统 v7.5")    print("=" * 50)    if not INVOICE_FOLDER.exists():        INVOICE_FOLDER.mkdir(parents=True)        print(f"\n📁 请将发票文件放入: {INVOICE_FOLDER}")        return    all_files = sorted(set(f for ext in ('*.pdf''*.PDF''*.jpg''*.jpeg''*.png''*.bmp'for f in INVOICE_FOLDER.glob(ext)))    if not all_files:        print(f"\n❌ 文件夹内没有发票文件")        return    print(f"\n📊 找到 {len(all_files)} 个文件")    if OUTPUT_EXCEL.exists():        df_display = pd.read_excel(OUTPUT_EXCEL)        reverse_map = {v: k for k, v in COLUMN_NAMES_MAP.items()}        df = pd.DataFrame()        for col in df_display.columns:            if col in reverse_map:                df[reverse_map[col]] = df_display[col]        print(f"📂 已有 {len(df)} 条记录")    else:        df = pd.DataFrame(columns=list(COLUMN_NAMES_MAP.keys()))    processed = set(df['source_file'].tolist()) if not df.empty else set()    new_records = []    print("\n🔄 开始识别...\n")    for idx, file_path in enumerate(all_files, 1):        print(f"[{idx}/{len(all_files)}{file_path.name}")        if file_path.name in processed:            print("  ⏭️  已处理过\n")            continue        images = pdf_to_base64(file_path) if file_path.suffix.lower() == '.pdf' else [img] if (img := image_to_base64(file_path)) else []        if not images:            print()            continue        for page_num, img_b64 in enumerate(images, 1):            data = recognize(img_b64)            if not data:                print("  ❌ 识别失败\n")                continue            data['source_file'] = file_path.name            data['page_number'] = page_num if file_path.suffix.lower() == '.pdf' else ''            data['recognition_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')            is_dup = check_duplicate(df, new_records, data)            data['is_duplicate'] = '是' if is_dup else '否'            print(f"    价税合计: ¥{data.get('total_amount''0')}")            print(f"    不含税金额: ¥{data.get('amount_without_tax''0')}")            print(f"    税额: ¥{data.get('tax_amount''0')}")            try:                t, w, x = float(data.get('total_amount'0or 0), float(data.get('amount_without_tax'0or 0), float(data.get('tax_amount'0or 0)                if t > 0 and w > 0 and x > 0:                    print(f"    {'✅'ifabs(t-w-x) <= 0.05else'⚠️'} 金额验证: ¥{t} = ¥{w} + ¥{x}")            except:                pass            print(f"    {'⚠️ 重复发票'if is_dup else'✅ 正常'}\n")            new_records.append(data)        processed.add(file_path.name)    if new_records:        new_df = pd.DataFrame(new_records)        df = pd.concat([df, new_df], ignore_index=True)        if save_excel(df):            print("=" * 50)            print(f"✅ 新增 {len(new_records)} 张,总计 {len(df)} 张")            print(f"💾 已保存到桌面: 发票汇总表.xlsx")    else:        print("ℹ️  没有新增发票")if __name__ == "__main__":    main()

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 08:28:46 HTTP/2.0 GET : https://f.mffb.com.cn/a/489810.html
  2. 运行时间 : 0.115746s [ 吞吐率:8.64req/s ] 内存消耗:4,536.48kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2913ee7d32a7d938b04deb40d3bc6a94
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000791s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000840s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000333s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000256s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000564s ]
  6. SELECT * FROM `set` [ RunTime:0.000180s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000611s ]
  8. SELECT * FROM `article` WHERE `id` = 489810 LIMIT 1 [ RunTime:0.000527s ]
  9. UPDATE `article` SET `lasttime` = 1783038527 WHERE `id` = 489810 [ RunTime:0.010032s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000245s ]
  11. SELECT * FROM `article` WHERE `id` < 489810 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000392s ]
  12. SELECT * FROM `article` WHERE `id` > 489810 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000567s ]
  13. SELECT * FROM `article` WHERE `id` < 489810 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.006528s ]
  14. SELECT * FROM `article` WHERE `id` < 489810 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001115s ]
  15. SELECT * FROM `article` WHERE `id` < 489810 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.018205s ]
0.118613s