溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何用Python爬取排行榜上的游戲打折信息

發(fā)布時間:2021-10-26 09:47:03 來源:億速云 閱讀:173 作者:柒染 欄目:大數(shù)據(jù)

如何用Python爬取排行榜上的游戲打折信息,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

前言

不知不覺,一年一度如火如荼的steam夏日促銷悄然開始了。每年通過大大小小的促銷,我的游戲庫里已經(jīng)堆積滿還未下載過的游戲。但所謂“買到就是賺到,G胖一定大虧”的想法日漸流行,指不定以后就靠它們發(fā)達(dá)了呢。

有時候滾動steam的排行榜看自己喜歡的游戲的時候,未免會被右邊的價格影響到。久而久之我發(fā)現(xiàn)我所不想買的游戲并不是因?yàn)樗缓猛?,而是它還沒打折。又或者有些心水未被別人挖掘,在排行榜隱秘的角落里自怨自艾,等待“把玩”它的人出現(xiàn)~

于是我簡單的用python爬取了steam排行榜前10000個游戲的信息,其中有游戲名,評價,價格,出版日期等,在更加簡潔的列表界面選取自己感興趣的游戲之時,也可以進(jìn)行進(jìn)一步的數(shù)據(jù)分析。

廢話不多說,趕緊開始,不然被我拖更到促銷結(jié)束了就蹭不到熱度了。(本來也沒有熱度)

如何用Python爬取排行榜上的游戲打折信息

開始爬取

先說說這次爬蟲選用數(shù)據(jù)的優(yōu)缺點(diǎn):

第一,我發(fā)現(xiàn)了steam在顯示排行榜列表的時候后臺會進(jìn)行一個查詢的申請,點(diǎn)開一看是一串json代碼,而且在python進(jìn)行request的時候不需要模擬瀏覽器進(jìn)行填“headers”表的操作。通過訪問而得到的json代碼大大簡化了循環(huán)復(fù)雜度,一次循環(huán)可以得到100個游戲信息。

第二,因?yàn)橹恍枰闅v所有json代碼,時間上可以比進(jìn)入每一個游戲鏈接更加短。

第三,但就因?yàn)闆]有進(jìn)入每個游戲的鏈接,所以像評論,簡介,開發(fā)商等信息就沒有爬取。但爬取游戲鏈接的爬蟲攻略網(wǎng)上也有很多,這里就不弄斧了。

首先,進(jìn)入官網(wǎng)的排行榜頁面,為了避免游戲DLC、bundle等影響后期操作的類型出現(xiàn),記得在右邊的過濾器里只勾選游戲類目。

通過后臺的XHR發(fā)現(xiàn),頁面每次刷新都只顯示前50個游戲,當(dāng)我們滾動頁面往下看時,網(wǎng)站會發(fā)送一個神秘代碼:

如何用Python爬取排行榜上的游戲打折信息

經(jīng)過觀察,我發(fā)現(xiàn)代碼會自動申請返回從start參數(shù)的數(shù)字開始,一共count參數(shù)的數(shù)字的游戲信息。比如,下面的圖顯示它申請了從第51個到100個總共50個游戲的信息。

雙擊上上圖的紅框鏈接,返回的頁面長這樣:

如何用Python爬取排行榜上的游戲打折信息

所謂json格式,其實(shí)就是在字典里夾字典或者列表,目前許多大數(shù)據(jù)都是這樣保存滴。所以在查詢的時候其實(shí)很方便,但是我在抽取信息的時候還是會用到正則表達(dá)式,因?yàn)闀奖愫芏唷?/p>

知道這些之后,剩下的就可以用python一個個有用信息抽取出來,組成一個新的Dataframe列表,以便之后保存為csv格式。

# 導(dǎo)入需要用到的庫
import requests
from bs4 import BeautifulSoup
import re
import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

我們嘗試用requests打開上面json頁面的鏈接,并用json load解析。

這里我更改了start和count 的參數(shù),比較方便對照原網(wǎng)頁來看信息是否一致。

url = 'https://store.steampowered.com/search/results/?query&start=0&count=100&dynamic_data=&sort_by=_ASC&category1=998&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'
content = requests.get(url).content
jsontext = json.loads(content)
soup = BeautifulSoup(jsontext['results_html'],'html.parser')

可以看看soup返回的結(jié)果,它顯示了json里邊'results_html'返回的東西,因?yàn)榍斑叺膬?nèi)容我們已經(jīng)不需要了,所有游戲信息都在這個鍵里邊。

接著我們回到那個json頁面看看我們想要的東西都藏在哪:

游戲名字藏在span的title class里:

如何用Python爬取排行榜上的游戲打折信息

listdate = soup.find_all('div', class_ ='col search_released responsive_secondrow')

同樣的,可以用上面的方法找到游戲的鏈接、ID,這里就不贅述了。

評分和打分人數(shù)藏在span標(biāo)簽里,如果用字典查找的話會比較麻煩,所以我們稍后使用正則表達(dá)式將它倆提取出來:

不幸運(yùn)的是,有些游戲因?yàn)檫€沒上架,所以沒有人評論,我們用正則表達(dá)式得到的信息是亂碼。所以我們用函數(shù)來防止出現(xiàn)亂碼的可能性:

def get_reviewscore(review):
    gamereview=[]
    for i in range(len(review)):    
        try:
            score = re.search('br>(\d\d)%',str(review[i]))[1]
        except:
            score = ''
        gamereview.append(score)
    return gamereview
###########################################
def get_reviewers(review):
    reviewers=[]
    for i in range(len(review)):
        try:
            ppl = (re.search('the\s(.*?)(\s)user',str(review[i]))[1])
        except:
            ppl = ''
        reviewers.append(ppl)
    return reviewers

如果看到這里的讀者覺得很輕松,那我便可以繼續(xù)往下述說,因?yàn)榕廊r格比評論更加麻煩。但僅限于麻煩,并沒有很高大上的操作;而我相信我并不是用聰明的方法爬取到想要的結(jié)果,因?yàn)閷τ谶@個體量的數(shù)據(jù)再優(yōu)化的代碼對于運(yùn)行時間來說相差不大。反正結(jié)果都一樣,管它呢。

其實(shí)要找物品的最終價格(即免費(fèi)游戲,打折后或未打折的游戲價格)非常簡單,因?yàn)樗筒卦谶@里:

如何用Python爬取排行榜上的游戲打折信息

默認(rèn)后邊兩位為小數(shù)點(diǎn)后兩位,所以我們直接把這串?dāng)?shù)字揪出來并除以100:

def get_finalprice(price):
    finalprice=[]
    for i in range(len(price)):
        pricelist = int(re.search('final(\W+?)(\d+)(\W)',str(price[i]))[2])/100
        finalprice.append(pricelist)
    return finalprice

但我們?nèi)绻拖胫浪脑瓋r,以便之后做分析該怎么辦呢?

先看一下steam排行榜上的價格有三種顯示方法:

第一種,帶有劃線價格的打折商品,在源代碼中長這樣:

如何用Python爬取排行榜上的游戲打折信息

第二種,免費(fèi)的:

頭疼的是,免費(fèi)的標(biāo)識也有變體:

如何用Python爬取排行榜上的游戲打折信息如何用Python爬取排行榜上的游戲打折信息

(連to的大小寫也有不一樣的……steam您用點(diǎn)心!)

不過Free還是老老實(shí)實(shí)在最前面,所以我們后邊只要找到Free就好啦。

第三種,原價顯示:

steam夏日促銷悄然開始,用Python爬取排行榜上的游戲打折信息

上面的圖片都是我在抽查的時候發(fā)現(xiàn)的規(guī)律與變形,為了避免后續(xù)幾千個游戲有“烏合之眾”,我在代碼里只查找這三種格式,如果有奇形怪狀的數(shù)據(jù)出現(xiàn),直接一棍子打成“空值”:

def get_price(price):
    oripricelist=[]
    for i in range(len(price)):
        try:
            oripricelist.append(price[i].find_all(class_="col search_price responsive_secondrow")[0].text)
        except:
            oripricelist.append(price[i].find_all(class_="col search_price discounted responsive_secondrow")[0].text)

    ori_price=[]
    for i in range(len(oripricelist)):
        try:
            search = re.search('Free',oripricelist[i])[0].replace('Free','0')
        except:
            if oripricelist[i]== '\n':
                search=''
            else:
                try:
                    search = re.search('HK.*?(\d+\.\d+)\D',oripricelist[i])[1]
                except:
                    search=''
        ori_price.append(search)
    return ori_price

定義完這些想要的數(shù)據(jù)之后,我們就開始跑循環(huán)了。

先把我們要的數(shù)據(jù)列命好名字:

def get_data(games=1000): 
    num_games = games
    gamename=[]
    gamereview=[]
    gamereviewers=[]
    gamerelease=[]
    oriprice=[]
    final_price=[]
    appid=[]
    website=[]

接著我們以每個鏈接查詢100個游戲的步伐開始跑循環(huán)并將里邊的信息找出來,錄入上面的列表里:

       page = np.arange(0,num_games,100)
    for num in page:
        url = 'https://store.steampowered.com/search/results/?query&start='+str(num)+'&count=100&dynamic_data=&sort_by=_ASC&category1=998&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'
        print('the {} iteration: Trying to connect...'.format((num/100)+1))
        content = requests.get(url).content
        jsontext = json.loads(content)
        soup = BeautifulSoup(jsontext['results_html'],'html.parser')
        name = soup.find_all('span',class_ ='title')
        review = soup.find_all('div', class_ ='col search_reviewscore responsive_secondrow')
        listdate = soup.find_all('div', class_ ='col search_released responsive_secondrow')
        price = soup.find_all('div', class_ = 'col search_price_discount_combined responsive_secondrow')
        href = soup.find_all(class_='search_result_row ds_collapse_flag')
        for i in name:
            gamename.append(i.text)
        getreview = get_reviewscore(review) 
        for i in getreview:
            gamereview.append(i)
        getreviewers = get_reviewers(review)
        for i in getreviewers:
            gamereviewers.append(i)
        for i in listdate:
            gamerelease.append(i.text)
        getprice = get_price(price)
        for i in getprice:
            oriprice.append(i)
        getfinalprice = get_finalprice(price)
        for i in getfinalprice:
            final_price.append(i)
        for i in range(len(href)):
            appid.append(eval(soup.find_all(class_='search_result_row ds_collapse_flag')[i].attrs['data-ds-appid']))
            website.append(soup.find_all(class_='search_result_row ds_collapse_flag')[i].attrs['href'])
        print('done')

我們在遍歷中每次訪問頁面、完成每次循環(huán)的時候都讓電腦打印一段字,以便出錯的時候能快速找出出錯的頁面。

接下來就將得到的數(shù)據(jù)塞進(jìn)一個數(shù)據(jù)表里:

    df = pd.DataFrame(data=[gamename,gamereview,gamereviewers,gamerelease,oriprice,final_price,appid,website]).T
    df.columns = ['name','review_score','reviewers','release_date','ori_price','final_price','id','link']
    return df

#呼叫我們的函數(shù):
df = get_data(10000) #這里的數(shù)字代表爬取10000個游戲

等待漫長的過程與欣賞成功的過程:

如何用Python爬取排行榜上的游戲打折信息

最后的數(shù)據(jù)集長這樣:

如何用Python爬取排行榜上的游戲打折信息

前1000個游戲里總共有3個這樣的錯誤:

實(shí)況足球2020 是demo版免費(fèi),而想體驗(yàn)完整游戲確實(shí)需要78港幣;

奇異人生1 是第一篇章免費(fèi),后邊的篇章需要23.8港幣。

這些代碼跑起來雖然快,但得到的信息依舊太少,如果要深入研究steam的數(shù)據(jù)還是需要有強(qiáng)大的耐心遍歷所有游戲鏈接吶。

這次的爬蟲經(jīng)歷其實(shí)也發(fā)現(xiàn)了steam一些錄入大數(shù)據(jù)庫的時候的小差錯,比如前面所提到的免費(fèi)標(biāo)識竟然有3種變體,但他們可能覺得問題不大。

關(guān)于如何用Python爬取排行榜上的游戲打折信息問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI