龙空技术网

从零开始设计一个Steam愿望单爬虫(一)

一屏乱码 50

前言:

当前姐妹们对“jquerysubs”都比较关切,姐妹们都需要分析一些“jquerysubs”的相关内容。那么小编同时在网上汇集了一些关于“jquerysubs””的相关知识,希望同学们能喜欢,小伙伴们一起来学习一下吧!

入坑Steam5年了,经历了几次促销,愿望单加到了1000左右,每次看愿望单都很迷茫,所以写一个爬虫帮助筛选游戏。

本项目开源,

首先我们要得到Steam的愿望单接口。

在浏览器访问steam的愿望单,按F12打开开发者控制台,切换到【网络】视图,可以看到加载所有的网络活动。

这么多网络请求大部分都是从CDN下载图片,对爬虫来说无关紧要,所以我们将筛选器设置为【XHR】,可以看到这些请求都非常有规律

看一下响应体,返回的是一个JSON对象,这就是我们需要的接口了

不难发现,这些请求只有一个【p】参数不一样,这个【p】应该就是页数的意思了,【p】的范围是0~9,接下来我们要找到这个值是在哪里定义的

因为这些请求都是通过jQuery异步请求的,所以大概率写在愿望单网页里。然后我找到了一个【g_nAdditionalPages】变量,它的值是10,刚好对应0~9。

Talk is cheap,show me the code,直接上代码

import requestsimport redef get_wishlish(steamid: int) -> dict:    url = f'{steamid}/#sort=order'    headers = {'Cookies': 'wants_mature_content=1;Steam_Language=schinese'}    resp = requests.get(url=url, headers=headers)    resp.encoding = 'utf-8'    html = resp.text    pattern = re.compile(r'nAdditionalPages\s=\s(\d+)')    matchobj = pattern.search(html)    count = int(matchobj.group(1))    wishlist = {}    for i in range(0, count):    url = f'{steamid}/wishlistdata/?p={i}'    resp = requests.get(url=url, headers=headers)    data = resp.json()    wishlist.update(data)    print(f'第 {i} 页')    return(wishlist)wishlist=get_wishlish(0)print(f'拉取完成,共 {len(wishlist)} 个游戏')

可以看到,已经获取到了愿望单中的每个游戏了。

加了一个筛选,去除没什么用的数据

def get_wishlish(steamid: int) -> dict:    url = f'{steamid}/#sort=order'    headers = {'Cookies': 'wants_mature_content=1;Steam_Language=schinese'}    resp = requests.get(url=url, headers=headers)    resp.encoding = 'utf-8'    html = resp.text    pattern = re.compile(r'nAdditionalPages\s=\s(\d+)')    matchobj = pattern.search(html)    count = int(matchobj.group(1))    wishlist = {}    for i in range(0, count):        url = f'{steamid}/wishlistdata/?p={i}'        resp = requests.get(url=url, headers=headers)        datajson = resp.json()        for key in datajson.keys():            data = datajson[key]            review_score = int(data.get('review_score', -1))            key = int(key)            wishlist[key] = {                'name': data.get('name', '【Error】'),                'picture': data.get('capsule', '#'),                'review_score': review_score,                'review_total': int(data.get('reviews_total', '0').replace(',', '')),                'review_percent': int(data.get('reviews_percent', 0)),                'release_date': int(data.get('release_date', 0)),                'subs': [s['id'] for s in data.get('subs', [])],                'free': data.get('is_free_game', False),                'type': data.get('type', 'Error'),                'priority': data.get('priority', 0),                'tags': data.get('tags', []),                'add_date': int(data.get('added', 0)),                'rank': int(data.get('rank', 0)),                'platform': (                    data.get('win', 0) == 1,                    data.get('mac', 0) == 1,                    data.get('linux', 0) == 1                )            }        print(f'第 {i} 页')    return(wishlist)

由于是同步访问,一共11个请求大概要花20秒的时间,所以接下来我们改造成异访问。

实现如下:

import asyncioimport refrom httpx import AsyncClientasync def get_wishlish(steamid: int) -> dict:    async with asyncio.Semaphore(5):  # 最大并发数        async with AsyncClient() as client:            client.cookies = {                'wants_mature_content': '1',                'Steam_Language': 'schinese'            }            count = await _get_page_count(client=client, steamid=steamid)            tasks = {                asyncio.create_task(_get_single_page(client=client, steamid=steamid, page=p)) for p in range(0, count)            }            await asyncio.wait(tasks)    wishlist = {}    for task in tasks:        wishlist.update(task.result())    return(wishlist)async def _get_page_count(client: AsyncClient, steamid: int) -> int:    url = f'{steamid}/#sort=order'    resp = await client.get(url=url)    pattern = re.compile(r'nAdditionalPages\s=\s(\d+)')    matchobj = pattern.search(resp.text)    count = int(matchobj.group(1))    return(count)async def _get_single_page(client: AsyncClient, steamid: int, page: int = 0) -> dict:    url = f'{steamid}/wishlistdata/?p={page}'    resp = await client.get(url=url)    datajson = resp.json()    wishlist = {}    for key in datajson.keys():        data = datajson[key]        key = int(key)        wishlist[key] = {            'name': data.get('name', '【Error】'),            'picture': data.get('capsule', '#'),            'review_score':         int(data.get('review_score', -1)),            'review_total': int(data.get('reviews_total', '0').replace(',', '')),            'review_percent': int(data.get('reviews_percent', 0)),            'release_date': int(data.get('release_date', 0)),            'subs': [s['id'] for s in data.get('subs', [])],            'free': data.get('is_free_game', False),            'type': data.get('type', 'Error'),            'priority': data.get('priority', 0),            'tags': data.get('tags', []),            'add_date': int(data.get('added', 0)),            'rank': int(data.get('rank', 0)),            'platform': (                data.get('win', 0) == 1,                data.get('mac', 0) == 1,                data.get('linux', 0) == 1            )        }    print(f'第 {page} 页')    return(wishlist)async def main():    wishlist = await get_wishlish('76561198181526215')    print(f'拉取完成,共 {len(wishlist)} 个游戏')    print('done')asyncio.run(main())

Python3.7才可以运行,需要安装httpx库,安装方法:

pip3 install httpx

使用异步访问运行速度大大加快了,而且得到的响应是乱序的,这是因为我们一次性发了多条请求,这些请求的返回时间有一定随机性,受到网络状况影响。

只有数据并没有什么用,下一章我们来设计一个数据分析模块

标签: #jquerysubs