抓取CSV文件指定内容到Excel表格中

该文章描述了一个Python类ParseCsvs2Excel,它读取csv文件中的数据,按照工作表(BK11,P,H,W等)进行组织,并将数据写入Excel工作簿,根据日期和流量、销量更新已有工作表的内容。脚本还包含了颜色选择和格式化单元格的功能。
import pandas as pd  
from openpyxl import load_workbook  
import os
import openpyxl 
from openpyxl.drawing.image import Image
import sys
from openpyxl.styles import Font, Border, Side  
from openpyxl.styles import Alignment  
from openpyxl.styles import PatternFill  
import random 
import glob
import natsort

SHEET_NAMES = ['BK11', 'P', 'H', 'W', 'T', 'HL', 'J', 'Z', 'C', 'R', 'DB', 'LV']
BK_MAP = {'B0B2ZTZZ3F': 'BK11', 'B0C32WC8S2': 'W', 'B0BRPMS42P': 'H', 'B0C8MCJX7M': 'J',
       'B0C32W5HR7': 'HL', 'B0C8MJD479': 'Z', 'B0BJ6W8XGL': 'P', 'B0C32YF1RK': 'T', 'B0CNK95SS7': 'C'}

# 取出文件夹中的csv文件,按数字顺序排序,并给出开始的时间。
# 遍历解析csv文件,得到每个工作表中的关键数值。
# 为了方便Excel表格的数据写入,那就按工作表来存放数值。
# 每个工作表,如BK11中,对每个值,存放:时间,流量(会话次数),销量(已订购商品数量)
class ParseCsvs2Excel():
    def __init__(self, csv_folder='./csv_folder', pattern=True) -> None:
        self._get_input()
        self.csv_folder = csv_folder
        self.bk11_s = []
        self.p_s = []
        self.h_s = []
        self.w_s = []
        self.t_s = []
        self.hl_s = []
        self.j_s = []
        self.z_s = []
        self.c_s = []
        self.r_s = []
        self.db_s = []

        self.pattern = pattern
        self._set_color()
                
        # 获取当前工作目录  
        current_dir = os.getcwd()  

        # 使用glob模块搜索当前目录下的所有.xlsx文件  
        xlsx_files = glob.glob(os.path.join(current_dir, '*.xlsx'))  
        # 打印找到的文件, 一般只有1个,先取1个吧  
        if len(xlsx_files) > 1: 
            print("存在多个xlsx格式的文件, 请小芳芳保留1个, 不然跑不通")
            sys.exit(-1)
        self.xlsx_path = xlsx_files[0]                  
        self.workbook = openpyxl.load_workbook(self.xlsx_path)  

        # 在当前文件夹中创建new_xlsw文件夹,用于存放新生成的xlsw表格数据。
        self.save_xlsw_dir = os.path.join(current_dir, 'new_xlsw')
        os.makedirs(self.save_xlsw_dir, exist_ok=True)
         
        
    def _set_color(self):
        # 定义“红橙黄绿青蓝紫”对应的RGB颜色值  
        colors = {  
            '红': "E60000",  # 暗红色,降低了亮度  
            '橙': "FFA500",  # 橙色保持不变,因为它通常已经比较柔和  
            '黄': "FFFF99",  # 淡黄色,提高了亮度但降低了饱和度  
            '绿': "00B300",  # 深绿色,降低了亮度  
            '青': "00E6E6",  # 淡青色,提高了亮度但降低了饱和度  
            '蓝': "0066FF",  # 深蓝色,降低了亮度  
            '紫': "9966CC",  # 淡紫色,提高了亮度并稍微改变了色调  
        }
        
        # 随机选择一个颜色  
        random_color = random.choice(list(colors.values()))          
        # 创建填充样式  
        self.fill = PatternFill(start_color=random_color, end_color=random_color, fill_type="solid") 
        # 创建边框样式  
        self.border = Border(left=Side(border_style='thin', color='000000'),  
                        right=Side(border_style='thin', color='000000'),  
                        top=Side(border_style='thin', color='000000'),  
                        bottom=Side(border_style='thin', color='000000'))


    # 1先解析csv的指定内容到BK11中去 2解析更多内容,解析到子表格 3解析多个csv
    def main(self):# 20240305  
        files = os.listdir(self.csv_folder)
        if len(files) > 10:
            print(f'小芳芳: CSV文件超过10个, 现在可以分析了')
        # 筛选出.csv文件,并排序好。
        csv_s = []
        for file in files:
            if file.endswith('.csv'): 
                csv_s.append(file)           
        # new_csv_s = sorted(csv_s)
        # 使用natsort进行排序  
        new_csv_s = natsort.natsorted(csv_s)        
        new_csv_s = [new_csv_s[-1]] + new_csv_s[:-1]

        for file in new_csv_s:
            csv_path = os.path.join(self.csv_folder, file)
            # 读取CSV文件  
            print(f'Read csv path: {csv_path}')
            self.parse_csv(csv_path, self.start_date)
            self.start_date += 1
        self.deal_multi_sheet_excel()

    def _get_input(self):
        date_input = input("请输入日期(如: 20240306)(格式:YYYYMMDD):\n")  
        try:  
            print('输入长度:',len(date_input))
            if (len(date_input) >= 8):
                # 尝试将输入的日期转换为整数  
                self.start_date = int(date_input[0:8]) 
                print(f'输入的参数为:{self.start_date}') 
            else:
                print("小芳芳, 输入长度必须为8, 如: 20240306。否则无法运行。")
                return
        except ValueError:  
            # 如果转换失败,打印错误信息并退出  
            print("输入的日期格式不正确,请使用YYYYMMDD的格式输入。")  
            return          

    def parse_csv(self, csv_file, date):
        df = pd.read_csv(csv_file) # df: DataFrame
        print('df index:', df.index)
        print(df.iloc[0,1])
        asin_lines = df['(子)ASIN']
        session_count = df['会话次数 – 总计']
        ordered_count = df['已订购商品数量']
        for i, asin in enumerate(asin_lines):
            if asin in BK_MAP:
                bk_name = BK_MAP[asin] 
                bk = []
                bk.append(date)
                session = str(session_count.iloc[i])
                print(f'session: {session}')
                # 原本是用于将表格中的去除。这里加个判断。
                if ',' in session:
                    session = session.replace(',', '')
                bk.append(int(session))
                bk.append(int(ordered_count.iloc[i]))
                print(f'{bk_name}, value: {bk}') 

                if bk_name == 'BK11': # 
                    self.bk11_s.append(bk)
                elif bk_name == 'P':
                    self.p_s.append(bk)
                elif bk_name == 'H':
                    self.h_s.append(bk)
                elif bk_name == 'W':
                    self.w_s.append(bk)
                elif bk_name == 'T':
                    self.t_s.append(bk)
                elif bk_name == 'HL':                
                    self.hl_s.append(bk)
                elif bk_name == 'J':    
                    self.j_s.append(bk)
                elif bk_name == 'Z':
                    self.z_s.append(bk)
                elif bk_name == 'C':
                    self.c_s.append(bk)
                elif bk_name == 'R':
                    self.r_s.append(bk)
                elif bk_name == 'DB':
                    self.db_s.append(bk)                

    def deal_multi_sheet_excel(self):  
        # self.workbook = openpyxl.load_workbook(self.xlsx_path)  
        # 遍历所有工作表  
        last_time = ''
        for sheet_name in self.workbook.sheetnames:  
            sheet = self.workbook[sheet_name]  
            print(f"工作表: {sheet_name}")  
            if sheet_name in SHEET_NAMES: #不处理“关键词”,“竞品分析表”等表格。 
                cell2_time_index, cell2_sales_index, cell3_flow_index, cell3_convert_index, cell2_remark_index = self.find_target_index(sheet)
                # 存储了如BK11多天的数据,[[时间,流量,销量], []]
                sheet_infos = self.get_sheet_infos(sheet_name)
                for sheet_info in sheet_infos:
                    sheet_time = str(sheet_info[0]) # 20240314
                    last_time = sheet_time
                    sheet_year = int(sheet_time[0:4])
                    sheet_month = int(sheet_time[4:6])
                    sheet_day = int(sheet_time[6:8])

                    sheet_flow = sheet_info[1]
                    sheet_sale = sheet_info[2]
                    # 遍历工作表的行(从第四行开始,即数据行)  
                    for index, row in enumerate(sheet.iter_rows(min_row=4, values_only=False)):  # 使用values_only=False以获取单元格对象  
                        time_cell = row[cell2_time_index]  # 时间所在索引  
                        cell_time = time_cell.value  
                        if cell_time is None: break # 空的值,就不继续遍历了 
                        year, month, day = cell_time.year, cell_time.month, cell_time.day 
                        # 读取所在列的格式,仅读取一次。字体,线条,对齐
                        if index == 0:
                            flow_font = row[cell3_flow_index].font  
                            sales_font = row[cell2_sales_index].font  
                            convert_font = row[cell3_convert_index].font
                            target_border = self.get_cell_border(row[cell3_flow_index]) #
                            font_alignment = row[cell3_flow_index].alignment
                            sales_alignment = row[cell2_sales_index].alignment
                            convert_alignment = row[cell3_convert_index].alignment
                        # 按照时间,找到所在行,然后修改其中的“流量,销量,转化率”的值。
                        if year==sheet_year and month==sheet_month and day==sheet_day:  # 检查时间是否匹配
                            if self.pattern: self.fill_color(sheet, index+4, cell2_remark_index+2) # 给所在行上色,要额外加4行                                                      
                            flow_cell = row[cell3_flow_index]  
                            sales_cell = row[cell2_sales_index]  
                            convert_cell = row[cell3_convert_index]  
                            print(f"时间:{year}-{month}-{day}, 修改前--流量:{flow_cell.value}, 销量:{sales_cell.value}, 转化率:{convert_cell.value}")  
                            # 修改流量和销量的值  
                            flow_cell.value = sheet_flow                              
                            sales_cell.value = sheet_sale
                            convert_cell.value = round(sales_cell.value/flow_cell.value, 4)
                            print(f"修改后-流量:{flow_cell.value}, 销量:{sales_cell.value}, 转化率:{convert_cell.value}")  
                            # 格式刷
                            flow_cell.font = Font(name=flow_font.name, size=flow_font.size, bold=flow_font.bold, italic=flow_font.italic, color=flow_font.color)            
                            sales_cell.font = Font(name=sales_font.name, size=sales_font.size, bold=sales_font.bold, italic=sales_font.italic, color=sales_font.color)            
                            convert_cell.font = Font(name=convert_font.name, size=convert_font.size, bold=convert_font.bold, italic=convert_font.italic, color=convert_font.color)            
                            flow_cell.border = target_border
                            sales_cell.border = target_border
                            convert_cell.border = target_border
                            flow_cell.alignment = Alignment(horizontal=font_alignment.horizontal,  
                                                            vertical=font_alignment.vertical,  
                                                            text_rotation=font_alignment.text_rotation,  
                                                            wrap_text=font_alignment.wrap_text,  
                                                            shrink_to_fit=font_alignment.shrink_to_fit,  
                                                            indent=font_alignment.indent) 
                            sales_cell.alignment = Alignment(horizontal=sales_alignment.horizontal,  
                                                            vertical=sales_alignment.vertical,  
                                                            text_rotation=sales_alignment.text_rotation,  
                                                            wrap_text=sales_alignment.wrap_text,  
                                                            shrink_to_fit=sales_alignment.shrink_to_fit,  
                                                            indent=sales_alignment.indent)
                            convert_cell.alignment = Alignment(horizontal=convert_alignment.horizontal,  
                                                            vertical=convert_alignment.vertical,  
                                                            text_rotation=convert_alignment.text_rotation,  
                                                            wrap_text=convert_alignment.wrap_text,  
                                                            shrink_to_fit=convert_alignment.shrink_to_fit,  
                                                            indent=convert_alignment.indent)                                                        
                            
                        # else:  
                        #     print(f"{sheet_name}工作表, 单元格时间:{year}-{month}-{day}, 未找到所有需要的列。")  
          
        # 保存修改后的工作簿 
        file_name = os.path.basename(self.xlsx_path) 
        save_path = os.path.join(self.save_xlsw_dir, file_name)
        save_path = f'{save_path[:-5]}_{last_time}.xlsx'
        self.workbook.save(save_path)
        print(f'小芳芳, 新的Excel文件名及保存地址: {save_path}')                 
        
    def fill_color(self, sheet, row, last_col):
        # # 定义要填充的颜色  
        # fill_color = "FFFF00"  # 黄色,这里是RGB的十六进制表示,但没有alpha通道,所以实际上是BGR顺序  
        # fill = PatternFill(start_color=fill_color, end_color=fill_color, fill_type="solid")  
  
        # 给第5行的前20列上颜色  
        for col in range(1, last_col):  # 在Excel中列是从1开始的,所以范围是1到20  
            cell = sheet.cell(row, column=col)  
            cell.fill = self.fill      
            cell.border = self.border  # 应用边框样式                

    def get_cell_border(self, source_cell):
        source_border = source_cell.border          
        # 复制边框可能会稍微复杂一些,因为您需要复制每条边的属性  
        top = Side(style=source_border.top.style, color=source_border.top.color)  
        right = Side(style=source_border.right.style, color=source_border.right.color)  
        bottom = Side(style=source_border.bottom.style, color=source_border.bottom.color)  
        left = Side(style=source_border.left.style, color=source_border.left.color)  
        
        target_border = Border(top=top, right=right, bottom=bottom, left=left)
        return target_border     

    def find_target_index(self, sheet):
        cell2_time_index = -1
        cell2_sales_index = -1
        cell3_flow_index = -1
        cell3_convert_index = -1
        cell2_remark_index = -1            
        for i,cell in enumerate(sheet[2]):
            if cell.value == '时间':
                print(f'时间列索引: {cell.value}, index: {i}')
                cell2_time_index = i
            if cell.value == '销量':
                print(f'销量列索引: {cell.value}, index: {i}')
                cell2_sales_index = i
            if cell.value == '备注':
                print(f'备注列索引: {cell.value}, index: {i}')
                cell2_remark_index = i
        for j,cell in enumerate(sheet[3]):
            if cell.value == '流量':
                print(f'流量列索引: {cell.value}, index: {j}')
                cell3_flow_index = j    
            if cell.value == '转化率':
                cell3_convert_index = j
        if cell2_time_index<0 or cell2_sales_index<0 or cell3_flow_index<0 or cell3_convert_index<0:
            print(f'异常, 有需要的列索引未找到: {cell2_time_index}, {cell2_sales_index}, {cell3_flow_index}, {cell3_convert_index}')
            sys.exit(-1)  
        return cell2_time_index, cell2_sales_index, cell3_flow_index, cell3_convert_index, cell2_remark_index   

    def get_sheet_infos(self, sheet_name):
            sheet_informations = []
            if sheet_name == 'BK11': # ['BK11', 'P', 'H', 'W', 'T', 'HL', 'J', 'Z', 'C', 'R', 'DB', 'LV']
                sheet_informations = self.bk11_s
            elif sheet_name == 'P':
                sheet_informations = self.p_s
            elif sheet_name == 'H':
                sheet_informations = self.h_s
            elif sheet_name == 'W':
                sheet_informations = self.w_s
            elif sheet_name == 'T':
                sheet_informations = self.t_s
            elif sheet_name == 'HL':
                sheet_informations = self.hl_s
            elif sheet_name == 'J':
                sheet_informations = self.j_s
            elif sheet_name == 'Z':
                sheet_informations = self.z_s
            elif sheet_name == 'C':
                sheet_informations = self.c_s
            elif sheet_name == 'R':
                sheet_informations = self.r_s
            elif sheet_name == 'DB':
                sheet_informations = self.db_s
            return sheet_informations



if __name__ == '__main__':
    parseCsvs = ParseCsvs2Excel(pattern=False)
    parseCsvs.main()

<think>嗯,用户现在的需求很明确:想把Wireshark抓取的数据包导出成Excel格式。这其实是个挺常见的需求,特别是需要做数据分析或者写报告的时候。用户之前提到过手机HTTPS抓包和TCP解析的引用,不过核心诉求还是格式转换。从对话历史看,用户应该已经掌握了基础抓包技能,现在卡在数据处理环节。ta可能遇到的情况是:Wireshark界面里的数据很难直接复制使用,或者需要把特定字段(比如IP地址、时间戳)整理成表格。这种需求在写实验报告或分析文档时特别常见。技术上其实有几种可行方案:最直接的是用Wireshark自带的导出功能配合CSV中转,虽然菜单叫"ExportPacketDissections",但CSV本身就是表格数据,Excel打开毫无压力。用户可能没注意到这个菜单项的位置——在"文件"下拉列表的中间区域,确实不太起眼。如果用户只需要关键字段的统计数据,比如流量排名前10的IP地址,用"Statistics"菜单里的报告功能会更高效。这个功能生成的虽然是文本表格,但Excel的"文本导入向导"处理起来也很顺手。稍微复杂点但更灵活的方法是TSHARK命令行导出,特别适合需要批量处理的情况。比如用户如果每天都要导出一批抓包文件,写个bat脚本自动转换会很省事。考虑到用户提到过计算机系统安全的作业,说不定ta后续真会有自动化需求。最后那个"ExportObjects"提醒很重要,很多用户会忘记HTTP导出功能只能处理未加密流量。用户之前抓过HTTPS包,如果直接操作肯定失败,得提前说明清楚。相关问题的设计要覆盖用户可能的后续需求:ta这次问导出Excel,下一步很可能要问怎么清洗数据、怎么分析特定协议字段,或者遇到导出失败的情况。把CSV分隔符问题和HTTP对象提取的可能性都列出来比较周全。</think> 将Wireshark抓取的数据包导出为Excel格式可通过以下步骤实现: --- ### **分步操作指南** #### **1. 导出为CSV文件** - 在Wireshark中选择目标数据包 → 点击菜单栏 `文件` → `导出分组解析结果` - 在保存类型中选择 **`逗号分隔值(*.csv)`** - 勾选需要导出的字段(如源IP、目的IP、协议类型等)→ 保存文件 *注:CSV可直接用Excel打开编辑* #### **2. 转换CSVExcel格式** - 用Excel打开CSV文件 → 点击菜单栏 `数据` → `获取数据` → `从文本/CSV` - 调整列格式后 → 点击 `加载` 完成转换 *注:若数据量较大,建议用Excel的「数据分列」功能优化格式* #### **3. 按协议导出特定数据** - 使用显示过滤器(如 `tcp` / `http`)筛选数据包 - 右键数据包列表 → `导出分组解析结果` → 选择CSV格式 *此方法可精准导出指定协议字段* #### **4. 通过TSHARK命令行导出** 在终端执行: ```bash tshark -r 输入文件.pcapng -T fields -e frame.number -e ip.src -e ip.dst -E header=y -E separator=, > 输出.csv ``` - `-e` 指定导出字段(如 `tcp.port` / `http.host`) - `-E separator=,` 设置逗号为分隔符 *适合批量处理或自动化脚本[^1]* --- ### **注意事项** 1. **字段选择** Wireshark默认导出所有可见列,建议在 `导出` 对话框中手动勾选关键字段(如下图),避免Excel臃肿 ![字段选择示意图](https://www.wireshark.org/docs/wsug_html/export-dialog.png) 2. **HTTP对象导出限制** HTTPS加密内容无法直接导出明文(需SSL密钥解密),HTTP对象可通过 `文件` → `导出对象` → `HTTP` 单独导出[^2] 3. **大数据处理** 超过10万行的数据建议先过滤再导出,或使用数据库工具处理 --- ### **
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值