go语言爬虫 - TapTap用户都喜欢些什么游戏

前面的废话

说到爬虫,首先想到的当然是python~ 它在机器学习、爬虫数据分析领域可谓是如日中天,十分热门。但我最近在学习go语言,所以就用go写了

TapTap社区

这是一个高品质的游戏分享社区,可以说是手机上的steam。上面的用户质量非常高,核心玩家多,看到他们那么用心的写那么多长评论,让我惊叹,所以这次打算拿它来爬取数据练练手,下面先看看成果

先看效果,这里的玩家,都喜欢玩啥类型游戏呀?

根据 下载榜 里游戏标签的词频统计出:

发现单机、二次元、MOBA、策略等标签比较突出

让我们加入玩家评分的权重,评分是根据数以万计的玩家打的分数来的,多个游戏相同标签会求平均值。

看看有什么变化?

词云完全不一样了呢,视觉错位、脑洞、哲理等标签的评分较高,这些才是玩家真实的喜好,为啥加入评分权重变化这么大呢,让我们看一下究竟是哪些游戏评分这么高!

原来是纪念碑谷、猿骑、艾希等游戏。而纪念碑谷(tag:视觉错位)的评分竟然达到了10分!!(7951条评价)

不过这款游戏也确实让我服气,连我妈妈、老婆她们不太玩游戏的,都很喜欢这款游戏呢~

那么下面就都把评分权重加进去,看看玩家心里的真实需求

接着分析新品榜

游戏名称(根据排名权重+评分权重)

看看我们分析出来的跟榜单上的有什么不一样?

可以看到,加入评分权重后,像《我叫MT4》、《王牌战争:代号英雄》这种虽然排名靠前,但是口碑很差的游戏,几乎在我们的分析图上就看不见啦。(所以在taptap上,就算你花钱刷榜上去了,也并没有太多用,玩家的眼睛是雪亮的,哈哈哈)

预约榜

游戏名称(根据排名权重+评分权重)

这里可以看出未来市场的玩家需求,《全职觉醒》、《堡垒之夜》等都是期待比较高的

热玩榜

游戏名称(根据排名权重+评分权重)

《绝地求生、刺激战场》也是突出游戏之一,看来taptap的玩家,也是很喜欢吃鸡的

实现方式

goquery解析html

iconv-go进行编码转换

sego用来中文分词

wordart实现词云效果

现在先做了个简单的版本,完整版是还想实现抓取某个游戏的玩家评论,进行分词,情感分析的。

先分析html结构,找到一个游戏信息里包含哪些html元素,然后用goquery解析

使用谷歌浏览器,按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 main

import (
    "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 []GameInfo
var 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作为我的主语言进行开发

接下来研究下爬取网易云音乐~ 嘿嘿嘿

原文地址:https://www.cnblogs.com/lijiajia/p/9388356.html

时间: 2024-10-06 23:16:29

go语言爬虫 - TapTap用户都喜欢些什么游戏的相关文章

CSDN数据库被爆 统计CSDN用户都喜欢哪些密码

今天有黑客在网上公开了知名网站CSDN的用户数据库,这是一次严重的暴库泄密事件,涉及到的账户总量高达600万个.有人写了一个小程序,统计了这次公布的 6428632 个 CSDN 哪些密码出镜率较高?统计结果显示有239万人的密码和别人存在重复,在所有密码中,123456789出镜率高居榜首,有23万5千人使用它作为密码. 重复次数 密码 百分比 501 qwerasdf (0.0124073903469017) 504 computer (0.012481686097482) 519 zxcz

后端程序员都做些什么?

后端程序员都做些什么? 2017-12-25 刘欣 程序猿 来自:码农翻身(微信号:coderising) 这个问题来自于QQ网友,一句两句说不清楚,索性写个文章. 我刚开始做Web开发的时候,根本没有前端,后端之说. 原因很简单,那个时候服务器端的代码就是一切:接受浏览器的请求,实现业务逻辑,访问数据库,用JSP生成HTML,然后发送给浏览器. 即使后来Javascript在浏览器中添加了一些AJAX的效果,那也是锦上添花,绝对不敢造次.因为页面的HTML主要还是用所谓"套模板"的方

(转)通天塔导游讲述C,C++,Lisp,Java,Perl,(我们在亚马逊用到的所有语言),Ruby (我就是喜欢),和Python

https://code.google.com/archive/p/windows-config/wikis/TourDeBabel.wiki 通天塔导游 (译注:圣经记载:在远古的时候,人类都使用一种语言,全世界的人决定一起造一座通天的塔,就是巴别塔,后来被上帝知道了,上帝就让人们使用不同的语言,这个塔就没能造起来. 巴别塔不建自毁,与其说上帝的分化将人类的语言复杂化,不如说是人类自身心灵和谐不再的分崩离析.之所以后来有了翻译,不仅是为了加强人类之间的交流,更寄达了一种愿望,希望能以此消除人际

看看iOS和安卓用户都对什么感兴趣

www.ithome.com:看看iOS和安卓用户都对什么感兴趣 移动,现在已经成为主流计算平台了,而在整个"移动战场"上,平台之战最重要的主角无疑就是iOS和Android两大系统.安卓系统赢得了群众,这主要归功于他们设备成本较低,便于普及:而苹果公司则赢得了高质量的消费者.现在的问题是,如何精确的总结归纳,才能让我们更好地去分析移动用户. Gravity研究显示,iOS用户对于媒体和消费者平台更感兴趣,比如这些人对Kindle Fire的感兴趣程度是平均水平的25.03倍,而对So

用户为什么喜欢氟碳铝单板

氟碳铝单板是装饰材料行业的宠儿,在铝单板行业非常走俏.用户为什么会在铝单板产品中更加喜欢氟碳铝单板呢?这是市场舆论的导向吗?其实主要是有以下几点组成. 一.色彩多样,工艺好.氟碳铝单板都是先加工后进行喷漆的工艺,它们不管是平面还是弧形都是非常精细的.这些正是用户常常会注意到的问题,也往往是用户动心的地方. 二.氟碳铝单板的重量很轻,它的刚性非常好,强度又非常高.这对于用户来说简直是捡到宝了.它给人的感觉一点都不累赘,也不厚重,材料的上乘更是让它变得非常高大上,用户不喜欢它又会喜欢什么呢? 三.耐

R语言爬虫初尝试-基于RVEST包学习

R语言爬虫初尝试-基于RVEST包学习 Thursday, February 26, 2015 在学完coursera的getting and Cleaning data后,继续学习用R弄爬虫网络爬虫.主要用的还是Hadley Wickham开发的rvest包.再次给这位矜矜业业开发各种好用的R包的大神奉上膝盖 查阅资料如下: rvest的github rvest自身的帮助文档 rvest + CSS Selector 网页数据抓取的最佳选择-戴申: 里面有提及如何快速获得html的位置.看完这

互联网公司为什么都喜欢加班

1,压力,难听点儿说是恐惧:2,责任感,难听点叫虚荣心互联网这个行业是……此处请参考职业大牛分析文章若干,结果就是任何产品,别人想要模仿你都很容易,大公司要踩你就更容易了.那么公司老板唯一可做的是什么呢? 快!快速上线,快速改进,快速更新换代.从另外一个方面来说,这个行业还处于快速发展期,技术,产品,用户都在成长期.也就是说企业的外部环境日新月异,企业要么跟上变化,要么被变化抛弃,继而被他人超越超过.这是这个行业里就算BAT也会有如虎在侧的危机感的大背景.我最爱说的还有更大的背景,就是国内形势.

30+程序员,平时都忙些什么事情?平时都想些什么?以后有啥计划?

很多人都说,30岁以后了,写程序还有前途嘛?我有时候也迷茫,但是迷茫过后,总会给自己寻找方向,每个人都需要有个信念.没有信念,活着就没意思,无聊,觉得没奔头了. 废话少说,我来说说,我平时工作都忙些什么? 01. 我比较喜欢技术,但是技术又不是很厉害,但是我有的是时间可以深入学习新技术,例如,我平时会学习 WF, WCF, WPF, Silverlight 等技术,还会安排年轻的同事一起学习提高,人都需要不断的提高,否则很容易落后. 02. 我会看一些书,每过一年半载会逛一趟书店,狂买一些,平时

在中国使用苹果Mac电脑的都是些什么人?

来源:PConline 资讯 文章收录于:风云社区(提供上千款各类Mac软件下载) (图片来源于互联网分享,如涉及版权问题请联系作者删除) 在中国用Mac的都是什么人?腾讯CDC用户研究中心对 QQ for Mac 用户调查发现,发现主要是男性,30岁以下,高学历,高收入,主要从事设计或IT业.Macbook pro是最受青睐的机型,他们中85%还有其他苹果产品,看图吧…… 男多女少 在这次调查的数据中,有 75.68% 的男性用户使用 Mac 电脑,而女性则占 24.32%. 20 - 30岁