Глядя на исходный код страницы:
<td class="cntBoxGreyLnk" rowspan="2" valign="top">
<script type="text/javascript" src="http://www.oil-price.net/COMMODITIES/gen.php?lang=en"></script>
<noscript> To get live <a href="http://www.oil-price.net/dashboard.php?lang=en#COMMODITIES">gold, oil and commodity price</a>, please enable Javascript.</noscript>
данные, которые вы хотите динамически загружается на страницу; вы не можете получить его с помощью BeautifulSoup, потому что не существует в HTML.
Если вы посмотрите на связанный URL сценария на http://www.oil-price.net/COMMODITIES/gen.php?lang=en вы увидите кучу JavaScript, как
document.writeln('<table summary=\"Crude oil and commodity prices (c) http://oil-price.net\" style=\"font-family: Lucida Sans Unicode, Lucida Grande, Sans-Serif; font-size: 12px; background: #fff; border-collapse: collapse; text-align: left; border-color: #6678b1; border-width: 1px 1px 1px 1px; border-style: solid;\">');
document.writeln('<thead>');
/* ... */
document.writeln('<tr>');
document.writeln('<td style=\"font-size: 12px; font-weight: bold; border-bottom: 1px solid #ccc; color: #1869bd; padding: 2px 6px; white-space: nowrap;\">');
document.writeln('<a href=\"http://oil-price.net/dashboard.php?lang=en#COMMODITIES\" style=\"color: #1869bd; text-decoration:none\">Heating Oil<\/a>');
document.writeln('<\/td>');
document.writeln('<td style=\"font-size: 12px; font-weight: normal; border-bottom: 1px solid #ccc; color: #000000; padding: 2px 6px; white-space: nowrap;\">');
document.writeln('3.05');
document.writeln('<\/td>');
document.writeln('<td style=\"font-size: 12px; font-weight: normal; border-bottom: 1px solid #ccc; color: green; padding: 2px 6px; white-space: nowrap;\">');
document.writeln('+1.81%');
document.writeln('<\/td><\/tr>');
При загрузке страницы, этот браузер запуска и динамически записывает в значениях, которые вы ищете. (В стороне: это совершенно архаичный, оскорбленный и, как правило, ужасный способ делать вещи, я могу только предположить, что кто-то думает об этом как о дополнительном уровне безопасности. Они заслуживают наказания за их несчастье!).
Теперь этот код довольно прямолинейный; вы могли бы, вероятно, захватить html-данные с регулярным выражением. Но (а) есть некоторые escape-коды, которые могут вызвать проблемы, (б) нет никакой гарантии, что они не могут запутать свой код в будущем, и (c) где это забавно?
PyV8 module обеспечивает прямолинейный способ выполнения кода javascript из Python и даже позволяет нам писать код Python, вызываемый javascript! Мы будем воспользоваться этим, чтобы получить данные в не obfuscatable образом:
import PyV8
import requests
from bs4 import BeautifulSoup
SCRIPT = "http://www.oil-price.net/COMMODITIES/gen.php?lang=en"
class Document:
def __init__(self):
self.lines = []
def writeln(self, s):
self.lines.append(s)
@property
def content(self):
return '\n'.join(self.lines)
class DOM(PyV8.JSClass):
def __init__(self):
self.document = Document()
def main():
# Create a javascript context which contains
# a document object having a writeln method.
# This allows us to capture the calls to document.writeln()
dom = DOM()
ctxt = PyV8.JSContext(dom)
ctxt.enter()
# Grab the javascript and execute it
js = requests.get(SCRIPT).content
ctxt.eval(js)
# The result is the HTML code you are looking for
html = dom.document.content
# html is now "<table> ... </table>" containing the data you are after;
# you can go ahead and finish parsing it with BeautifulSoup
tbl = BeautifulSoup(html)
for row in tbl.findAll('tr'):
print('/'.join(td.text.strip() for td in row.findAll('td')))
if __name__ == "__main__":
main()
Это приводит к:
Crude Oil/99.88/+2.04%
Natural Gas/4.78/-3.27%
Gasoline/2.75/+2.40%
Heating Oil/3.05/+1.81%
Gold/1263.30/+0.45%
Silver/19.92/+0.06%
Copper/3.27/+0.37%
, который данные, которые вы хотели.
Редактировать: Я больше не могу опустить его; это мертвый минимальный код, который выполняет эту работу. Но, может быть, я могу лучше объяснить, как это работает (это действительно не так страшно, как кажется!):
Модуль PyV8 обертывает переводчик Javascript Google V8 таким образом, что Python может взаимодействовать с ним.Вам нужно будет перейти на https://code.google.com/p/pyv8/downloads/list, чтобы загрузить и установить соответствующую версию, прежде чем вы сможете запустить мой код.
Язык javascript сам по себе не знает ничего о том, как взаимодействовать с внешним миром; он не имеет встроенных методов ввода или вывода. Это не очень полезно. Чтобы решить эту проблему, мы можем перейти в «контекстный объект», который содержит информацию о внешнем мире и как взаимодействовать с ним. Когда javascript запускается в веб-браузере, он получает объект контекста, который предоставляет все виды информации о браузере и текущей веб-странице и о том, как с ними взаимодействовать.
Код javascript от http://www.oil-price.net/COMMODITIES/gen.php?lang=en предполагает, что он будет запущен в браузере, где контекст имеет объект «документ», представляющий веб-страницу с методом «writeln», который добавляет текст в текущий конец веб-страницы стр. Когда страница загружается, скрипт загружается и запускается; он записывает текст (который, как раз, является действительным HTML) на страницу; это становится отображаемым как часть страницы, заканчивая как таблица товаров, которую вы хотели. Вы не можете получить таблицу с BeautifulSoup, потому что таблица не существует до запуска javascript, а BeautifulSoup не загружает и не запускает javascript.
Мы хотим запустить javascript; для этого нам нужен фальшивый контекст браузера, который имеет объект «document» с методом «writeln». Затем нам нужно сохранить информацию, которая передается в «writeln», и нам нужен способ вернуть ее, когда скрипт закончен. Мой класс DOM - это поддельный контекст браузера; при создании экземпляра (т. е. когда мы делаем один из них), он дает объект Document, называемый документом, который имеет метод writeln. Когда вызывается document.writeln, он добавляет строку текста в document.lines, и в любое время мы можем вызвать document.content, чтобы вернуть весь текст, написанный до сих пор.
Теперь: действие! В основной функции мы создаем фальшивый контекст браузера, устанавливаем его как текущий контекст интерпретатора и запускаем интерпретатор. Мы захватим код javascript и попросим интерпретатора оценить (т.е. запустить) его. (Обфускация исходного кода, которая может испортить статический анализ, не повлияет на нас, потому что код должен выдавать хороший результат при запуске, и мы фактически запускаем его!) Как только код будет закончен, мы получим окончательный вывод из документа .context; это таблица html, которую вы не смогли получить. Мы передаем это обратно в BeautifulSoup, чтобы вытащить данные, а затем распечатать данные.
Надеюсь, что это поможет!
«Но есть одна колонка в одной из строк, которую я не могу найти» Какой столбец, какая строка? –
@KaranGoel: включен URL, и я смог воспроизвести проблему. –
Возможный дубликат [Недостающие детали на результатах Beautiful Soup] (http://stackoverflow.com/questions/18614305/missing-parts-on-beautiful-soup-results) –