【问题标题】:BeautifulSoup Not Returning Twitch.tv ViewcountBeautifulSoup 不返回 Twitch.tv 观看次数
【发布时间】:2019-03-11 21:35:14
【问题描述】:

我正在尝试使用 Python 在 www.twitch.tv/directory 上抓取观众。我已经尝试了基本的 BeautifulSoup 脚本:

url= 'https://www.twitch.tv/directory'
html= urlopen(url)
soup = BeautifulSoup(url, "html5lib") #also tried using html.parser, lxml
soup.prettify()

这给了我没有显示实际观众人数的 html。

然后我尝试使用参数 ajax 数据。 From this thread

param = {"action": "getcategory",
        "br": "f21",
        "category": "dress",
        "pageno": "",
        "pagesize": "",
        "sort": "",
        "fsize": "",
        "fcolor": "",
        "fprice": "",
        "fattr": ""}

url = "https://www.twitch.tv/directory"
# Also tried with the headers parameter headers={"User-Agent":"Mozilla/5.0...
js = requests.get(url,params=param).json()

但我收到 JSONDecodeError: Expecting value: line 1 column 1 (char 0) 错误。

从那时起我转向硒

driver = webdriver.Edge()
url = 'https://www.twitch.tv/directory'
driver.get(url)
#Also tried driver.execute_script("return document.documentElement.outerHTML") and innerHTML
html = driver.page_source
driver.close()
soup = BeautifulSoup(html, "lxml")

这些只是产生与标准 BeautifulSoup 调用相同的结果。

任何关于抓取观看次数的帮助将不胜感激。

【问题讨论】:

  • 我刚刚检查了页面并查看了源代码 - 似乎所有数据都是通过 javascript 获取的,那里没有“正常”的 HTML。因此,不可能从 HTML 中转义该数据,就像 BeatifulSoup 所做的那样——它们解析 HTML,它们也无法运行 Javascript。
  • @RobinZigmond 嗨罗宾。是否有其他方法可以获取我可以查看的这些数据?谢谢。
  • 恐怕我真的不知道,我不使用twitch。看来 twitch 有一个 API,正如我所期望的那样:dev.twitch.tv/api - 我想你可以从中获得你需要的信息,但我不知道如何使用它。
  • @RobinZigmond 我会调查的。它可能最终成为最简单的方法

标签: javascript python web-scraping beautifulsoup twitch


【解决方案1】:

第一次加载时页面中不存在统计信息。该页面向https://gql.twitch.tv/gql 发出graphql 请求以获取游戏数据。当用户未登录时,graphql 请求要求查询 AnonFrontPage_TopChannels

这是python中的一个工作请求:

import requests
import json

resp = requests.post(
    "https://gql.twitch.tv/gql",
    json.dumps(
        {
            "operationName": "AnonFrontPage_TopChannels",
            "variables": {"platformType": "all", "isTagsExperiment": True},
            "extensions": {
                "persistedQuery": {
                    "version": 1,
                    "sha256Hash": "d94b2fd8ad1d2c2ea82c187d65ebf3810144b4436fbf2a1dc3af0983d9bd69e9",
                }
            },
        }
    ),
    headers = {'Client-Id': 'kimne78kx3ncx6brgo4mv6wki5h1ko'},
)

print(json.loads(resp.content))

我在请求中包含了 Client-Id。 id 似乎不是会话唯一的,但我想 Twitch 会使它们过期,所以这可能不会永远有效。您必须检查未来的 graphql 请求并在未来获取一个新的 Client-Id,或者弄清楚如何以编程方式从页面中抓取一个。

此请求实际上似乎是热门直播频道部分。以下是获取观看次数和标题的方法:

edges = json.loads(resp.content)["data"]["streams"]["edges"]
games = [(f["node"]["title"], f["node"]["viewersCount"]) for f in edges]

# games:
[
    ("Let us GAME", 78250),
    ("(REBROADCAST) Worlds Play-In Knockouts: Cloud9 vs. Gambit Esports", 36783),
    ("RuneFest 2018 - OSRS Reveals !schedule", 35042),
    (None, 25237),
    ("Front Page of TWITCH + Fortnite FALL SKIRMISH Training!", 22380),
    ("Reckful - 3v3 with barry and a german", 20399),
]

您需要检查 chrome 网络检查器并找出其他请求的结构以获取更多数据。

以下是目录页面的示例:

import requests
import json

resp = requests.post(
    "https://gql.twitch.tv/gql",
    json.dumps(
        {
            "operationName": "BrowsePage_AllDirectories",
            "variables": {
                "limit": 30,
                "directoryFilters": ["GAMES"],
                "isTagsExperiment": True,
                "tags": [],
            },
            "extensions": {
                "persistedQuery": {
                    "version": 1,
                    "sha256Hash": "75fb8eaa6e61d995a4d679dcb78b0d5e485778d1384a6232cba301418923d6b7",
                }
            },
        }
    ),
    headers={"Client-Id": "kimne78kx3ncx6brgo4mv6wki5h1ko"},
)

edges = json.loads(resp.content)["data"]["directoriesWithTags"]["edges"]
games = [f["node"] for f in edges]

【讨论】:

  • 感谢您的快速回复!您将如何修改 operationName 以通过顶级游戏提供“twitch.tv/directory”视图?编辑:我知道我必须去找网络检查员
  • 非常感谢!这正是我想要的
猜你喜欢
  • 2015-07-25
  • 2015-01-02
  • 2015-01-10
  • 1970-01-01
  • 2013-05-30
  • 2020-09-28
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
相关资源
最近更新 更多