|
|
@@ -99,24 +99,28 @@ class ExcelGenerator:
|
|
|
df = processor.get_sorted_dataframe()
|
|
|
|
|
|
# 写入表头
|
|
|
- asin_cell = self.ws.cell(1, self.current_col, asin)
|
|
|
- asin_cell.font = HEADER_FONT
|
|
|
+ # 标题行下移到第3行(图片占1-2行)
|
|
|
+ # 标题行调整到第2行
|
|
|
+ asin_cell = self.ws.cell(2, self.current_col, asin)
|
|
|
+ asin_cell.font = Font(bold=True, color='0000FF', underline='single') # 添加蓝色下划线
|
|
|
asin_cell.fill = HEADER_FILL
|
|
|
asin_cell.alignment = Alignment(horizontal='center', vertical='center')
|
|
|
|
|
|
- search_volume_cell = self.ws.cell(1, self.current_col + 1, "搜索量")
|
|
|
+ search_volume_cell = self.ws.cell(2, self.current_col + 1, "搜索量")
|
|
|
search_volume_cell.font = HEADER_FONT
|
|
|
search_volume_cell.fill = HEADER_FILL
|
|
|
search_volume_cell.alignment = Alignment(horizontal='center', vertical='center')
|
|
|
|
|
|
# 使用pandas写入数据
|
|
|
+ # 数据从第3行开始(标题行下方直接开始数据)
|
|
|
for idx, row in df.iterrows():
|
|
|
- data_row = idx + 2 # Excel行号从2开始
|
|
|
+ data_row = idx + 3
|
|
|
|
|
|
# 关键词(带超链接)
|
|
|
kw_cell = self.ws.cell(data_row, self.current_col, row['traffic_keyword'])
|
|
|
if pd.notna(row.get('amazon_search_link')):
|
|
|
kw_cell.hyperlink = row['amazon_search_link']
|
|
|
+ kw_cell.font = Font(color='0000FF', underline='single') # 添加蓝色下划线样式
|
|
|
|
|
|
# 搜索量
|
|
|
search_cell = self.ws.cell(data_row, self.current_col + 1, row['monthly_searches'])
|
|
|
@@ -135,13 +139,13 @@ class ExcelGenerator:
|
|
|
|
|
|
# 产品信息
|
|
|
self.ws.cell(start_row, self.current_col, "产品信息").font = Font(bold=True)
|
|
|
- info_text = "\n".join([
|
|
|
- f"标题: {processor.product_info.get('title', '')}",
|
|
|
- f"评分: {processor.product_info.get('stars', '')}",
|
|
|
- f"价格: {processor.product_info.get('price', '')}"
|
|
|
- ])
|
|
|
+ # 从product_info提取实际存在的字段
|
|
|
+ info_text = processor.product_info.get('main_text', '')
|
|
|
+ if processor.product_info.get('goto_amazon'):
|
|
|
+ info_text += f"\n产品链接: {processor.product_info['goto_amazon']}"
|
|
|
info_cell = self.ws.cell(start_row+1, self.current_col, info_text)
|
|
|
info_cell.alignment = Alignment(wrap_text=True, vertical='top')
|
|
|
+ self.ws.column_dimensions[get_column_letter(self.current_col)].width = 35
|
|
|
|
|
|
# 唯一词
|
|
|
self.ws.cell(start_row+4, self.current_col, "唯一词").font = Font(bold=True)
|
|
|
@@ -159,34 +163,40 @@ class ExcelGenerator:
|
|
|
img = Image(BytesIO(img_data))
|
|
|
|
|
|
# 图片位置:附加信息上方
|
|
|
- img_row = self.max_data_rows + 2
|
|
|
+ # 图片插入到第1行(标题之前)
|
|
|
+ img_row = 1
|
|
|
img.anchor = f'{get_column_letter(self.current_col)}{img_row}'
|
|
|
self.ws.add_image(img)
|
|
|
|
|
|
- # 调整行高
|
|
|
+ # 调整行高并预留空间
|
|
|
self.ws.row_dimensions[img_row].height = 150
|
|
|
+ # 更新最大数据行数(数据从第5行开始)
|
|
|
+ self.max_data_rows = max(self.max_data_rows, 5)
|
|
|
except Exception as e:
|
|
|
logger.error(f'图片插入失败: {e}')
|
|
|
|
|
|
def apply_formatting(self):
|
|
|
"""应用最终格式"""
|
|
|
self._apply_conditional_formatting()
|
|
|
- self._adjust_column_widths()
|
|
|
+ # self._adjust_column_widths()
|
|
|
self._set_global_alignment()
|
|
|
|
|
|
def _apply_conditional_formatting(self):
|
|
|
"""应用条件格式"""
|
|
|
red_rule = CellIsRule(
|
|
|
operator='greaterThan',
|
|
|
- formula=['10000'],
|
|
|
+ formula=['10000'], # 1万阈值
|
|
|
fill=RED_FILL
|
|
|
)
|
|
|
|
|
|
- # 每隔一列应用条件格式
|
|
|
- for col in range(2, self.current_col, COLUMN_SPACING):
|
|
|
- col_letter = get_column_letter(col)
|
|
|
+ # 精确应用条件格式到每个产品的搜索量列(current_col+1)
|
|
|
+ # 遍历每个产品的搜索量列(current_col +1 的步进)
|
|
|
+ for col in range(1, self.current_col, COLUMN_SPACING):
|
|
|
+ search_col = col + 1 # 每个产品的搜索量列
|
|
|
+ col_letter = get_column_letter(search_col)
|
|
|
+ # 应用格式到整个数据区域
|
|
|
self.ws.conditional_formatting.add(
|
|
|
- f'{col_letter}2:{col_letter}{self.max_data_rows}',
|
|
|
+ f'{col_letter}3:{col_letter}{self.max_data_rows}',
|
|
|
red_rule
|
|
|
)
|
|
|
|
|
|
@@ -246,4 +256,4 @@ if __name__ == "__main__":
|
|
|
generator.add_product(json_path, asin)
|
|
|
|
|
|
generator.apply_formatting()
|
|
|
- generator.save()
|
|
|
+ generator.save()
|