雙十一購物攻略:如何利用爬蟲技術獲取歷史價格趨勢,理性購物不踩雷

努力的小雨發表於2024-11-12

雙十一購物狂歡節即將到來,作為程式設計師,利用爬蟲技術查詢商品的歷史價格趨勢,似乎是一個合理的需求,畢竟這只是為了自己參考,不涉及商業用途。然而,小夥伴們在進行爬蟲操作時一定要謹慎小心,尤其是在資料採集和使用的過程中,務必遵守相關法律法規與平臺的使用規範。

每次和大家講解爬蟲時,我總是提醒一句:“謹慎、謹慎、再謹慎!”不僅要避免觸犯法律,也要避免對網站的正常運營造成影響,保持理性和合規。

商品獲取

好的,我們的第一步是進入京東的查詢頁面,找到並開啟我們關注的商品頁面。例如,假設我最關注的是顯示卡的價格和相關資料,那麼接下來我就會去查詢顯示卡的具體資訊。透過這種方式,我們能夠獲取到顯示卡的相關商品資料。如圖:

image

你要做的工作是找到我們的商品資訊請求連線。這個連線可能不好找,所以你需要耐心地逐個檢視相關頁面。我已經幫你找到這個連線了,現在我們可以直接根據它開始編寫爬蟲指令碼,目標是從中提取商品連結。你可以透過右鍵點選請求,選擇“複製請求為Python程式碼”來直接獲取Python程式碼。

至於線上工具,市場上有很多類似的工具可以幫助你轉換請求,但我就不一一列舉了,你可以根據需求自行選擇合適的工具。

程式碼部分你可以自己編寫,我這裡只會提供一些關鍵部分的示例程式碼,幫助你更好地理解如何實現。以下是我為你整理的關鍵程式碼片段:

response = requests.get('https://api.m.jd.com/', params=params, cookies=cookies, headers=headers)
    # 使用BeautifulSoup解析HTML
    soup = BeautifulSoup(response.text, 'html.parser')

    # 查詢所有符合條件的div標籤
    div_tags = soup.find_all('div', class_='p-name p-name-type-2')

    # 迴圈遍歷每個div標籤,提取資訊
    for div_tag in div_tags:
        # 查詢 span 標籤中是否有 "自營" 標識
        self_operated_tag = div_tag.find('span', class_='p-tag')
        
        if self_operated_tag and '自營' in self_operated_tag.text:
            # 提取顯示卡名稱和連結
            a_tag = div_tag.find('a', href=True)
            product_name = a_tag.find('em').text.strip()
            
            # 處理相對路徑,拼接為完整的URL
            link = 'https:' + a_tag['href'] if a_tag['href'].startswith('//') else a_tag['href']
            store.append({
                'name': product_name,
                'link': link
            })
            # 列印結果
            print("名稱:", product_name)
            print("連結:", link)
        else:
            print("沒有找到自營標識或沒有相關資訊。")
    
    sort_data(store,keyword)
    
def sort_data(data,name):
    with open(name+'.csv','a',newline='',encoding='utf8')as f:
        writer=csv.writer(f)
        for i in data:
            writer.writerow((i['name'],i['link']))

這裡我們只關注自營商品,因為自營商品的品質相對有保障。為了避免頻繁爬取導致封號的風險,我將爬取到的資料儲存到了CSV檔案中,便於後續使用。畢竟,不建議頻繁地向同一網站發起請求,這樣很容易被封禁。

以下是我爬取的某一頁的資料示例。如果你需要獲取多個頁面的資料,只需調整相關引數即可,確保分頁功能正常工作。爬取的示例資料如下所示:

image

沒錯,我並沒有爬取商品的實時價格,因為我們這次的主要目標是獲取歷史價格資料。不過,在抓取歷史價格的同時,順便也爬取了商品的最新價格,這樣既能滿足需求,又不會浪費額外的爬取時間。因此,當前的程式碼已經覆蓋了這兩方面的內容。

接下來,我們可以轉到另一個網站,看看它的資料結構和爬取方式,以便進行比較和最佳化。

歷史價格爬取

在成功獲取完當前網站的資料後,我們將轉向爬取另一個網站的資料。首先,為了確保能夠順利抓取到所需的歷史價格資訊,我們需要在Web端進行一些初步的測試。透過手動操作和分析網路請求,我確認了能夠獲取歷史價格資料的請求介面。

經過一番測試和除錯後,我成功找到了正確的請求連線。接下來,我將展示這個連線,供大家參考。如下所示:

image

我們計劃逐步抓取每一個商品連結的歷史價格資訊,以確保資料的全面性和準確性。然而,在抓取過程中,我注意到請求的內容中包含了一個加密部分,這使得我們無法直接獲取到完整的價格資料。這一加密內容需要解密或進一步處理,才能確保我們能夠成功提取出歷史價格。

因此,在繼續抓取之前,我們需要先分析並處理這個加密機制。以下是加密部分的內容,供參考:

image

在這個請求過程中,使用的並不是商品的直接連結,而是一個經過加密處理的“code”引數。實際上,商品連結在上面的請求中已經經歷了一定的轉換處理,因此我們無需過於擔心這個轉換步驟,它只是多了一道處理環節而已,對資料獲取本身沒有實質性影響。

我們只需要按照指定的方式獲取這個“code”引數,並在後續請求中正確使用它即可。經過一系列分析和處理,最終的程式碼實現如下所示:

def get_history(itemid):
    #此處省略一堆程式碼
    params = {
        'ud': 'EAONJNRXWXSMTBKNNYL_1730899204',
        'reqid': '46db0db9f67129f31d1fca1f96ed4239',
        'checkCode': 'ada35e4f5d7c1c55403289ec49df69e3P9f1',
        'con': itemid,
    }

    data = {
        'checkCode': 'ada35e4f5d7c1c55403289ec49df69e3P9f1',
        'con': itemid,
    }

    response = requests.post('http://www.tool168.cn/dm/ptinfo.php', params=params, cookies=cookies, headers=headers, data=data, verify=False)
    
    #此處省略一堆程式碼

    code =   json.loads(response.text)
    params = {
        'code': code['code'],
        't': '',
        'ud': 'EAONJNRXWXSMTBKNNYL_1730899204',
        'reqid': '46db0db9f67129f31d1fca1f96ed4239',
    }

    response = requests.post('http://www.tool168.cn/dm/history.php', params=params, cookies=cookies, headers=headers, verify=False)
    # 正規表示式匹配Date.UTC中的日期和價格
    pattern = r"Date.UTC\((\d{4}),(\d{1,2}),(\d{1,2})\),([\d\.]+)"

    matches = re.findall(pattern, response.text)

    # 解析日期和價格
    prices = []
    for match in matches:
        year, month, day, price = match
        date = datetime(int(year), int(month) + 1, int(day))  # 月份是從0開始的,需要加1
        prices.append((date, float(price)))

    # 找出最低價格、最高價格和最新價格
    min_price = min(prices, key=lambda x: x[1])
    max_price = max(prices, key=lambda x: x[1])
    latest_price = prices[-1]

    # 列印結果
    print(f"最低價格: {min_price[1]},日期: {min_price[0].strftime('%Y-%m-%d')}")
    print(f"最高價格: {max_price[1]},日期: {max_price[0].strftime('%Y-%m-%d')}")
    print(f"最新價格: {latest_price[1]},日期: {latest_price[0].strftime('%Y-%m-%d')}")
    
get_history("https://item.jd.com/100061261651.html")    

最後,透過對獲取到的歷史價格資料進行分析,我們可以基於價格的波動趨勢做出合理的購買判斷!看下最終的效果:

image

剩下的工作就是對程式碼進行最佳化的過程了。在這個階段,我們的主要目標是展示一個基本的實現思路,並且驗證相關功能是否有效。實際上,我們並不打算爬取所有商品的詳細資訊,因為這不僅不符合我們的實際需求,而且在實際操作中也沒有必要。

總結

總的來說,爬蟲技術為我們提供了豐富的資料資源,但在使用過程中,謹慎行事,理性操作,才能真正讓爬蟲技術為我們的生活帶來便利,而不是帶來麻煩。希望大家在即將到來的雙十一購物狂歡節中,既能抓住機會購買心儀的商品,又能遵守道德與法律的底線,做一個負責任的技術使用者。


我是努力的小雨,一名 Java 服務端碼農,潛心研究著 AI 技術的奧秘。我熱愛技術交流與分享,對開源社群充滿熱情。同時也是一位騰訊雲創作之星、阿里雲專家博主、華為云云享專家、掘金優秀作者。

💡 我將不吝分享我在技術道路上的個人探索與經驗,希望能為你的學習與成長帶來一些啟發與幫助。

🌟 歡迎關注努力的小雨!🌟

相關文章