【问题标题】:Getting html source when some html is generated by javascriptjavascript生成某些html时获取html源
【发布时间】:2014-06-10 12:32:16
【问题描述】:

我正在尝试从包含由 javascript 生成的 html 的网页中获取源代码。我目前的代码如下:

from selenium import webdriver
from bs4 import BeautifulSoup

case_url = "http://na.leagueoflegends.com/tribunal/en/case/5555631/#nogo"
try:
    browser = webdriver.Firefox()
    browser.get(case_url)
    url = browser.page_source
    print url
    browser.close
except:
    ...

soup=BeautifulSoup(url)
...extraction code that finds the right tags, but they are empty...

当我打印存储在 url 中的源时,它会打印通常的 HTML,但缺少生成的 html 信息。如何获得与按 f12 时相同的 HTML(但我更愿意以编程方式执行此操作)?

【问题讨论】:

    标签: python python-2.7 selenium html-parsing beautifulsoup


    【解决方案1】:

    除了上面 alexce 的回答之外,您的根本问题是您在 JavaScript 生成 HTML 之前就提取了它。 Selenium 会在浏览器加载后立即返回控制权,并且不会等待任何后加载 JavaScript 生成的 HTML。

    通过使用“find_elements”,您将自动等待元素出现(取决于实例化驱动程序时设置的超时)。

    如果您在“find_elements”之后调用 get“page_source”,那么您将看到完整的 HTML。

    我已经自动化了许多客户端动态生成的网页,并且只要您等待 HTML 被呈现,就没有问题。

    Alexce 说得对,不需要使用 BeautifulSoup,但我想明确一点,Selenium 完全能够自动化 JavaScript 生成的 HTML

    【讨论】:

    • 非常感谢您的澄清。
    【解决方案2】:

    在这种情况下,您实际上不需要使用BeautifulSoup 来解析html,就Locating Elements 而言,selenium 本身非常强大。

    您可以通过以下方式一一解析每个标签/游戏的内容:

    from selenium import webdriver
    
    case_url = "http://na.leagueoflegends.com/tribunal/en/case/5555631/#nogo"
    browser = webdriver.Firefox()
    browser.get(case_url)
    
    game_tabs = browser.find_elements_by_xpath('//a[contains(@id, "tab-")]')
    for index, tab in enumerate(game_tabs, start=1):
        tab.click()
        game = browser.find_element_by_id('game%d' % index)
        game_type = game.find_element_by_id('stat-type-fill').text
        game_length = game.find_element_by_id('stat-length-fill').text
        game_outcome = game.find_element_by_id('stat-outcome-fill').text
    
        game_chat = game.find_element_by_class_name('chat-log')
        enemy_chat = [msg.text for msg in game_chat.find_elements_by_class_name('enemy') if msg.text]
        ally_chat = [msg.text for msg in game_chat.find_elements_by_class_name('ally') if msg.text]
    
        print game_type, game_length, game_outcome
        print "Enemy chat: ", enemy_chat
        print "Ally chat: ", ally_chat
        print "------"
    

    打印:

    Classic 34:48 Loss
    Enemy chat:  [u'Akali [All] [00:01:38] lol', ... ]
    Ally chat:  [u'Gangplank [All] [00:00:12] anyone remember the april fools lee sin spotlight? lol', ... ]
    ------
    Dominion 19:22 Loss
    Enemy chat:  [u'Evelynn [All] [00:00:10] Our GP has a Ti-83', ... ]
    Ally chat:  [u'Miss Fortune [All] [00:00:18] arr ye wodden computer needs to walk the plank!', ... ]
    

    【讨论】:

    • 我基本上在阅读之前编写了代码以使用 selenium。为了摆脱 BeautifulSoup,需要进行大量的重构。 selenium 方法似乎也找不到 javascript 生成的元素。
    • @KyleGrage 好的,您可以分享链接或提供任何信息,以便其他人可以调试/测试问题吗?谢谢。
    • @KyleGrage 谢谢,你需要什么元素?
    • 这是我的汤代码game1_html = soup.find("div", {"id": "game1"}) ... game5_html = soup.find("div", {"id": "game5"}) #gameX_html is game_html in the next bit of code game_type = game_html.find("p", {"id": "stat-type-fill"}).string game_length = game_html.find("p", {"id": "stat-length-fill"}).string game_outcome = game_html.find("p", {"id": "stat-outcome-fill"}).string game_chat = game_html.find("table", {"class": "chat-log"}).string
    • 是的,这很有帮助。但是,我想我应该提到这一点。稍后,我将聊天分类为不同的类别(例如,我需要聊天中的 html 过滤器),例如,这是我的 `#Ally 聊天处理 achat_arr = game_chat.findAll("tr", {"class":" ally alliesFilter"}) aallchat_arr = game_chat.findAll("tr", {"class": "ally alliesFilter facesFilter"})`
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 2011-01-10
    相关资源
    最近更新 更多