【问题标题】:Python scrape tablePython刮表
【发布时间】:2017-08-12 15:12:39
【问题描述】:

我是编程新手,所以我很可能做我想做的事情的想法完全不是这样做的方法。

我正在尝试从该站点上抓取排名表 - http://www.flashscore.com/hockey/finland/liiga/ - 现在如果我什至可以抓取带有团队名称的一列就可以了,所以我尝试找到带有“participant_name col_participant_name col_name”类的 td 标签" 但代码返回空括号:

import requests
from bs4 import BeautifulSoup
import lxml

def table(url):
    teams = []
    source = requests.get(url).content
    soup = BeautifulSoup(source, "lxml")
    for td in soup.find_all("td"):
        team = td.find_all("participant_name col_participant_name col_name")
        teams.append(team)
        print(teams)

table("http://www.flashscore.com/hockey/finland/liiga/")

我尝试使用 tr 标签检索整行,但也没有成功。

【问题讨论】:

    标签: python web-scraping beautifulsoup


    【解决方案1】:

    我认为这里的主要问题是您试图使用requests 抓取动态生成的内容,请注意页面的 HTML 源代码中根本没有 participant_name col_participant_name col_name 文本,这意味着这是使用生成的网站的 JavaScript。对于这项工作,您应该使用selenium 之类的东西以及ChromeDriver 或您发现更好的驱动程序,下面是使用上述两种工具的示例:

    from bs4 import BeautifulSoup
    from selenium import webdriver
    
    url = "http://www.flashscore.com/hockey/finland/liiga/"
    
    driver = webdriver.Chrome()
    driver.get(url)
    
    source = driver.page_source
    
    soup = BeautifulSoup(source, "lxml")
    elements = soup.findAll('td', {'class':"participant_name col_participant_name col_name"})
    

    我认为您的代码的另一个问题是您尝试访问标签的方式,如果您想匹配特定的 class 或任何其他特定属性,您可以使用 Python 的字典作为 @987654330 的参数来匹配@函数。

    现在我们可以使用elements 来查找所有团队的名称,尝试print(elements[0]) 并注意团队的名称在a 标记内,我们可以使用.a.text 访问它,如下所示:

    teams = []
    for item in elements:
        team = item.a.text
        print(team)
        teams.append(team)
    
    print(teams)
    

    teams 现在应该是所需的输出:

    >>> teams
    ['Assat', 'Hameenlinna', 'IFK Helsinki', 'Ilves', 'Jyvaskyla', 'KalPa', 'Lukko', 'Pelicans', 'SaiPa', 'Tappara', 'TPS Turku', 'Karpat', 'KooKoo', 'Vaasan Sport', 'Jukurit']
    

    teams 也可以使用 list comprehension 创建:

    teams = [item.a.text for item in elements]
    

    【讨论】:

    • 很高兴为您提供帮助!如果有帮助,请记住accept 答案,这对社区整体来说是一件好事。
    • 太棒了-谢谢。我现在正试图让它基于行工作,但是行没有一个共同的单一类,而是每个都有唯一的类,比如:odd glib-participant-I9wm5xTA,甚至 glib-participant-zV5a4drH 等等.有没有办法让下一行查找名称中具有特定字符串的类(在本例中为“glib-participant”)而不是全名? rows = soup.findAll('tr', {'class':"participant_name col_participant_name col_name"})
    • @SomeGuy 我猜你可以使用regex 表达式。 soup.findAll('tr', {'class':re.compile("your regex")})
    【解决方案2】:

    Aguiar 先生打败了我!我只想指出,你可以单独使用硒来完成这一切。当然,他指出这是动态加载其大部分内容的众多网站之一是正确的。

    您可能有兴趣观察我使用了 xpath 表达式。这些通常会以紧凑的方式表达您想要的内容。一旦习惯了它们就不会太难阅读。

    >>> from selenium import webdriver
    >>> driver = webdriver.Chrome()
    >>> driver.get('http://www.flashscore.com/hockey/finland/liiga/')
    >>> items = driver.find_elements_by_xpath('.//span[@class="team_name_span"]/a[text()]')
    >>> for item in items:
    ...     item.text
    ... 
    'Assat'
    'Hameenlinna'
    'IFK Helsinki'
    'Ilves'
    'Jyvaskyla'
    'KalPa'
    'Lukko'
    'Pelicans'
    'SaiPa'
    'Tappara'
    'TPS Turku'
    'Karpat'
    'KooKoo'
    'Vaasan Sport'
    'Jukurit'
    

    【讨论】:

    • 很高兴有一个单独基于selenium 的解决方案,+1 包括电池 解决方案!
    • @ViníciusAguiar:非常感谢。我很高兴看到您的回答被接受了。
    【解决方案3】:

    使用 css 选择器实现同样的效果,这将使您的代码更具可读性和简洁性:

    from selenium import webdriver; driver = webdriver.Chrome()
    
    driver.get('http://www.flashscore.com/hockey/finland/liiga/')
    for player_name in driver.find_elements_by_css_selector('.participant_name'):
        print(player_name.text)
    driver.quit()
    

    【讨论】:

      【解决方案4】:

      你很亲密。

      开始时不要那么雄心勃勃,只关注“participant_name”。看看https://www.crummy.com/software/BeautifulSoup/bs4/doc/#find-all。我想你想要这样的东西:

      for td in soup.find_all("td", "participant_name"):
      

      另外,您看到的网页内容肯定与我不同。在您的 URL 的 wget 之后,grep 在文本中根本找不到“participant_name”。您需要验证您的代码是否正在查找 HTML 文本中实际存在的 ID 或类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-29
        • 2020-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-11
        • 1970-01-01
        • 2017-11-11
        相关资源
        最近更新 更多