快轉到主要內容
  1. Posts/

將 Momo 短網址轉換為完整商品網址

·324 字·2 分鐘· loading · loading · ·
ADSFAaron
作者
ADSFAaron
目錄

在製作 電商歷史價格查詢 時,發現 momo 手機 app 分享商品網址會是一個短網址,這會導致無法查詢到對應的商品,因此有轉換為一般 momo 網址的需求,這篇文章就這麼誕生了。

推廣一下自己做的 電商歷史價格查詢,最主要是致敬 TWBuyer.info,覺得使用網址來查詢價格非常方便、直覺,但可惜網站不知道什麼原因下架了 🥲

先來稍微講解 momo 短網址的流程

graph LR;
A[短網址]-->B[接收_HTTP_301];
B-->C[完整商品網址]

什麼是 HTTP 301? 這邊簡單的介紹:

Status code 用途
301 Moved Permanently 表示請求的資源已被永久地移動到由 Location 標頭給出的 URL
302 Found 表示所請求的資源已暫時移動到由 Location 標頭給出的 URL
307 Temporary Redirect 與 302 回應相同,主要差異是用戶端不會更改重新導向請求的方法與主體。

舉例來說,使用 POST 傳遞資料時,302 會使舊版用戶端將方法改為 GET,而 307 不會。
308 Permanent Redirect 與 301 回應相同,主要差異是用戶端不會更改重新導向請求的方法與主體。

Ref: Mozilla Developer - HTTP Reference Status

Steps
#

首先,當然要有一台可以運行的主機(這什麼廢話 🫤

  • 已安裝 Python3、pip
  1. 安裝 requests 套件

    pip install requests
    
  2. 複製和稍微了解 Code

    載入剛剛安裝的套件和其他程式庫

    import requests
    from urllib.parse import urlparse, parse_qs
    

    來到主程式,這邊假設我要找的商品短網址是 https://momo.dm/fiaiym

    將短網址傳遞到 Function,最後輸出完整商品網址。

    if __name__ == "__main__":
    
        short_url = "https://momo.dm/fiaiym"
        destination_url = resolve_momo_short_url(short_url)
    
        parse_url = parse_momo_short_url(destination_url)
    
        if destination_url:
            print(f"The destination URL for {short_url} is: {destination_url}")
            print(f"Parsed goodsUrl: {parse_url}")
        else:
            print(f"Could not resolve {short_url}")
    

    當中的 Function resolve_momo_short_url(short_url) 用途是將短網址傳送一個要求,嘗試看看主機回傳什麼資料。

    這邊有一個需要注意的地方,allow_redirects 要設定為 False,否則你就被他導過去拉 🤣。

    如果有找到轉向的 Location,則回傳 Location URL。

    def resolve_momo_short_url(short_url:str):
    
        try:
            response = requests.get(short_url, allow_redirects=False)
    
            if response.status_code in [301, 302, 307, 308]:
                return response.headers['Location']
            else:
                print(
                    f"Unexpected status code: {response.status_code} for {short_url}")
                return None
    
        except requests.exceptions.RequestException as e:
            print(f"Error resolving {short_url}: {e}")
            return None
    

    若執行正常的話,回傳結果應該會類似這樣的樣式:

    {
        "statusCode": 301, 
        "location": "https://www.momoshop.com.tw/event/appRedirect.jsp?status=0&goodsUrl=https://m.momoshop.com.tw/goods.momo?i_code=12655371&simOrderYn=0"
    }
    

    可以看到 Requests 回傳確實有出現 location 和其他欄位。

    接著我們要處理這段 Redirected URL。

    parse_momo_short_url Function 的用途是將導向的 URL 提取出來。從回傳的 URL 可以看到當中其實是帶有許多的參數,而主要對我們有用的參數是 goodsUrl,因此透過 urlliburlparse,將網址中的資料進行分段。

    def parse_momo_short_url(destination_url):
    
        # 解析網址
        parsed_url = urlparse(destination_url)
    
        # 解析 query 部分為字典
        query_params = parse_qs(parsed_url.query)
    
        goodsUrl = query_params.get('goodsUrl', [""])[0]
    
        return goodsUrl
    

    整合起來的程式碼:

    import requests
    from urllib.parse import urlparse, parse_qs
    
    
    def resolve_momo_short_url(short_url):
    
        try:
            response = requests.get(short_url, allow_redirects=False)
    
            if response.status_code in [301, 302, 307, 308]:
                return response.headers['Location']
            else:
                print(
                    f"Unexpected status code: {response.status_code} for {short_url}")
                return None
    
        except requests.exceptions.RequestException as e:
            print(f"Error resolving {short_url}: {e}")
            return None
    
    
    def parse_momo_short_url(destination_url):
    
        # 解析網址
        parsed_url = urlparse(destination_url)
    
        # 解析 query 部分為字典
        query_params = parse_qs(parsed_url.query)
    
        goodsUrl = query_params.get('goodsUrl', [""])[0]
    
        return goodsUrl
    
    
    if __name__ == "__main__":
    
        short_url = "https://momo.dm/fiaiym"
        destination_url = resolve_momo_short_url(short_url)
    
        parse_url = parse_momo_short_url(destination_url)
    
        if destination_url:
            print(f"The destination URL for {short_url} is: {destination_url}")
            print(f"Parsed goodsUrl: {parse_url}")
        else:
            print(f"Could not resolve {short_url}")
    
  3. Save and Run

    將上方的 Code 儲存,這邊我存成 test-short-url-simple.py,你可以自定義名稱。

    並且在終端機執行

    python3 test-short-url-simple.py
    

    執行結果如下:

    execute_pic

Reference
#