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

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


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

viveport 网站主页
VIVEPORT 网站主页

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

VIVEPORT 全部游戏

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

游戏详细信息

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


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

1. 首先分析 URL

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

第一页:https://www.viveport.com/list/desktop

第二页:https://www.viveport.com/list/desktop?contentType=desktop&category=-1&categoryGenus=-1&price=all&sort=99&from=18

第三页:https://www.viveport.com/list/desktop?contentType=desktop&from=36&size=18&sort=99&category=-1&categoryGenus=-1&price=all&showTrackerGames=false

第四页:https://www.viveport.com/list/desktop?contentType=desktop&from=54&size=18&sort=99&category=-1&categoryGenus=-1&price=all&showTrackerGames=false

第五页:https://www.viveport.com/list/desktop?contentType=desktop&from=72&size=18&sort=99&category=-1&categoryGenus=-1&price=all&showTrackerGames=false

......

发现什么规律了吗?

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

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

from=0时 展示应用1-18

 

from=9时 展示应用10-27

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

2. 分析页面源码 

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

使用开发者工具查看源码

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

<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’)

游戏详细介绍源码

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

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。

cookie

虽然,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!!!')

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

运行结果

 运行结果链接:(链接:https://pan.baidu.com/s/1QHWx0feQznO_gCI8LX2wEQ 提取码:u2tc)


经过了一个半小时的爬取,终于将 1406 款游戏的信息爬取完成,还是蛮开心的,很有成就感(虽然不知道爬它们下来有什么用)。不过在本次爬虫实践中还是存有一些遗憾和疑惑的,再次先记录下来,等将来想到解决办法之后再来解决。

1. 没有使用多线程和代理

本次爬取用了这么长时间,其实很大原因是由于我 “过于谨慎” ,担心被服务器封 IP ,而强行延长等待时间。如果使用了代理,以及多线程的技术,预计可以在 5 分钟内爬完。

2. 无法获取价格和评分信息

一开始爬取的时候,我是打算连价格和评分一块儿爬取的,结果处理请求返回的结果时发现,居然没有评分和价格数据,这就很奇怪了。

浏览器访问 可以正常显示价格和评分

 

爬虫返回结果 没有评分及价格数据

我猜测,评分和价格这些数据是在页面加载之后,再通过其他请求加载出来的。由于我刚入门爬虫,第一次接触这种情况,不知如何处理,故先做记录,暂不处理。如果有大佬知道如何解决,请不吝赐教。


这是我第一次独立爬虫实践,以学习为主,爬到的东西可能真没啥用,但是这不重要,重要的是解决问题的思路和方法。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页