Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
Amazon-Selection-Data
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abel_cjy
Amazon-Selection-Data
Commits
809c5a60
Commit
809c5a60
authored
Aug 28, 2026
by
chenyuanjie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
信息库月流程调整
parent
ff5dda2e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
25 additions
and
100 deletions
+25
-100
dwt_ai_asin.py
Pyspark_job/doris_handle/dwt_ai_asin.py
+25
-100
No files found.
Pyspark_job/doris_handle/dwt_ai_asin.py
View file @
809c5a60
"""
"""
@Author : CT
@Author : CT
@Description : 信息库月度整合脚本
@Description : 信息库月度整合脚本
- 从 dwt_flow_asin 读取当月符合条件的ASIN及详情字段
(含 mom/yoy)
- 从 dwt_flow_asin 读取当月符合条件的ASIN及详情字段
- 过滤禁用分类,筛选信息库候选ASIN(月销>=50,asin_type in (0,1))
- 过滤禁用分类,筛选信息库候选ASIN(月销>=50,asin_type in (0,1))
- is_new_flag:跟上个月 Hive dwt_ai_asin 比,上月没有的视为新增
- is_new_flag / is_ascending_flag:已废弃,不再计算,Hive里固定写NULL(保留字段位避免破坏历史表结构)
- is_ascending_flag:近6月 asin_bought_mom>0 满6次
- 关联ODS评论(ods_asin_detail)
- 关联店铺(dwt_fb_base_report)、ODS评论(ods_asin_detail)
- Hive dwt_ai_asin 备份;PG表 {site}_ai_asin_detail 且只导出增量:跟 Doris selection.{site}_ai_asin_analyze_detail 反连接,
- Hive dwt_ai_asin 备份;不再写 Doris selection.{site}_ai_asin_detail,
改成写 PG15 {site}_ai_asin_detail_month_{yyyy_mm}(LIKE上月同名表建表),
且只导出增量:跟 Doris selection.{site}_ai_asin_analyze_detail 反连接,
已经在里面(已完成AI分析)的不用再导出
已经在里面(已完成AI分析)的不用再导出
"""
"""
import
os
import
os
...
@@ -35,17 +32,9 @@ class DwtAiAsin(object):
...
@@ -35,17 +32,9 @@ class DwtAiAsin(object):
app_name
=
f
"{self.__class__.__name__}:{site_name}:{date_type}:{date_info}"
app_name
=
f
"{self.__class__.__name__}:{site_name}:{date_type}:{date_info}"
self
.
spark
=
SparkUtil
.
get_spark_session
(
app_name
)
self
.
spark
=
SparkUtil
.
get_spark_session
(
app_name
)
# 近6个月(含当月)用于 is_ascending_flag
self
.
df_base_asin
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
last_6_month
=
[
CommonUtil
.
get_month_offset
(
date_info
,
-
i
)
for
i
in
range
(
0
,
6
)]
self
.
df_ods_detail
=
self
.
spark
.
sql
(
"select 1+1"
)
# 上个月,用于 is_new_flag 比对 + PG建表模板月份
self
.
df_save
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
last_month
=
CommonUtil
.
get_month_offset
(
date_info
,
-
1
)
self
.
df_base_asin
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
df_existing_asin
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
df_ascending_flag
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
df_fb_info
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
df_ods_detail
=
self
.
spark
.
sql
(
"select 1+1"
)
self
.
df_save
=
self
.
spark
.
sql
(
"select 1+1"
)
def
run
(
self
):
def
run
(
self
):
self
.
read_data
()
self
.
read_data
()
...
@@ -64,20 +53,21 @@ class DwtAiAsin(object):
...
@@ -64,20 +53,21 @@ class DwtAiAsin(object):
asin_title AS title,
asin_title AS title,
asin_brand_name AS brand,
asin_brand_name AS brand,
account_name,
account_name,
account_id AS seller_id,
seller_country_name AS fb_country_name,
asin_buy_box_seller_type AS buy_box_seller_type,
asin_buy_box_seller_type AS buy_box_seller_type,
asin_launch_time AS launch_time,
asin_launch_time AS launch_time,
asin_img_num AS img_num,
asin_img_num AS img_num,
CASE WHEN variation_num > 0 THEN 1 ELSE 0 END AS variation_flag,
CASE WHEN variation_num > 0 THEN 1 ELSE 0 END AS variation_flag,
variation_num,
variation_num,
asin_ao_val AS ao_val,
asin_ao_val AS ao_val,
category_first_id
AS category_id
,
category_first_id,
category_id AS category_current_id,
category_id AS category_current_id,
parent_asin,
parent_asin,
first_category_rank AS bsr_rank,
first_category_rank AS bsr_rank,
asin_price AS price,
asin_price AS price,
asin_rating AS rating,
asin_rating AS rating,
asin_total_comments AS total_comments,
asin_total_comments AS total_comments,
asin_launch_time_type AS launch_time_type,
asin_describe AS describe,
asin_describe AS describe,
asin_bought_mom AS bought_month_mom,
asin_bought_mom AS bought_month_mom,
asin_bought_yoy AS bought_month_yoy
asin_bought_yoy AS bought_month_yoy
...
@@ -116,41 +106,13 @@ class DwtAiAsin(object):
...
@@ -116,41 +106,13 @@ class DwtAiAsin(object):
)
)
self
.
df_base_asin
=
self
.
df_base_asin
\
self
.
df_base_asin
=
self
.
df_base_asin
\
.
join
(
df_filter_cat_id
,
'category_id'
,
'left_anti'
)
\
.
join
(
df_filter_cat_id
,
self
.
df_base_asin
[
'category_current_id'
]
==
df_filter_cat_id
[
'category_id'
]
,
'left_anti'
)
\
.
join
(
df_filter_cat_desc
,
'category'
,
'left_anti'
)
\
.
join
(
df_filter_cat_desc
,
'category'
,
'left_anti'
)
\
.
repartition
(
40
,
'asin'
)
\
.
repartition
(
40
,
'asin'
)
\
.
persist
(
StorageLevel
.
DISK_ONLY
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
print
(
f
"当月信息库ASIN:{self.df_base_asin.count()}"
)
print
(
f
"当月信息库ASIN:{self.df_base_asin.count()}"
)
# ── 2. 存量asin(上个月 Hive dwt_ai_asin),用于 is_new_flag:相比上月是否为新增 ──
# ── 2. ODS 评论/产品详情(取 updated_at 最新一条)──
sql_exist
=
f
"""
SELECT asin FROM dwt_ai_asin
WHERE site_name = '{self.site_name}' AND date_type = '{self.date_type}' AND date_info = '{self.last_month}'
"""
self
.
df_existing_asin
=
self
.
spark
.
sql
(
sql_exist
)
.
repartition
(
40
,
'asin'
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
print
(
f
"上月({self.last_month}) 信息库存量ASIN:{self.df_existing_asin.count()}"
)
# ── 3. 近6月 asin_bought_mom,用于 is_ascending_flag ──
sql_asc
=
f
"""
SELECT asin, asin_bought_mom
FROM dwt_flow_asin
WHERE site_name = '{self.site_name}'
AND date_type = '{self.date_type}'
AND date_info IN ({CommonUtil.list_to_insql(self.last_6_month)})
"""
self
.
df_ascending_flag
=
self
.
spark
.
sql
(
sql_asc
)
.
repartition
(
40
,
'asin'
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
# ── 4. 店铺信息 ──
sql_fb
=
f
"""
SELECT account_name, seller_id, fb_country_name, business_addr AS account_addr
FROM dwt_fb_base_report
WHERE site_name = '{self.site_name}'
AND date_type = '{self.date_type}'
AND date_info = '{self.date_info}'
"""
self
.
df_fb_info
=
self
.
spark
.
sql
(
sql_fb
)
.
dropDuplicates
([
'account_name'
])
.
persist
(
StorageLevel
.
DISK_ONLY
)
# ── 5. ODS 评论/产品详情(取 updated_at 最新一条)──
sql_ods
=
f
"""
sql_ods
=
f
"""
SELECT asin, review_json_list, product_json, product_detail_json, updated_at
SELECT asin, review_json_list, product_json, product_detail_json, updated_at
FROM ods_asin_detail
FROM ods_asin_detail
...
@@ -165,27 +127,9 @@ class DwtAiAsin(object):
...
@@ -165,27 +127,9 @@ class DwtAiAsin(object):
.
repartition
(
40
,
'asin'
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
.
repartition
(
40
,
'asin'
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
def
handle_data
(
self
):
def
handle_data
(
self
):
# is_new_flag:不在上月 Hive dwt_ai_asin 存量中的视为新增
self
.
df_base_asin
=
self
.
df_base_asin
\
.
join
(
self
.
df_existing_asin
.
withColumn
(
'_exist'
,
F
.
lit
(
0
)),
'asin'
,
'left'
)
\
.
withColumn
(
'is_new_flag'
,
F
.
when
(
F
.
col
(
'_exist'
)
.
isNull
(),
F
.
lit
(
1
))
.
otherwise
(
F
.
lit
(
0
)))
\
.
drop
(
'_exist'
)
# is_ascending_flag:近6月 mom 全部 > 0 且出现6次
df_asc
=
self
.
df_ascending_flag
.
groupBy
(
'asin'
)
.
agg
(
F
.
count
(
'asin'
)
.
alias
(
'month_cnt'
),
F
.
sum
(
F
.
when
(
F
.
col
(
'asin_bought_mom'
)
>
0
,
1
)
.
otherwise
(
0
))
.
alias
(
'rising_cnt'
)
)
.
withColumn
(
'is_ascending_flag'
,
F
.
when
((
F
.
col
(
'month_cnt'
)
==
6
)
&
(
F
.
col
(
'rising_cnt'
)
==
6
),
F
.
lit
(
1
))
.
otherwise
(
F
.
lit
(
0
))
)
.
drop
(
'month_cnt'
,
'rising_cnt'
)
# 汇总关联
# 汇总关联
self
.
df_save
=
self
.
df_base_asin
\
self
.
df_save
=
self
.
df_base_asin
\
.
join
(
df_asc
,
'asin'
,
'left'
)
\
.
join
(
self
.
df_ods_detail
,
'asin'
,
'left'
)
.
join
(
self
.
df_fb_info
,
'account_name'
,
'left'
)
\
.
join
(
self
.
df_ods_detail
,
'asin'
,
'left'
)
\
.
fillna
({
'is_new_flag'
:
0
,
'is_ascending_flag'
:
0
})
def
save_data
(
self
):
def
save_data
(
self
):
# 字段对齐 us_ai_asin_detail
# 字段对齐 us_ai_asin_detail
...
@@ -198,14 +142,14 @@ class DwtAiAsin(object):
...
@@ -198,14 +142,14 @@ class DwtAiAsin(object):
F
.
col
(
'title'
),
F
.
col
(
'title'
),
F
.
col
(
'brand'
),
F
.
col
(
'brand'
),
F
.
col
(
'account_name'
),
F
.
col
(
'account_name'
),
F
.
col
(
'account_addr'
),
F
.
lit
(
None
)
.
alias
(
'account_addr'
),
# 废弃字段
F
.
col
(
'buy_box_seller_type'
),
F
.
col
(
'buy_box_seller_type'
),
F
.
col
(
'launch_time'
),
F
.
col
(
'launch_time'
),
F
.
col
(
'img_num'
),
F
.
col
(
'img_num'
),
F
.
col
(
'variation_flag'
),
F
.
col
(
'variation_flag'
),
F
.
col
(
'variation_num'
),
F
.
col
(
'variation_num'
),
F
.
col
(
'ao_val'
),
F
.
col
(
'ao_val'
),
F
.
col
(
'category_id'
),
F
.
col
(
'category_
first_
id'
),
F
.
col
(
'category_current_id'
),
F
.
col
(
'category_current_id'
),
F
.
col
(
'parent_asin'
),
F
.
col
(
'parent_asin'
),
F
.
col
(
'bsr_rank'
),
F
.
col
(
'bsr_rank'
),
...
@@ -215,14 +159,14 @@ class DwtAiAsin(object):
...
@@ -215,14 +159,14 @@ class DwtAiAsin(object):
F
.
col
(
'seller_id'
),
F
.
col
(
'seller_id'
),
F
.
col
(
'fb_country_name'
),
F
.
col
(
'fb_country_name'
),
F
.
col
(
'review_json_list'
),
F
.
col
(
'review_json_list'
),
F
.
col
(
'launch_time_type'
),
F
.
lit
(
None
)
.
alias
(
'launch_time_type'
),
# 废弃字段
F
.
col
(
'describe'
),
F
.
col
(
'describe'
),
F
.
col
(
'product_json'
),
F
.
col
(
'product_json'
),
F
.
col
(
'product_detail_json'
),
F
.
col
(
'product_detail_json'
),
F
.
col
(
'bought_month_mom'
),
F
.
col
(
'bought_month_mom'
),
F
.
col
(
'bought_month_yoy'
),
F
.
col
(
'bought_month_yoy'
),
F
.
col
(
'is_new_flag'
),
F
.
lit
(
None
)
.
alias
(
'is_new_flag'
),
# 废弃字段
F
.
col
(
'is_ascending_flag'
),
F
.
lit
(
None
)
.
alias
(
'is_ascending_flag'
),
# 同上
F
.
lit
(
0
)
.
alias
(
'chat_flag'
),
F
.
lit
(
0
)
.
alias
(
'chat_flag'
),
# 分区字段必须在最后
# 分区字段必须在最后
F
.
lit
(
self
.
site_name
)
.
alias
(
'site_name'
),
F
.
lit
(
self
.
site_name
)
.
alias
(
'site_name'
),
...
@@ -245,25 +189,23 @@ class DwtAiAsin(object):
...
@@ -245,25 +189,23 @@ class DwtAiAsin(object):
partitionBy
=
[
'site_name'
,
'date_type'
,
'date_info'
]
partitionBy
=
[
'site_name'
,
'date_type'
,
'date_info'
]
)
)
# ── PG 写入
(只导出增量:不在 Doris selection.{site}_ai_asin_analyze_detail 里的才需要)
──
# ── PG 写入
{site}_ai_asin_detail,只导出增量:不在 Doris selection.{site}_ai_asin_analyze_detail 里的才需要
──
sql_analyzed
=
f
"SELECT asin FROM `selection`.`{self.site_name}_ai_asin_analyze_detail`"
sql_analyzed
=
f
"SELECT asin FROM `selection`.`{self.site_name}_ai_asin_analyze_detail`"
df_analyzed_asin
=
DorisHelper
.
spark_import_with_sql
(
self
.
spark
,
sql_analyzed
)
.
repartition
(
40
,
'asin'
)
df_analyzed_asin
=
DorisHelper
.
spark_import_with_sql
(
self
.
spark
,
sql_analyzed
)
.
repartition
(
40
,
'asin'
)
# persist:下面先count()校验数量、再write()真正落库,两次action共用同一份物化结果,
# persist:下面先count()校验数量、再write()真正落库,两次action共用同一份物化结果,
# 不然anti join(含一次Doris JDBC读取)会被重新算一遍
# 不然anti join(含一次Doris JDBC读取)会被重新算一遍
df_to_export
=
self
.
df_save
.
drop
(
'date_type'
,
'date_info'
)
\
df_to_export
=
self
.
df_save
.
drop
(
.
join
(
df_analyzed_asin
,
'asin'
,
'left_anti'
)
\
'date_type'
,
'date_info'
,
'account_addr'
,
'launch_time_type'
,
'is_new_flag'
,
'is_ascending_flag'
)
.
join
(
df_analyzed_asin
,
'asin'
,
'left_anti'
)
\
.
persist
(
StorageLevel
.
DISK_ONLY
)
.
persist
(
StorageLevel
.
DISK_ONLY
)
export_count
=
df_to_export
.
count
()
export_count
=
df_to_export
.
count
()
print
(
f
"待导出PG的增量ASIN数量:{export_count}"
)
print
(
f
"待导出PG的增量ASIN数量:{export_count}"
)
pg_con
=
DBUtil
.
get_connection_info
(
"postgresql"
,
"us"
)
pg_con
=
DBUtil
.
get_connection_info
(
"postgresql"
,
"us"
)
export_pg_tb
=
f
"{self.site_name}_ai_asin_detail_month_{self.date_info.replace('-', '_')}"
export_pg_tb
=
f
"{self.site_name}_ai_asin_detail"
template_tb
=
f
"{self.site_name}_ai_asin_detail_month_{self.last_month.replace('-', '_')}"
try
:
try
:
# 即使这个月没有增量,也要把当月空表建出来,避免下个月LIKE这个月当模板建表时找不到表
self
.
create_pg_table_if_absent
(
export_pg_tb
,
template_tb
)
if
export_count
==
0
:
if
export_count
==
0
:
print
(
"没有需要导出到PG的增量ASIN,
空表已建好,
跳过写入"
)
print
(
"没有需要导出到PG的增量ASIN,跳过写入"
)
return
return
df_to_export
.
write
.
format
(
"jdbc"
)
\
df_to_export
.
write
.
format
(
"jdbc"
)
\
.
option
(
"url"
,
pg_con
[
"url"
])
\
.
option
(
"url"
,
pg_con
[
"url"
])
\
...
@@ -280,23 +222,6 @@ class DwtAiAsin(object):
...
@@ -280,23 +222,6 @@ class DwtAiAsin(object):
CommonUtil
.
send_wx_msg
([
'chenyuanjie'
],
'⚠ ASIN信息库月度数据写入PG失败'
,
CommonUtil
.
send_wx_msg
([
'chenyuanjie'
],
'⚠ ASIN信息库月度数据写入PG失败'
,
f
'详情:{export_pg_tb} {self.site_name} {self.date_type} {self.date_info}'
)
f
'详情:{export_pg_tb} {self.site_name} {self.date_type} {self.date_info}'
)
@staticmethod
def
create_pg_table_if_absent
(
export_pg_tb
,
template_tb
):
"""LIKE 上月同名表建表(INCLUDING ALL 复制字段类型/约束/索引),并重建独立id序列;表已存在则跳过"""
engine
=
DBUtil
.
get_db_engine
(
"postgresql"
,
"us"
)
result
=
DBUtil
.
engine_exec_sql
(
engine
,
f
"SELECT to_regclass('{export_pg_tb}')"
)
if
list
(
result
)[
0
][
0
]
is
not
None
:
print
(
f
"PostgreSQL 表 {export_pg_tb} 已存在,跳过建表"
)
return
sql
=
f
"""
CREATE TABLE {export_pg_tb} (LIKE {template_tb} INCLUDING ALL);
ALTER TABLE {export_pg_tb} ALTER COLUMN id DROP DEFAULT;
CREATE SEQUENCE {export_pg_tb}_id_seq OWNED BY {export_pg_tb}.id;
ALTER TABLE {export_pg_tb} ALTER COLUMN id SET DEFAULT nextval('{export_pg_tb}_id_seq')
"""
DBUtil
.
exec_sql
(
"postgresql"
,
"us"
,
sql
)
print
(
f
"PostgreSQL 表 {export_pg_tb} 创建完成(LIKE {template_tb},独立自增序列)"
)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
site_name
=
sys
.
argv
[
1
]
site_name
=
sys
.
argv
[
1
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment