Web 数据抓取:通过选择下拉菜单获取所有数据 python

Web Data scraping: getting all data by selecting drop down menus python

我正在尝试从 https://www.iplt20.com/teams/sunrisers-hyderabad/squad" 获取数据 但面临一个问题,尤其是下拉列表(“按年份过滤”)。

我能够在下拉列表中检索名称,即 2020、2019,。 ETC 但无法检索每个列表元素的数据。

当我们点击按年份筛选列表时,会出现一个下拉列表,然后在赛季(年份)上,球员会发生变化(我们会得到当年打过那个赛季的球员以及概括)。 我想按赛季获取每个球员的数据。 当我们点击下拉列表

时也没有创建新的 URL

我找不到任何解决方案。 使用以下 python 代码从下拉列表中检索 season/year 值。

Python代码

    squad_url= "https://www.iplt20.com/teams/sunrisers-hyderabad/squad"
    driver = webdriver.Chrome(executable_path=".\chromedriver.exe")
    driver.get(squad_url)
    html = driver.page_source
    soup2 = BeautifulSoup(''.join(html), 'html.parser')
    for llist in soup2.find_all("ul",class_="drop-down__dropdown-list"):
        for year in llist.find_all("li"):
            print(year.text)

html 下拉列表代码片段如下

<div class="large-squad-list__filter single-filter">
        <div class="stats-table__filter drop-down js-drop-down is-open">
            <div class="drop-down__clickzone js-dropdown-trigger" tabindex="0" role="button"></div>
            <div class="drop-down__label js-drop-down-label">Filter by Year</div>
            <div class="drop-down__current js-drop-down-current">2020</div>
            <ul class="drop-down__dropdown-list js-drop-down-options">
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2020">2020</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2019">2019</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2018">2018</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2017">2017</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2016">2016</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2015">2015</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2014">2014</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2013">2013</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2012">2012</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2011">2011</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2010">2010</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2009">2009</li>
                <li tabindex="0" role="button" class="drop-down__dropdown-list__option" data-option="ipl2008">2008</li>
            </ul>
        </div>
    </div>

这可能只是部分答案,但它确实得到了你想要的(统计数据)。

问题是,数据是JS动态加载的。但是,如果您查看流量(检查 Developer Tool -> Network),您会看到发送到 API.

的请求

您可以获取 url 并解析响应。

这正是代码的作用:

import requests


_ids = [18790, 10192, 7749, 5815, 3957, 2785, 2374, 605]


for _id in _ids:
    url = f"https://cricketapi.platform.iplt20.com/stats/" \
          f"players?teamIds=62&tournamentIds={_id}&scope=TOURNAMENT&pageSize=30"
    response = requests.get(url).json()
    print(f"Printing stats for {response['team']['fullName']}")
    for player in response['stats']['content']:
        print(f"{player['player']['fullName']} - {player['stats']}")

但是,我无法确定 tournamentIds 的来源。此外,没有 2013 年以后的数据。

示例输出(为简洁起见,仅部分输出):

Printing stats for Sunrisers Hyderabad
Yusuf Pathan - [{'matchType': 'AGG', 'battingStats': {'50s': 0, '100s': 0, 'inns': 8, 'm': 10, 'r': '40', 'b': 45, '4s': 1, '6s': 1, 'no': 5, 'hs': '16*', 'sr': '88.88', 'a': '13.33'}, 'bowlingStats': {'bbiw': 0, 'bbir': 0, 'bbmw': 0, 'bbmr': 0, '4w': 0, '5w': 0, '10w': 0, 'inns': 1, 'm': 10, 'b': 6, 'r': 8, 'wb': 0, 'nb': 0, 'd': 1, 'w': 0, '4s': 1, '6s': 0, 'maid': 0, 'wmaid': 0, 'ht': 0, 'a': '-', 'e': '8.00', 'sr': '-', 'o': '1.00'}, 'fieldingStats': {'c': 1, 'ro': 0, 's': 0, 'inns': 1, 'm': 10}}, {'matchType': 'IPLT20', 'battingStats': {'50s': 0, '100s': 0, 'inns': 8, 'm': 10, 'r': '40', 'b': 45, '4s': 1, '6s': 1, 'no': 5, 'hs': '16*', 'sr': '88.88', 'a': '13.33'}, 'bowlingStats': {'bbiw': 0, 'bbir': 0, 'bbmw': 0, 'bbmr': 0, '4w': 0, '5w': 0, '10w': 0, 'inns': 1, 'm': 10, 'b': 6, 'r': 8, 'wb': 0, 'nb': 0, 'd': 1, 'w': 0, '4s': 1, '6s': 0, 'maid': 0, 'wmaid': 0, 'ht': 0, 'a': '-', 'e': '8.00', 'sr': '-', 'o': '1.00'}, 'fieldingStats': {'c': 1, 'ro': 0, 's': 0, 'inns': 1, 'm': 10}},

经过一整天的努力,我做到了:

在代码中导入以下内容

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
from selenium.common.exceptions import WebDriverException

Python 下面的代码

    driver.execute_script("return arguments[0].scrollIntoView(true);", element)
    
    time.sleep(3)
    driver.execute_script("window.scrollBy(0, -100);")
    time.sleep(2)
    #above code ensures drop list is visible, otherwise we get errors of non clickable etc.

    element = driver.find_element_by_class_name("stats-table__filter")
    season_element = element.find_elements_by_tag_name("li")
    for season in season_element:
        action.move_to_element_with_offset(element,0,0).perform()
        element.click()
        action.move_to_element_with_offset(season,0,0).perform()
        time.sleep(2) 

        try:
            print("clicking:",season.text )
            season.click()
        except WebDriverException:
            print("Not clickable", season.text)
            break

以上逻辑只包含如何点击下拉列表的信息。 但是动态数据正在加载(我已经从 driver.page_source 输出中确认)

requests 库的问题是未加载动态数据。 但是用硒就可以轻松做到。

我添加了睡眠以确保滚动完成。 我在很多地方阅读而不是睡觉可以使用 WebDriverWait,但我无法让它们工作

我很确定可以有优化版本。 (如果找到请post这里)