BeautifulSoup возвращает неверный текст

Я пытаюсь очистить сайт ниже, чтобы играть в теннис. Когда матч заканчивается над элементами, которые я исправляю, и я могу получить оценку, но во время матча, когда я ищу соответствующий класс "span", где счет сохраняется, я возвращаю класс, но оценка пуста (см. Ниже )

http://www.scoreboard.com/game/6LeqhPJd/#game-summary

score = score.findAll('span',attrs={'class':'scoreboard'})

выход:

[<span class="scoreboard">-</span>, <span class="scoreboard">-</span>]

ожидаемый выход

[<span class="scoreboard">1</span>, <span class="scoreboard">0</span>]

Используя firebug, я могу видеть оценку в этих полях, однако я не могу ее вернуть. Кто-нибудь знает, почему это произойдет..?

ПРИМЕЧАНИЕ. Когда совпадение в указанном выше URL-адресе закончено, элемент для оценки изменяется. Это только проблема для матчей LIVE...

+2
источник поделиться
1 ответ

Веб-страница использует JavaScript. Если вы загружаете URL-адрес с помощью urllib, JavaScript не выполняется. Так что большая часть HTML, которую вы видите в браузере, не генерируется.

Один из способов выполнения JavaScript - использовать Selenium. Другой способ - использовать PyQt4:

import sys
from PyQt4 import QtWebKit
from PyQt4 import QtCore
from PyQt4 import QtGui

class Render(QtWebKit.QWebPage):
    def __init__(self, url):
        self.app = QtGui.QApplication(sys.argv)
        QtWebKit.QWebPage.__init__(self)
        self.loadFinished.connect(self._loadFinished)
        self.mainFrame().load(QtCore.QUrl(url))
        self.app.exec_()

    def _loadFinished(self, result):
        self.frame = self.mainFrame()
        self.app.quit()

url = 'http://www.scoreboard.com/game/6LeqhPJd/#game-summary'
r = Render(url)
content = unicode(r.frame.toHtml())

Как только у вас есть content (после выполнения JavaScript), вы можете проанализировать его с помощью парсера HTML (например, BeautifulSoup или lxml).

Например, используя lxml:

import lxml.html as LH

def clean(text):
    return text.replace(u'\xa0', u'')

doc = LH.fromstring(content)   
result = []
for tr in doc.xpath('//tr[td[@class="left summary-horizontal"]]'):
    row = []
    for elt in tr.xpath('td'):
        row.append(clean(elt.text_content()))
    result.append(u', '.join(row[1:]))
print(u'\n'.join(result))

дает

Chardy J. (Fra), 2, 6, 77, , , , 
Zeballos H. (Arg), 0, 4, 63, , , , 

Используя Selenium и PhantomJS ( так что браузер GUI не появляется), вот как выглядит эквивалентный код:

import selenium.webdriver as webdriver
import contextlib
import os
import lxml.html as LH

# define path to the phantomjs binary
phantomjs = os.path.expanduser('~/bin/phantomjs')
url = 'http://www.scoreboard.com/game/6LeqhPJd/#game-summary'
with contextlib.closing(webdriver.PhantomJS(phantomjs)) as driver:
    driver.get(url)
    content = driver.page_source
    doc = LH.fromstring(content)   
    result = []
    for tr in doc.xpath('//tr[td[@class="left summary-horizontal"]]'):
        row = []
        for elt in tr.xpath('td'):
            row.append(elt.text_content())
        result.append(u', '.join(row[1:]))
    print(u'\n'.join(result))

Как решение Selenium/PhantomJS, так и решение PyQt4 занимают примерно такое же количество времени для запуска.

+6
источник

Посмотрите другие вопросы по меткам или Задайте вопрос