go語言爬蟲 - TapTap使用者都喜歡些什麼遊戲

來源:互聯網
上載者:User

標籤:代號   爬取   mes   mt4   names   https   成功   fun   ada   

前面的廢話

說到爬蟲,首先想到的當然是python~ 它在機器學習、爬蟲資料分析領域可謂是如日中天,十分熱門。但我最近在學習go語言,所以就用go寫了

TapTap社區

這是一個高品質的遊戲分享社區,可以說是手機上的steam。上面的使用者品質非常高,核心玩家多,看到他們那麼用心的寫那麼多長評論,讓我驚歎,所以這次打算拿它來爬取資料練練手,下面先看看成果

先看效果,這裡的玩家,都喜歡玩啥類型遊戲呀?

根據 下載榜 裡遊戲標籤的詞頻統計出:

發現單機、二次元、MOBA、策略等標籤比較突出

讓我們加入玩家評分的權重,評分是根據數以萬計的玩家打的分數來的,多個遊戲相同標籤會求平均值。
看看有什麼變化?

詞雲完全不一樣了呢,視覺錯位、腦洞、哲理等標籤的評分較高,這些才是玩家真實的喜好,為啥加入評分權重變化這麼大呢,讓我們看一下究竟是哪些遊戲評分這麼高!

原來是紀念碑穀、猿騎、艾希等遊戲。而紀念碑穀(tag:視覺錯位)的評分竟然達到了10分!!(7951條評價)

不過這款遊戲也確實讓我服氣,連我媽媽、老婆她們不太玩遊戲的,都很喜歡這款遊戲呢~


那麼下面就都把評分權重加進去,看看玩家心裡的真實需求

接著分析新品榜

遊戲名稱(根據排名權重+評分權重)

看看我們分析出來的跟榜單上的有什麼不一樣?

可以看到,加入評分權重後,像《我叫MT4》、《王牌戰爭:代號英雄》這種雖然排名靠前,但是口碑很差的遊戲,幾乎在我們的分析圖上就看不見啦。(所以在taptap上,就算你花錢刷榜上去了,也並沒有太多用,玩家的眼睛是雪亮的,哈哈哈)

預約榜


遊戲名稱(根據排名權重+評分權重)

這裡可以看出未來市場的玩家需求,《全職覺醒》、《堡壘之夜》等都是期待比較高的

熱玩榜

遊戲名稱(根據排名權重+評分權重)

《絕地求生、刺激戰場》也是突出遊戲之一,看來taptap的玩家,也是很喜歡吃雞的

實現方式

goquery解析html
iconv-go進行編碼轉換
sego用來中文分詞
wordart實現詞雲效果

現在先做了個簡單的版本,完整版是還想實現抓取某個遊戲的玩家評論,進行分詞,情感分析的。

先分析html結構,找到一個遊戲資訊裡包含哪些html元素,然後用goquery解析

使用Google瀏覽器,按F12可以很方便的找到元素哦

然後定義一個結構體,用來存放資料

type GameInfo struct {    Rank     int      //排名    TapTapID string   //遊戲ID    Name     string   //遊戲名    Company  string   //公司名    Score    float64  //遊戲評分    IconUrl  string   //表徵圖地址    Type     string   //遊戲類型    tags     []string //標籤}

分析單個遊戲資訊

//解析一個遊戲資訊func ParseGameInfoCell(selection *goquery.Selection) {    gameInfo := GameInfo{}    nameA := selection.Find(".card-middle-title ")    gameInfo.TapTapID = nameA.AttrOr("href", "")    gameInfo.TapTapID = gameInfo.TapTapID[strings.LastIndex(gameInfo.TapTapID, "/")+1:]    gameInfo.Name = nameA.Find("h4").Text()    gameInfo.Company = selection.Find(".card-middle-author").Find("a").Text()    score, _ := strconv.ParseFloat(selection.Find(".middle-footer-rating").Find("span").Text(), 64)    gameInfo.Score = score    gameInfo.IconUrl = selection.Find(".card-left-image").Find("img").AttrOr("src", "")    tempRank, _ := strconv.ParseInt(selection.Find(".top-card-order-text").Text(), 10, 32)    gameInfo.Rank = int(tempRank)    gameInfo.Type = selection.Find(".card-middle-footer").Find("a").Text()    tagsAList := selection.Find(".card-tags").Find("a")    tagsAList.Each(func(i int, selectionA *goquery.Selection) {        gameInfo.tags = append(gameInfo.tags, selectionA.Text())    })    GameInfoList = append(GameInfoList, gameInfo)    //fmt.Printf("%v\n", gameInfo)}

但是很快就遇到了問題,因為熱門排行榜的資料是分頁的,我們請求一次只能得到30條資料,於是我們找到了“更多”按鈕,發現裡面通過ajax非同步請求了一條連結擷取資料。

https://www.taptap.com/ajax/top/played?page=2&total=30

page就代表的頁數,根據熱門排行榜總數量150,每頁30條可以得出一共有5頁。這樣我們就可以迴圈5次去請求所有的資料了

func ReqRankPage(page int) {    res, err := http.Get("https://www.taptap.com/ajax/top/" + rankTypeName + "?page=" + strconv.Itoa(page))    if err != nil {        log.Fatal(err)    }    defer res.Body.Close()    if res.StatusCode != 200 {        log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)    }    jsonBs, err := ioutil.ReadAll(res.Body)    tPageJson := TPageJson{}    err = json.Unmarshal(jsonBs, &tPageJson)    if err != nil {        fmt.Println("解析json錯誤", err)    }    var htmlRead io.Reader = strings.NewReader(tPageJson.Data.Html)    doc, err := goquery.NewDocumentFromReader(htmlRead)    if err != nil {        log.Fatal(err)    }    doc.Find(".taptap-top-card").Each(func(i int, selection *goquery.Selection) {        ParseGameInfoCell(selection)    })}

全部代碼

package mainimport (    "bytes"    "encoding/json"    "fmt"    "github.com/PuerkitoBio/goquery"    "io"    "io/ioutil"    "log"    "net/http"    "strconv"    "strings"    "math")type TPageJson struct {    Success bool          `json:"success"`    Data    TPageDataJson `json:"data"`}type TPageDataJson struct {    Html string `json:"html"`    Next string `json:"next"`}type GameInfo struct {    Rank     int      //排名    TapTapID string   //遊戲ID    Name     string   //遊戲名    Company  string   //公司名    Score    float64  //遊戲評分    IconUrl  string   //表徵圖地址    Type     string   //遊戲類型    tags     []string //標籤}var GameInfoList []GameInfovar rankTypeName = "reserve"var rankTypes = []string{"download", "new", "reserve", "sell", "played"}func main() {    for _, typeName := range rankTypes {        GameInfoList = []GameInfo{}        rankTypeName = typeName        //每個熱門排行榜有5頁資料(根據總數150條,每頁30條得出)        for i := 1; i <= 5; i++ {            ReqRankPage(i)        }        //產生標籤詞典        GenerateTags()        GenerateGameNames()        fmt.Println("產生熱門排行榜:", rankTypeName, "完畢")    }}func GenerateGameNames() {    var tagsBuffer bytes.Buffer    tagsBuffer.WriteString("word;weight\n")    for _, gameInfo := range GameInfoList {        //weightSize := 150 - gameInfo.Rank //把排名的權值加上        //weightSize := int(math.Ceil(float64(150-gameInfo.Rank) * gameInfo.Score)) //把排名的權值加上        weightSize := int(math.Ceil(gameInfo.Score*100)) //把排名的權值加上        tagsBuffer.WriteString(gameInfo.Name)        tagsBuffer.WriteString(";")        tagsBuffer.WriteString(strconv.Itoa(weightSize))        tagsBuffer.WriteString("\n")    }    WriteFile(rankTypeName+"_names_score.csv", tagsBuffer.String())}func GenerateTags() {    tagsCountDic := make(map[string]int)    tagsScoreDic := make(map[string]float64)    var tagsBuffer bytes.Buffer    tagsBuffer.WriteString("word;weight;")    for _, gameInfo := range GameInfoList {        for _, tag := range gameInfo.tags {            tagsCountDic[tag]++            tagsScoreDic[tag] += gameInfo.Score*100        }    }    for key, value := range tagsCountDic {        tagsBuffer.WriteString(key)        tagsBuffer.WriteString(";")        //tagsBuffer.WriteString(strconv.Itoa( value))        tagsBuffer.WriteString(strconv.Itoa( int(tagsScoreDic[key]/float64(value))))        tagsBuffer.WriteString("\n")    }    WriteFile(rankTypeName+"_tags_score.csv", tagsBuffer.String())}func WriteFile(name, content string) {    data := []byte(content)    if ioutil.WriteFile(name, data, 0644) == nil {        fmt.Println("寫入檔案成功:", name)    }}func ReqRankPage(page int) {    res, err := http.Get("https://www.taptap.com/ajax/top/" + rankTypeName + "?page=" + strconv.Itoa(page))    if err != nil {        log.Fatal(err)    }    defer res.Body.Close()    if res.StatusCode != 200 {        log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)    }    jsonBs, err := ioutil.ReadAll(res.Body)    tPageJson := TPageJson{}    err = json.Unmarshal(jsonBs, &tPageJson)    if err != nil {        fmt.Println("解析json錯誤", err)    }    var htmlRead io.Reader = strings.NewReader(tPageJson.Data.Html)    doc, err := goquery.NewDocumentFromReader(htmlRead)    if err != nil {        log.Fatal(err)    }    doc.Find(".taptap-top-card").Each(func(i int, selection *goquery.Selection) {        ParseGameInfoCell(selection)    })}//解析一個遊戲資訊func ParseGameInfoCell(selection *goquery.Selection) {    gameInfo := GameInfo{}    nameA := selection.Find(".card-middle-title ")    gameInfo.TapTapID = nameA.AttrOr("href", "")    gameInfo.TapTapID = gameInfo.TapTapID[strings.LastIndex(gameInfo.TapTapID, "/")+1:]    gameInfo.Name = nameA.Find("h4").Text()    gameInfo.Company = selection.Find(".card-middle-author").Find("a").Text()    score, _ := strconv.ParseFloat(selection.Find(".middle-footer-rating").Find("span").Text(), 64)    gameInfo.Score = score    gameInfo.IconUrl = selection.Find(".card-left-image").Find("img").AttrOr("src", "")    tempRank, _ := strconv.ParseInt(selection.Find(".top-card-order-text").Text(), 10, 32)    gameInfo.Rank = int(tempRank)    gameInfo.Type = selection.Find(".card-middle-footer").Find("a").Text()    tagsAList := selection.Find(".card-tags").Find("a")    tagsAList.Each(func(i int, selectionA *goquery.Selection) {        gameInfo.tags = append(gameInfo.tags, selectionA.Text())    })    GameInfoList = append(GameInfoList, gameInfo)    //fmt.Printf("%v\n", gameInfo)}

這樣就可以把爬取下來的資料,寫成檔案,產生出一張張的詞雲進行分析啦

總結

第一次玩爬蟲,所以寫的不是很好,爬蟲還有很多技術,本文裡都沒有涉及。如防止反爬,帳號登陸等。寫這個也是想多寫一點go代碼,以後可能會把go作為我的主語言進行開發

接下來研究下爬取網易雲音樂~ 嘿嘿嘿

go語言爬蟲 - TapTap使用者都喜歡些什麼遊戲

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.