一個處理批量資料python指令碼的分享

語言: CN / TW / HK

一、前言

由於在滲透測試和企業安全自查過程中,經常會涉及到批量資料處理,之前有寫過python指令碼處理,但是需要每次調整程式碼對應不同的情況,於是經過不斷改進,直接編寫了一版具備較強健壯性的python指令碼,再次遇到批量資料處理,直接執行python指令碼,選擇引數即可,不需要手動除錯程式碼。

指令碼包含功能: json資料轉excel檔案,自定義正則表示式提取批量資料,兩個excel檔案進行資料匹配,批量資料的編碼解碼 等。

二、環境準備

import re
import openpyxl
from openpyxl import Workbook
import base64
from urllib import parse
import pypinyin

執行指令碼提示缺少模組,使用命令‘pip install 模組名’  或 ‘pip3 install 模組名’即可。

三、功能實現

功能分類

1 json2excel() #從一串josn{}{}中獲取到想要的結果,可匹配任意數量的變數,並寫入指定的excel檔案中
2 re2excel() #從文字中使用正則表示式篩選出資訊到excel檔案中,正則表示式需自定義
3 excel2_pipei() #匹配兩個excel,以key為匹配引數從excel2中檢索資訊填寫在excel1的某一列中
4 encode_decode() #對單條資料或多條資料進行編碼解碼處理,包含base64,url,unicode,拼音處理

3.1 json2excel()

從一串josn{}{}中獲取到想要的結果,可匹配任意數量的變數,並寫入指定的excel檔案中。

使用場景:

通常用於批量資料處理分析、暴力破解快速獲得使用者名稱使用。

示例json資料:

{"rows":[{"Id":3170,"UserName":"test1","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183},{"Id":3172,"UserName":"user2","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183},{"Id":3173,"UserName":"user3","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183},{"Id":3174,"UserName":"user4","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183},{"Id":3175,"UserName":"user5","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183},{"Id":3185,"UserName":"user6","CreateDate":"2021-11-12 14:34","RoleName":"測試","RoleId":183}]}

使用方法1-全部提取:

處理結果:

使用方法2-部分提取:

當json資料中一條資料引數過多,而你只想提取某個引數時,使用該方法

處理結果:

3.2 re2excel()

從文字中使用正則表示式篩選出資訊到excel檔案中,正則表示式需自定義。

使用場景:

對於非json資料,如需批量獲得具有類似資料的值,可使用該方法處理,需具備一定正則表示式的知識。

示例處理資料:

<li>
            <a href="https://www.cnblogs.com/test1">機器學習<span class="tag-count">(72)</span></a>
        </li>
        <li>
            <a href="https://www.cnblogs.com/test2">人工智慧<span class="tag-count">(64)</span></a>
        </li>
        <li>
            <a href="https://www.cnblogs.com/test3">前端<span class="tag-count">(21)</span></a>
        </li>

使用方法:

由於在cmd下直接輸入正則表示式容易誤輸入中文字元,建議現在notepad++上嘗試是否能匹配到。

處理結果:

3.3 excel2_pipei()

匹配兩個excel,以key為匹配引數從excel2中檢索資訊填寫在excel1的某一列中。

使用場景:

excel1儲存了id、username,excel2儲存了id、password,可使用該方法將兩個excel的資料進行匹配,獲得比較全的資料,在企業自測口令安全中使用較多。

示例資料:

excel1

id username
1001 張三
1002 李四
1003 王五

excel2

id password
1001 123456
1003 111111

使用方法:

處理結果:

3.4 encode_decode()

對單條資料或多條資料進行編碼解碼處理,包含base64,url,unicode,拼音處理

使用場景:

處於內網環境,無法線上使用編碼解碼工具,根據姓名輸出可能的密碼字典

使用方法1-base64編碼解碼處理:

使用方法2-url編碼解碼處理:

使用方法3-Unicode編碼解碼處理:

使用方法4-拼音全拼簡拼處理:

使用方法5-迴圈輸入單條資料:

使用方法6-從文字中讀取批量資料處理:

3.5 整體使用

使用方法:命令臺下執行‘python tool_tool.py’ or 'python3 tool_tool.py'

四、原始碼

由於本人為非專業的開發人員,程式碼實現上可能會較為繁瑣,僅為實現相關功能。

程式碼上已實現輸入引數的校驗及迴圈輸入,輸出檔案儲存錯誤提示,程式碼小白也可以正常使用,具備較好的友好性。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:goat time:2021/11/15


'''
基礎函式
1       text2list()             #從text中讀取資料並返回一個list
2       list2text()             #把list轉化為text,可指定間隔符
3       listll2excel()          #把list[][]按行寫入excel
4       excel2listll()          #把excel轉換為list[][]
5       base64_url()            #base64/url編碼解碼
6       pinyin_list2str()       #把字串進行base64/url等編碼解碼處理
7       encode_decode_io()      #迴圈監聽輸入的處理方式,直到輸入正確
'''

import re
import openpyxl
from openpyxl import Workbook
import base64
from urllib import parse
import pypinyin

'''
從text中讀取資料並返回一個list
'''


def text2list(text_path):
    l = []
    with open(text_path, encoding='utf-8') as f:
        text = f.read()
        for l1 in re.split(r'[\s\n,;]+', text):  # 以文字中空格,回車,逗號,頓號為切割符處理
            l.append(l1)
    return l


'''
把list轉化為text,可指定間隔符
'''


def list2text(l, text_path, tag):
    with open(text_path, 'w', encoding='utf-8') as f:
        for i in l:
            f.write(str(i) + tag)


'''
把二層list[][]按行寫入excel
'''


def listll2excel(ll, excel_path):
    wb = Workbook()
    ws = wb.active
    for x in ll:
        ws.append(x)
    wb.save(excel_path)


'''
把excel轉換為list[][]
'''


def excel2listll(excel_path, sheet_index=0):
    wb = openpyxl.load_workbook(excel_path)
    ws = wb[wb.sheetnames[sheet_index]]
    total_list = []
    for row in ws.rows:  # ws.rows是一個生成器
        row_list = []
        for cell in row:  # 直接從行中取每個cell
            row_list.append(cell.value)
        total_list.append(row_list)
    return total_list


'''
把pinyin處理的多層list提取出來處理為一個字串
'''


def pinyin_list2str(ll, level):
    s = ''
    if level == 0:
        for x in ll:
            s = s + x[0]
    elif level == 1:
        for x in ll:
            s = s + x[0][0]
    else:
        s = '處理錯誤'
    return s


'''
把字串進行base64/url等編碼解碼處理
'''


def base64_url(s, k):
    if k == '00':  # base64編碼
        x = base64.b64encode(s.encode('utf-8')).decode('utf-8')
    elif k == '01':  # base64解碼
        x = base64.b64decode(s.encode('utf-8')).decode('utf-8')
    elif k == '10':  # url編碼
        x = parse.quote(s)
    elif k == '11':  # url解碼
        x = parse.unquote(s)
    elif k == '20':  # unicode編碼
        x = s.encode('unicode_escape').decode('utf-8')
    elif k == '21':  # unicode解碼
        x = s.encode('utf-8').decode('unicode_escape')
    elif k == '30':  # 拼音全拼輸出
        x = pinyin_list2str(pypinyin.pinyin(s, style=pypinyin.NORMAL), 0)
    elif k == '31':  # 拼音首字母輸出
        x = pinyin_list2str(pypinyin.pinyin(s, style=pypinyin.NORMAL), 1)
    else:
        x = '測試處理引數輸入資訊錯誤!'
    return x


'''
迴圈監聽輸入的處理方式,直到輸入正確
'''


def encode_decode_io():
    global k
    print('base64編碼:00,base64解碼:01; url編碼:10,url解碼:11;  unicode編碼:20,unicode解碼:21;拼音全拼輸出:30,拼音首字母輸出:31; 輸入end返回上一級')
    in_k = input("請輸入處理方法>>>")
    if in_k in ['00', '01', '10', '11', '20', '21', '30', '31']:
        k = in_k
    elif in_k == 'end':
        main()
    else:
        print("引數選取錯誤!")
        encode_decode_io()  # 自迴圈等待輸入成功


message = '''
對資料進行批量加工處理,輸入序號選擇

1      json2excel()             #從一串josn{}{}中獲取到想要的結果,可匹配任意數量的變數,並寫入指定的excel檔案中
2      re2excel()               #從文字中使用正則表示式篩選出資訊到excel檔案中,正則表示式需自定義
3      excel2_pipei()           #匹配兩個excel,以key為匹配引數從excel2中檢索資訊填寫在excel1的某一列中
4      encode_decode()          #對單條資料或多條資料進行編碼解碼處理,包含base64,url,unicode,拼音處理
'''

'''
從一串josn{}{}中獲取到想要的結果,可匹配任意數量的變數,並寫入指定excel檔案中
'''


def json2excel():
    path_du = input("請輸入要讀取的json檔案地址,同路徑下直接輸入檔名,或輸入絕對或相對路徑>>>")
    with open(path_du, 'r', encoding='utf-8') as f:  # 讀取
        s = f.read()
    list_xuqiu = []  # 儲存需提取的值
    json_key = re.findall('{.*?\[({.*?})', s, re.S)  # 獲取第一個{}
    list_xuqiu = re.findall('"([a-zA-Z0-9]+)":', json_key[0], re.S)  # 獲取key值
    print("自動識別json資料為:", list_xuqiu)
    auto = input("提取部分引數輸入0,全部提取輸入任意值>>>")
    if auto == '0':
        list_xuqiu = []  # 手動提取時先置空
        while True == True:
            xuqiu = input("請輸入需要匹配的引數,輸入0結束>>>")
            if xuqiu != '0':
                list_xuqiu.append(xuqiu)
            else:
                break
    elif auto == '1':
        pass
    print("提取資料為:", list_xuqiu)
    list_xuqiu_compile = []
    for i in range(len(list_xuqiu)):
        list_xuqiu_compile.append(re.compile(str(list_xuqiu[i] + '\":(.*?)[,}]'), re.S))
    # print(list_xuqiu_compile)#檢視匹配集合是否出問題
    c = re.compile('{.*?}', re.S)  # 定位每個框
    results = re.findall(c, s)
    # print(results)#檢視{}返回結果
    path_xie = input("請輸入需要輸出的excel檔名稱,如1.xlsx>>>")
    ll_result = []  # 獲取到的結果記錄在ll_result中
    ll_result.append(list_xuqiu)  # 把需求引數新增,後續寫在excel的第一行
    for result in results:  # 遍歷每個框
        l_result = []
        for cc in list_xuqiu_compile:  # 遍歷尋找幾個值
            ccc = re.findall(cc, result)
            if ccc:
                l_result.append(re.sub(r'[\"]', '', ccc[0]))  # 去除“”包裹
            else:
                l_result.append('無')
        ll_result.append(l_result)
    # print(ll_result)
    listll2excel(ll_result, path_xie)
    print("寫入完成,請檢視同目錄下檔案")


'''
從文字中使用正則表示式篩選出資訊到excel檔案中,正則表示式需自定義
'''


def re2excel():
    path_du = input("請輸入要讀取的檔案地址,同路徑下直接輸入檔名,或輸入絕對或相對路徑>>>")
    with open(path_du, 'r', encoding='utf-8') as f:  # 讀取
        s = f.read()
    str_re = input("請輸入自定義正則表示式,請注意中英文字元,建議先在notepad++單條查詢嘗試>>>")
    c = re.compile(str_re, re.S)
    results = re.findall(c, s)
    # print(results)#檢視{}返回結果
    path_xie = input("請輸入需要輸出的excel檔名稱,如1.xlsx>>>")
    try:
        listll2excel(results, path_xie)
        print("寫入完成,請檢視同目錄下檔案")
    except:
        print("儲存失敗,請確認同名檔案未被開啟")


'''
匹配兩個excel,以key為匹配引數從excel2中檢索資訊填寫在excel1的某一列中
'''


def excel2_pipei():
    print("---\n比如1.xlsx儲存了'id','name',2.xlsx儲存了'id','passwd',則可以將2.xlsx的passwd資訊寫入1.xlsx的某一列\n---")
    excel_path1 = input("請輸入需寫入資訊的excel檔案地址,同路徑下直接輸入檔名,或輸入絕對或相對路徑>>>")
    l1_key = input("請輸入excel-key所在的列,如第一列輸入1>>>")
    l1_value = input("請輸入excel被寫入的列值,如第二列輸入2>>>")
    l1 = [int(l1_key), int(l1_value)]
    wb = openpyxl.load_workbook(excel_path1)
    ws = wb[wb.sheetnames[0]]
    excel_path2 = input("請輸入需提取資訊的excel檔案地址,同路徑下直接輸入檔名,或輸入絕對或相對路徑>>>")
    l2_key = input("請輸入excel-key所在的列,如第一列輸入1>>>")
    l2_value = input("請輸入需提取的值所在的列,如第二列輸入2>>>")
    l2 = [int(l2_key), int(l2_value)]
    ll = excel2listll(excel_path2)
    dict_index = {}
    for x in ll:
        key_s = str(x[l2[0] - 1]).strip()  # .strip()去除前後空格
        value_s = str(x[l2[1] - 1])
        dict_index[key_s] = value_s
    # print(dict_index.keys())
    for r in range(1, ws.max_row + 1):
        key_ss = str(ws.cell(r, l1[0]).value).strip()
        if key_ss in dict_index.keys():
            ws.cell(r, l1[1]).value = str(dict_index[key_ss])
            # print(key_ss,dict_index[key_ss])
        else:
            pass
            # print(key_ss,"無法匹配")
    try:
        wb.save(excel_path1)
        print("儲存成功,請檢視被寫入excel檔案")
    except:
        print("儲存失敗,請關閉被寫入資訊的excel檔案再操作")
        c = input("請確認關閉檔案後,輸入任意資訊繼續儲存>>>")
        if c:
            print("再次儲存,請檢視是否儲存成功")
            wb.save(excel_path1)


'''
對單條資料或多條資料進行編碼解碼處理,包含base64,url
'''


def encode_decode():
    code_way = input("處理單條資料輸入0,處理批量資料輸入1>>>")
    if code_way == '0':
        while True == True:
            s = input("可迴圈輸入,輸入end結束迴圈,請輸入單條字串資料>>>")
            if s != 'end':
                s2 = base64_url(s, k)
                print("結果為:     ", s2)
            else:
                encode_decode_io()
                encode_decode()
                break
    elif code_way == '1':
        path_du = input("請輸入檔名稱>>>")
        l = text2list(path_du)
        l2 = []
        for s in l:
            x = base64_url(s, k)
            l2.append(x)
        path_xie = input("處理完成,請輸入寫入的檔名稱>>>")
        list2text(l2, path_xie, '\n')
        print("寫入完成,請檢視檔案" + path_xie)
    else:
        print("引數選取錯誤!")
        encode_decode()


'''
定義使用者輸入選擇
'''
k = ''#全域性變數k,定義使用者的編碼處理方式
def IO():
    way = input("請輸入要執行的操作>>>")
    if way == '1':
        json2excel()
    elif way == '2':
        re2excel()
    elif way == '3':
        excel2_pipei()
    elif way == '4':
        k = ''
        encode_decode_io()  # 迴圈等待輸入成功,將正確的in_k賦值給全域性變數K
        encode_decode()
    else:
        print("引數選取錯誤!")
        IO()


def main():
    while True == True:
        print(message)
        IO()
        io = input("處理完成,是否還要再處理資料,輸入任意字元繼續,輸入end結束>>>")
        if io == 'end':
            break


if __name__ == '__main__':
    main()

五、結語

這是本人的第一次工具分享,實現的功能和方法都比較基礎,大佬高抬貴手。文章中部分名詞或描述可能存在錯誤,程式碼實現可能存在部分缺陷,歡迎討論和指出。

編寫該工具的目的,最開始是因為企業自查弱口令,方便從返回包提取使用者名稱進行暴力破解,再對弱口令賬戶關聯身份資訊;暴力破解過程中,部分系統會進行簡單編碼,並可以通過身份資訊構造相應的弱密碼字典,在弱口令自查中有奇效;後面是在風控分析中,可手動關聯多個excel表,手動分析出異常行為使用者(手動的原因當然是目前還沒有風控系統)。