【问题标题】:How to scrape through Single page Application websites in python using bs4如何使用 bs4 在 python 中抓取单页应用程序网站
【发布时间】:2019-07-16 17:52:57
【问题描述】:

我正在通过 NBA 网站获取球员姓名。玩家姓名网页是使用单页应用程序设计的。播放器按字母顺序分布在多个页面中。我无法提取所有玩家的名字。 这是链接:https://in.global.nba.com/playerindex/

from selenium import webdriver
from bs4 import BeautifulSoup

class make():
    def __init__(self):
        self.first=""
        self.last=""

driver= webdriver.PhantomJS(executable_path=r'E:\Downloads\Compressed\phantomjs-2.1.1-windows\bin\phantomjs.exe')

driver.get('https://in.global.nba.com/playerindex/')

html_doc = driver.page_source


soup = BeautifulSoup(html_doc,'lxml')

names = []

layer = soup.find_all("a",class_="player-name ng-isolate-scope")
for a in layer:
    span = a.find("span",class_="ng-binding")
    thing = make()
    thing.first = span.text
    spans = a.find("span",class_="ng-binding").find_next_sibling()
    thing.last = spans.text
    names.append(thing)

【问题讨论】:

    标签: python web-scraping beautifulsoup


    【解决方案1】:

    在处理 SPA 时,您不应该尝试从 DOM 中提取信息,因为如果没有运行支持 JS 的浏览器来填充数据,DOM 是不完整的。打开页面源,你会看到页面 HTML 没有你需要的数据。

    但大多数 SPA 使用 XHR 请求加载数据。您可以在开发者控制台 (F12) 中监控网络请求,以查看在页面加载期间发出的请求。

    这里https://in.global.nba.com/playerindex/https://in.global.nba.com/stats2/league/playerlist.json?locale=en加载玩家列表

    自己模拟该请求,然后选择您需要的任何内容。检查请求标头以确定您需要随请求发送的内容。

    import requests
    
    if __name__ == '__main__':
        page_url = 'https://in.global.nba.com/playerindex/'
        s = requests.Session()
        s.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'}
    
        # visit the homepage to populate session with necessary cookies
        res = s.get(page_url)
        res.raise_for_status()
    
        json_url = 'https://in.global.nba.com/stats2/league/playerlist.json?locale=en'
        res = s.get(json_url)
        res.raise_for_status()
        data = res.json()
    
        player_names = [p['playerProfile']['displayName'] for p in data['payload']['players']]
        print(player_names)
    

    输出:

    ['Steven Adams', 'Bam Adebayo', 'Deng Adel', 'LaMarcus Aldridge', 'Kyle Alexander', 'Nickeil Alexander-Walker', ...
    

    处理身份验证

    需要注意的一点是,某些网站需要授权令牌才能随请求一起发送。如果它存在,您可以在 API 请求中看到它。

    如果您正在构建一个需要长期(更)发挥作用的抓取工具,您可能希望通过从页面中提取令牌并将其包含在请求中来使脚本更加健壮。

    此令牌(主要是 JWT 令牌,以 ey... 开头)通常位于 HTML 中的某个位置,编码为 JSON。或者它作为 cookie 发送给客户端,浏览器将其附加到请求中,或者在标头中。简而言之,它可以在任何地方。扫描请求和响应以找出令牌的来源以及如何自己检索它。

    ...
    <script>
    const state = {"token": "ey......", ...};
    </script>
    
    import json
    import re
    
    res = requests.get('url/to/page')
    
    # extract the token from the page. Here `state` is an object serialized as JSON,
    # we take everything after `=` sign until the semicolon and deserialize it
    state = json.loads(re.search(r'const state = (.*);', res.text).group(1))
    token = state['token']
    
    res = requests.get('url/to/api/with/auth', headers={'authorization': f'Bearer {token}'})
    

    【讨论】:

    • 很好的解释 :-) +
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    相关资源
    最近更新 更多