这次我们准备爬取 HTC VIVE 的VR内容平台——Viveport,上面有 1406 款优质的 VR 游戏/应用,本次我们的目标就是把这些游戏的详细信息爬取下来。


首先我们去该网站看一下(www.viveport.com),网站的主页长这样。

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

点击 VIVEPORT 一栏,左侧选择 全部 ,我们可以发现 1406 款游戏全部在这里(我们待会爬虫就会从这里开始爬)。

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

点击游戏/应用的图片链接,可以进入到游戏/应用的详细介绍页面。

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

通过对网站页面的简单了解,我们可以得知,在该平台上共有1406款VR应用,在游戏列表界面,有每款游戏的名称,作者/公司,评分和价格;在详细信息界面,有关于游戏的运行截图/视频,详细介绍,以及硬件设备支持等。


这个作为练手项目,主要以在实战中巩固知识熟练技能为目标,所以在爬取过程中,不会面面俱到将全部信息爬下来,而是仅选取一些关键信息如:游戏名称作者评分价格,以及玩法详细介绍,这些信息爬下来,意思一下就好了(因为这些原理都是一样的)。话不多说,开始分析。

1. 首先分析 URL

网站上这 1406 款 VR 应用,采用翻页的形式,分成了 79 页,每页展示 18 款应用,翻页时,URL 会随之改变。

第一页:www.viveport.com/list/deskto…

第二页:www.viveport.com/list/deskto…

第三页:www.viveport.com/list/deskto…

第四页:www.viveport.com/list/deskto…

第五页:www.viveport.com/list/deskto…

……

发现什么规律了吗?

我们发现虽然 URL 很长,而且还有些不太一样,但是有一个值是一直在有规律的变化着,那就是 “from=”。

我们以第二页的 URL 作为模板,修改其 “from = ” 的值,看有什么发现?

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

我们可以发现,from值不同,展示的应用也不同,翻页的原理就是通过from每次增加18(因为每页展示18个)直到最后。

2. 分析页面源码

按快捷键 F12 ,可以调出开发者工具,方便我们查看网页源码。

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

通过这个工具,我们可以很快定位到关键信息的所在位置。大概结构如下(为了直观展示,做了一定改动)

<ul class="Listing " ...>
    <li class="Listing-item" ...>
        <a href="/apps/b5ea62db-9aea-484e-99b8-91ef1c138423" ...>
        <div class="Listing-item-info" ...>
            <span class="title" ...>与你在一起VR</span>
            <p class="Listing-item-author" ...>Aurora Games</p>
            <div class="Listing-item-bottom" ...>
                <span class="review-rating-number" ...>5.0</span>
                <p class="Listing-item-price" ...><span>会员限定</span></p>
            </div>
        </div>
    </li>
    <li class="Listing-item" ...> ... </li>
    <li class="Listing-item" ...> ... </li>
    <li class="Listing-item" ...> ... </li>
    ......
</ul>

由于路径较为复杂,所以我发现用class 属性来获取标签是一个较为方便的选择。

3. 游戏详细信息页面

然后我们再分析游戏的详细信息页面,尝试分析 “游戏介绍” 所在位置。访问 a 标签中的链接,获取页面内容后发现,游戏详细介绍就在网页的 meta 标签的 content 属性里(name = "description"

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

所以,游戏详细信息的问题也解决啦。

4. 开始编写爬虫程序

有了前面的准备工作,我们可以开始编写爬虫程序,正式爬取网页啦。我们先爬第一页,试试效果。

import requests
import bs4
def fetchURL(url):
    '''
    功能:访问 url 的网页,获取网页内容并返回
    参数:
        url :目标网页的 url
    返回:目标网页的 html 内容
    '''
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
    }
    try:
        r = requests.get(url,headers=headers)
        r.raise_for_status()
        return r.text
    except requests.HTTPError as e:
        print(e)
    except requests.RequestException as e:
        print(e)
    except:
        print("Unknown Error !")
def parserHtml(html):
    '''
    功能:根据参数 html 给定的内存型 HTML 文件,尝试解析其结构,获取所需内容
    参数:
            html:类似文件的内存 HTML 文本对象
    '''
    bsobj = bs4.BeautifulSoup(html,'html.parser')
    tr = bsobj.find(class_ = 'Listing')
    if isinstance(tr, bs4.element.Tag):
        for li in tr('li'):
            # 获取基本信息
            href = li.a['href']
            title = li.find(class_ = 'title')
            author = li.find(class_ = 'Listing-item-author')
            print(title.string + ' : ' + author.string)
            link = 'https://www.viveport.com' + href 
            html = fetchURL(link)
            print(link)
            # 获取详细信息
            try:
                bs = bs4.BeautifulSoup(html,'html.parser')
                previews = bs.find(attrs={'name':'description'})['content']
                print(previews)
            except:
                print('this webpage error')
            print('---'*20)
if __name__ == '__main__':
    url = 'https://www.viveport.com/list/desktop?contentType=desktop&category=-1&categoryGenus=-1&price=all&sort=99&from=0'
    parserHtml(fetchURL(url))
    print('Page has been saved!')

部分运行结果如下:

TOGETHER VR : Aurora Games
https://www.viveport.com/apps/b5ea62db-9aea-484e-99b8-91ef1c138423
I wanna throw darts with you.
I wanna play games with you.
I wanna act vulnerable with you all the time however late it is.
I wanna be with you forever...
TOGETHER VR is a virtual reality experience that allows players to experience everyday life with Hoshihara Mei in their own private den.
The game offers players the opportunity to play different games with Mei and enjoy couple-like interaction. Players can also transform into digital warriors and engage in an exciting space battles. 
Features:
▪ Exquisite pictures and atmosphere, with rich real experience.
▪ Use the motion controllers to communicate and interact with her in a variety of ways.
▪ Fully experience immersive virtual reality with crouching or even lying prone.
▪ Dazzling special effects and life-or-death situations for you to challenge.
(also playable on Oculus Rift)
------------------------------------------------------------
Sairento VR Lite : Mixed Realms Pte Ltd
https://www.viveport.com/apps/e4fa9753-c234-41d9-9e8d-75134bcc5d0b
Experience the thrill of being a cyber ninja in VR. Wall runs, power slides, back flips, triple jumps, katanas, guns, shurikens, kunais, throwing glaives, arrows and more. Be the super bad ass you've always wanted to be in Sairento VR!
Since its launch, Sairento VR has been gaining fans worldwide with its unique locomotion system. It is the one game in VR that allows you to experience the iconic "bullet-time" scenes from The Matrix, blended with the slow-motion mayhem of the Max Payne game series, all while looking and feeling as badass as the Bride from Kill Bill. 
Sairento VR was designed to be easy to pick up, but tough to master. The more time you spend with Sairento VR, the better you will perform the moves in the game and the more you will be rewarded with the unparalleled feeling of being the action hero of a big budget move production. 
Although Sairento VR Lite is a 'slimmer' version of the hit cyber ninja game Sairento VR, it is still an awesome experience because you will still be able to leap 15 feet into the air, slow time down while you blast away at an enemy before landing to deliver a lethal strike with your katana on another. It is the same badassery you get in the full version - just with less levels, less weapons and without the multiplayer, endless and campaign modes.
And if you decide you love it, then consider buying the full game!
******
Note - Sairento VR Lite is a modified version of Sairento VR. The differences are described below.
The full game includes the following :
- Campaign mode (not in Lite)
- Endless modes (not in Lite)
- Cooperative and PVP modes (not in Lite)
- 12 different levels (6 in Lite)
- 16 different weapons (6 in Lite)
- 80+ legendary relics to discover (20 in Lite)
- Daily rewards (not in Lite)
- No level cap (Max level 20 in Lite)
(also playable on Oculus Rift)
------------------------------------------------------------

内容爬是爬到了,但是怎么感觉优点怪怪的,我们之前用浏览器看的时候,明明都是中文的,怎么到这里全是英文版了呢?难道是哪儿没设置好吗?

同样的 URL ,用浏览器打开默认是中文版,而用爬虫访问默认是英文版,为什么呢?带着这个问题,我又去浏览器 开发者选项中仔细翻看,果然让我发现了问题所在—— cookie

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息

虽然,cookie 里都是一堆类似于乱码的东西,但是我还是凭借自己薄弱的英语水平,勉强猜出几个参数的大概含义,如果没猜错的话,服务器应该就是根据 cookie 来自动调整网页的语言的。

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
    'cookie': 'csdataBid=922fec0d9fecf2df2cdae83fa17446258d67c83c04fc4605f7e222f7f293b5f9; csdataInit={; x-htc-user-country-code=CN; AWSELB=7773410D10A94E52F9D7AF6C9160CC7B23301281198F0B9581174B44999BC640CDC28A25FD949839DFF186326A65F0228CB92887BAF456BD6610C293D3E77C258C9DE138E4; csdataBid=922fec0d9fecf2df2cdae83fa17446258d67c83c04fc4605f7e222f7f293b5f9; csdataInit={; csdataCid=7f491367b4f8ee7cd98ebe36d46030e0; Hm_lvt_5d3da6ff3a7b79da4280f7882713a05d=1540626829,1540627526,1540628232,1540628340; _ga=GA1.2.487789027.1540628334; _gid=GA1.2.1566658088.1540628334; Hm_lvt_a78ff99e4ea84ee3cc6e59baaa3dc434=1540626830,1540627526,1540628232,1540628340; x-htc-session=75b211ca-4f90-3bf3-3b42-18d547be3e60; Hm_lpvt_5d3da6ff3a7b79da4280f7882713a05d=1540630678; Hm_lpvt_a78ff99e4ea84ee3cc6e59baaa3dc434=1540630679; lc=zh-CN; _gat=1'
}

果然,在 headers 中添加 cookie 之后,再次运行,结果变成中文了。

与你在一起VR : Aurora Games
https://www.viveport.com/apps/b5ea62db-9aea-484e-99b8-91ef1c138423
想要跟你一起射飞镖、
想要跟你一起玩游戏、
就算再晚,也想一直跟你撒娇,
想要一直一直,与你在一起...
与你在一起VR是一款VR模拟游戏,让玩家体验与星原 芽衣一起生活的点点滴滴,在专属的小窝里,与她创造甜蜜的回忆。
游戏中能与芽衣一起竞赛各种小游戏,享受情侣般的打情骂俏,更能一同化身太空战场上的电子战士,来一场精彩刺激的大对决。
特色:
▪ 精致的画面与氛围,丰富的真实体验。
▪ 用手把与她进行各式各样的交流与互动。
▪ 蹲下甚至趴下,充分体验VR沉浸的惊喜。
▪ 炫丽的特效与生死一瞬间的机关等你来挑战。
(Oculus Rift 相容內容)
------------------------------------------------------------
永恒战士VR: 觉醒 : Vanimals Games
https://www.viveport.com/apps/24c057f4-31c3-47cc-a2c9-1351c4062189
“永恒战士VR”系列是由北京威魔纪元(Vanimals Technology)原创开发,与美国Glu Mobile进行IP合作的硬核动作VR游戏系列。
2017年暑假《永恒战士VR:觉醒》双人协作版在Viveport 平台发布。威魔纪元选择大陆范围内主流线下渠道作为首发的战场,利用永恒战士系列几千万手游用户影响力的余威,旨在给国内线下市场打一支强心剂,将线下VR产业推向一个新的高度。除了布局体验店市场,威魔纪元还计划在2017年内把“永恒战士VR”系列的后续产品,陆续推向线上各大VR平台。
==== 更新局域网联机流程 ====
  1. 确保两台电脑处于同一局域网内
  2. 确保游戏启动时, 系统弹出的"是否允许连接网络"的窗口, 选择了"允许". (这时需要重启游戏, 此操作只需一次)
  3. 进入游戏后, 请不要两个人同时进入多人模式, 而是第一个人先进入, 看到武器选择后, 第二个人再进入
  4. 等两个人都出现在武器选择界面, 再开始打击面前的石像. 
此次《永恒战士VR:觉醒》 双人协作版可以给您呈现:
-  一场视觉盛宴:奇幻风格、次世代级的画面效果,满足各层次的玩家
-  AI充满挑战:栩栩如生的亡灵军团、飞行石像鬼、性感精英魅魔、史诗级的巨型牛头Boss!
-  经典的街机爽快感:见招拆招的战斗策略,刀光箭影的生死奋战,把你带回到那个感人的街机年代!
-  双英雄设定:猎人和战士,手持不同神兵,感受完全不同的战斗体验!
-  局域网双人协作模式:把你的后背和生死,交给你的战友,拿Boss的首级做团队的奖杯!
-  英雄不死 只负责耍帅:英雄会受伤,但不会倒下!请大胆地挑战高分,在英雄榜上碾压其他英雄!
-  绿色VR游戏:没有眩晕感、没有眩晕感、没有眩晕感!
想要体验这款场面血脉喷张、荡气回肠的VR游戏?请和您的朋友一起来激爽一下吧!
(Oculus Rift 相容內容)
------------------------------------------------------------

5. 完善程序细节

通过前面的分析和实践,我们确实可以成功获取到我们想要的数据,接下来,需要对程序进行最后的完善。

  1. 在主函数中,添加 for 循环,遍历所有的游戏页面
  2. 添加 writepage 函数,将获取到的数据保存在本地 csv 文件中。

此爬虫完整代码如下所示:

'''
这次我们准备爬一下 viveport 网站,将上面的游戏信息爬取下来。
'''
import time
import requests
import bs4
def fetchURL(url):
    '''
    功能:访问 url 的网页,获取网页内容并返回
    参数:
        url :目标网页的 url
    返回:目标网页的 html 内容
    '''
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        'cookie': 'csdataBid=922fec0d9fecf2df2cdae83fa17446258d67c83c04fc4605f7e222f7f293b5f9; csdataInit={; x-htc-user-country-code=CN; AWSELB=7773410D10A94E52F9D7AF6C9160CC7B23301281198F0B9581174B44999BC640CDC28A25FD949839DFF186326A65F0228CB92887BAF456BD6610C293D3E77C258C9DE138E4; csdataBid=922fec0d9fecf2df2cdae83fa17446258d67c83c04fc4605f7e222f7f293b5f9; csdataInit={; csdataCid=7f491367b4f8ee7cd98ebe36d46030e0; Hm_lvt_5d3da6ff3a7b79da4280f7882713a05d=1540626829,1540627526,1540628232,1540628340; _ga=GA1.2.487789027.1540628334; _gid=GA1.2.1566658088.1540628334; Hm_lvt_a78ff99e4ea84ee3cc6e59baaa3dc434=1540626830,1540627526,1540628232,1540628340; x-htc-session=75b211ca-4f90-3bf3-3b42-18d547be3e60; Hm_lpvt_5d3da6ff3a7b79da4280f7882713a05d=1540630678; Hm_lpvt_a78ff99e4ea84ee3cc6e59baaa3dc434=1540630679; lc=zh-CN; _gat=1'
    }
    try:
        r = requests.get(url,headers=headers)
        r.raise_for_status()
        #r.encoding = r.apparent_encoding
        return r.text
    except requests.HTTPError as e:
        print(e)
    except requests.RequestException as e:
        print(e)
    except:
        print("Unknown Error !")
def parserHtml(html, page):
    '''
    功能:根据参数 html 给定的内存型 HTML 文件,尝试解析其结构,获取所需内容
    参数:
            html:类似文件的内存 HTML 文本对象
            page:网页的页数,用于生成文件名
    '''
    bsobj = bs4.BeautifulSoup(html,'html.parser')
    # 获取表头信息
    tr = bsobj.find(class_ = 'Listing')
    filename = 'game/游戏列表_page' + i + '.csv'
    gamelist = []
    hlist = []
    blist = []
    hlist.append("游戏名称")
    hlist.append("作者/公司")
    hlist.append("网站网址")
    hlist.append("游戏介绍")
    gamelist.append(hlist)
    if isinstance(tr, bs4.element.Tag):
        for li in tr('li'):
            blist = []
            href = li.a['href']
            title = li.find(class_ = 'title')
            author = li.find(class_ = 'Listing-item-author')
            try:
                link = 'https://www.viveport.com' + href
                print(title.string + ' : ' + author.string)
                print(link)
                html = fetchURL(link)
                bs = bs4.BeautifulSoup(html,'html.parser')
                previews = bs.find(attrs={'name':'description'})['content']
                print(previews)
            except:
                print('this webpage error')
            blist.append(title.string)
            blist.append(author.string)
            blist.append(link)
            blist.append(previews)
            gamelist.append(blist)
            print('---'*20)
            # 由于没有使用代理,为了避免被服务器封ip,所以爬一个歇3秒
            time.sleep(3)
        writePage(gamelist,filename)
def writePage(urating, filename):
    '''
        Function : To write the content of html into a local file
        html : The response content
        filename : the local filename to be used stored the response
    '''
    print('To write html into a local file %s ...' % filename)
    import pandas as pd
    dataframe = pd.DataFrame(urating)
    dataframe.to_csv(filename, index=True, sep=',', header=False)
if __name__ == '__main__':
    for i in range(0, 79):
        pageindex = i*18
        url = 'https://www.viveport.com/list/desktop?contentType=desktop&category=-1&categoryGenus=-1&price=all&sort=99&from=' + str(pageindex)
        # writePage(fetchURL(url),'viveport_test.html')
        parserHtml(fetchURL(url), str(i))
        print('Page' + str(i) + ' has been saved!')
    print('Over!!!')

运行结果如下(有需要的同学可以点击下面的链接下载):

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息


如果文章中有哪里没有讲明白,或者讲解有误的地方,欢迎在评论区批评指正,或者扫描下面的二维码,加我微信,大家一起学习交流,共同进步。

Python爬虫实战:爬取 viveport 上 1406 款VR游戏信息