File size: 9,055 Bytes
ed642c2
 
 
 
 
 
 
 
 
abcb27a
134a32c
f2b4a88
ed642c2
a0cd1f2
ed642c2
 
a0cd1f2
ed642c2
 
36f7670
a0cd1f2
fb8274a
 
 
a0cd1f2
ed642c2
 
 
a0cd1f2
ed642c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a0cd1f2
ed642c2
 
 
 
 
a0cd1f2
ed642c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e59d6a2
a0cd1f2
25869c1
 
 
 
 
 
 
 
 
 
e59d6a2
 
 
 
ed642c2
a0cd1f2
ed642c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a0cd1f2
ed642c2
 
 
 
 
 
 
 
a0cd1f2
ed642c2
 
 
 
 
a0cd1f2
ed642c2
 
 
 
 
 
 
 
 
 
 
 
25869c1
a0cd1f2
25869c1
 
 
 
 
 
 
 
 
 
ed642c2
a0cd1f2
ed642c2
 
a0cd1f2
ed642c2
 
 
 
 
 
 
 
 
a0cd1f2
abcb27a
a0cd1f2
abcb27a
fb8274a
abcb27a
ab0c85e
abcb27a
fb8274a
abcb27a
fb8274a
 
abcb27a
 
ab0c85e
 
 
a0cd1f2
ab0c85e
 
 
fb8274a
ab0c85e
 
 
 
1962771
a0cd1f2
ab0c85e
 
1962771
a0cd1f2
ab0c85e
 
1962771
a0cd1f2
ab0c85e
 
 
1962771
a0cd1f2
ab0c85e
 
44c46e1
a0cd1f2
fb8274a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import os
import requests
import pandas as pd
import matplotlib as mpl
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
import streamlit as st
import json
import time
from pytrends.request import TrendReq
import plotly.express as px
from datetime import datetime, timedelta

# 設置 Streamlit 應用標題
st.title("🐣MOMO 🆚 PCHOME 商品搜索和價格分析👁️‍🗨️")

# 獲取用戶輸入
search_keyword = st.text_input("請輸入要搜索的關鍵字: ", "筆電")
page_number = st.number_input("請輸入要搜索的頁數: ", min_value=1, max_value=100, value=1, step=1)

# Pytrends 的日期範圍輸入
start_date = st.date_input("選擇開始日期", value=datetime.today() - timedelta(days=30))
end_date = st.date_input("選擇結束日期", value=datetime.today())

# 創建一個按鈕來開始爬取過程
if st.button("開始搜索"):
    start_time = time.time()
    
    # MOMO 爬取
    momo_url = "https://apisearch.momoshop.com.tw/momoSearchCloud/moec/textSearch"
    momo_headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
    }
    momo_payload = {
        "host": "momoshop",
        "flag": "searchEngine",
        "data": {
            "searchValue": search_keyword,
            "curPage": str(page_number),
            "priceS": "0",
            "priceE": "9999999",
            "searchType": "1"
        }
    }
    momo_response = requests.post(momo_url, headers=momo_headers, json=momo_payload)
    
    if momo_response.status_code == 200:
        momo_data = momo_response.json().get('rtnSearchData', {}).get('goodsInfoList', [])
        momo_product_list = []
        for product in momo_data:
            name = product.get('goodsName', '')
            price = product.get('goodsPrice', '')
            price_str = str(price).split('(')[0].replace(',', '').replace('$', '')
            try:
                product_price = float(price_str)
            except ValueError:
                product_price = 0
            momo_product_list.append({'title': name, 'price': product_price, 'platform': 'MOMO'})
        
        momo_df = pd.DataFrame(momo_product_list)
        st.write("MOMO 商品數據:", momo_df)
        
        # MOMO 數據分析
        momo_avg_price = momo_df['price'].mean()
        st.write(f"MOMO 平均價格: {momo_avg_price:.2f}")
        st.write(f"MOMO 最高價格: {momo_df['price'].max():.2f}")
        st.write(f"MOMO 最低價格: {momo_df['price'].min():.2f}")
        
        # MOMO 視覺化
        font_url = "https://drive.google.com/uc?id=1eGAsTN1HBpJAkeVM57_C7ccp7hbgSz3_&export=download"
        font_response = requests.get(font_url)
        with open("TaipeiSansTCBeta-Regular.ttf", "wb") as font_file:
            font_file.write(font_response.content)
        fm.fontManager.addfont("TaipeiSansTCBeta-Regular.ttf")
        mpl.rc('font', family='Taipei Sans TC Beta')
        
        fig, ax = plt.subplots(figsize=(15, 8))
        ax.plot(momo_df.index[:70], momo_df['price'][:70], 'o', color='skyblue', markersize=8)
        ax.set_title(f'MOMO 電商網站上 "{search_keyword}" 的銷售價格', fontsize=20, fontweight='bold')
        ax.axhline(y=momo_avg_price, color='red', linestyle='--', linewidth=2, label=f'參考價格: {momo_avg_price:.2f}')
        ax.set_xlabel('商品索引', fontsize=14)
        ax.set_ylabel('價格', fontsize=14)
        ax.tick_params(axis='x', rotation=45, labelsize=12)
        ax.tick_params(axis='y', labelsize=12)
        ax.legend(fontsize=12, loc='upper left')
        ax.grid(axis='y', linestyle='--', alpha=0.7)
        plt.tight_layout()
        st.pyplot(fig)
        
        # MOMO Sunburst圖
        if not momo_df.empty:
            momo_sunburst = momo_df.groupby(['title', 'price']).size().reset_index(name='count')
            fig_momo_sunburst = px.sunburst(
                momo_sunburst, 
                path=['title', 'price'], 
                values='count', 
                title='MOMO 商品價格分佈'
            )
            fig_momo_sunburst.update_layout(margin=dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig_momo_sunburst)
    else:
        st.error(f"MOMO 請求失敗,狀態碼: {momo_response.status_code}")


    
    # PCHOME 爬取
    pchome_base_url = 'https://ecshweb.pchome.com.tw/search/v3.3/all/results?q='
    pchome_data = pd.DataFrame()
    
    for i in range(1, page_number + 1):
        pchome_url = f'{pchome_base_url}{search_keyword}&page={i}&sort=sale/dc'
        pchome_response = requests.get(pchome_url)
        if pchome_response.status_code == 200:
            pchome_json_data = json.loads(pchome_response.content)
            pchome_df = pd.DataFrame(pchome_json_data['prods'])
            
            available_columns = ['name', 'describe', 'price', 'orig']
            selected_columns = [col for col in available_columns if col in pchome_df.columns]
            pchome_df = pchome_df[selected_columns]
            if 'orig' in pchome_df.columns:
                pchome_df = pchome_df.rename(columns={'orig': 'original_price'})
            pchome_df['platform'] = 'PCHOME'  # 添加平台識別符
            pchome_data = pd.concat([pchome_data, pchome_df])
            time.sleep(1)
        else:
            st.error(f"PCHOME 請求失敗,狀態碼: {pchome_response.status_code}")
    
    if not pchome_data.empty:
        st.write("PCHOME 商品數據:", pchome_data)
        
        # PCHOME 數據分析
        pchome_avg_price = pchome_data['price'].mean()
        st.write(f"PCHOME 平均價格: {pchome_avg_price:.2f}")
        st.write(f"PCHOME 最高價格: {pchome_data['price'].max():.2f}")
        st.write(f"PCHOME 最低價格: {pchome_data['price'].min():.2f}")
        
        # PCHOME 視覺化
        fig, ax = plt.subplots(figsize=(15, 8))
        ax.plot(pchome_data.index[:70], pchome_data['price'][:70], 'o', color='skyblue', markersize=8)
        ax.set_title(f'PCHOME 電商網站上 "{search_keyword}" 的銷售價格', fontsize=20, fontweight='bold')
        ax.axhline(y=pchome_avg_price, color='red', linestyle='--', linewidth=2, label=f'參考價格: {pchome_avg_price:.2f}')
        ax.set_xlabel('商品索引', fontsize=14)
        ax.set_ylabel('價格', fontsize=14)
        ax.tick_params(axis='x', rotation=45, labelsize=12)
        ax.tick_params(axis='y', labelsize=12)
        ax.legend(fontsize=12, loc='upper left')
        ax.grid(axis='y', linestyle='--', alpha=0.7)
        plt.tight_layout()
        st.pyplot(fig)

        # PCHOME Sunburst圖
        if not pchome_data.empty:
            pchome_sunburst = pchome_data.groupby(['name', 'price']).size().reset_index(name='count')
            fig_pchome_sunburst = px.sunburst(
                pchome_sunburst, 
                path=['name', 'price'], 
                values='count', 
                title='PCHOME 商品價格分佈'
            )
            fig_pchome_sunburst.update_layout(margin=dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig_pchome_sunburst)
    
    # 合併 MOMO 和 PCHOME 的數據
    combined_data = pd.concat([momo_df, pchome_data], ignore_index=True)
    
    # 添加一個按鈕以CSV格式下載合併後的數據
    csv = combined_data.to_csv(index=False, encoding='utf-8-sig').encode('utf-8-sig')
    st.download_button(
        label="下載CSV檔案",
        data=csv,
        file_name=f'{search_keyword}_combined_data.csv',
        mime='text/csv'
    )
    
    end_time = time.time()
    st.write(f"執行時間: {end_time - start_time:.2f} 秒")

    # Pytrends 分析
    pytrend = TrendReq(hl="zh-TW", tz=-480)
    keywords = [search_keyword] # 使用列表形式
    pytrend.build_payload(
        kw_list=keywords,
        cat=3,
        timeframe=f"{start_date} {end_date}",
        geo="TW",
        gprop=""
    )
    
    df = pytrend.interest_over_time()
    if "isPartial" in df.columns:
        df = df.drop(["isPartial"], axis=1)
    
    # 繪製趨勢數據
    fig, ax = plt.subplots(figsize=(12, 8), dpi=80)
    ax.plot(df.index, df[keywords[0]], label=keywords[0], lw=3.0, marker='o', markersize=8, color='#4285F4', linestyle='-')
    
    ax.set_title("Interest Over Time for " + search_keyword, fontsize=20, fontweight='bold', color='#4285F4')
    ax.set_xlabel("時間", fontsize=14, fontweight='bold', color='#4285F4')
    ax.set_ylabel("熱搜度", fontsize=14, fontweight='bold', color='#4285F4')
    ax.legend()
    ax.grid(True, linestyle='--', alpha=0.6)

    # 移除軸線
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    # 自訂刻度顏色
    ax.tick_params(axis='x', colors='#4285F4')
    ax.tick_params(axis='y', colors='#4285F4')

    # 自訂圖例
    legend = ax.legend()
    legend.get_frame().set_alpha(0.5)
    legend.get_lines()[0].set_linestyle('-')

    # 顯示圖表
    plt.tight_layout()
    st.pyplot(fig)

    # 輸出統計數據
    st.write(df.describe())