2011-12-15 2 views
0

Я понимаю, что регулярное выражение - это подход бедного человека к работе с beautifulsoup, но мне было интересно, является ли это моим единственным вариантом, если в html-файле я не пытаюсь разобрать теги с четкими тегами?Beautifulsoup parse через плохие теги

Я в конечном счете, просто пытаюсь получить некоторые простые данные из HTML ... но это только в серии таблиц, которые выглядят так:

<table width="733" border="0" cellpadding="2"> 
<tr> 
<td align="right" valign="top" nowrap="nowrap" bgcolor="#29ff36"> 
<font size="-1" face="Verdana, Arial, Helvetica, sans-serif"> 
<strong> 
PART CODE: 
</strong> 
</font> 
</td> 
<td align="left" valign="top" nowrap="nowrap"> 
<font size="-1" color="#7b1010" face="Verdana, Arial, Helvetica, sans-serif"> 
PART# (//THIS IS WHAT I WANT) 
</font> 
</td> 
<td> 
</td> 

есть хороший способ приблизиться к этому без регулярное выражение?

Спасибо за помощь, ребята. Этот сайт является невероятно

OK:

Там про 15 из этих таблиц, каждая из них имеет метку (например, стоимость, Vendor, On-Hand), который сидит в первой ячейке, а затем данные, которые я на самом деле want всегда находится в следующей ячейке.

label = 'Price:' 
rows = soup.findAll('tr') 
for tr in rows: 
    cols = tr.findAll('td') 
    for td in cols: 
    if td.find(text=True) == label: 
     print td.find(text=True) 

Это работает достаточно хорошо, чтобы найти правильную ячейку с ярлыком в нем ... Я в основном просто нужно найти следующую ячейку над теперь я думаю. «Следующая» команда в документации beautifulsoup на самом деле не справляется с этим. Любые мысли?

+1

Да, вы можете использовать 'BeautifulSoup'. Но я не подозреваю, что это тот ответ, который вы хотите. Вы можете немного уточнить вопрос? –

+0

Что уникально в данных, которые вы хотите? Всегда ли это во второй ячейке первой строки таблицы? Каждый раз текст начинается с определенного текста? Невозможно сказать BeautifulSoup или любому другому парсеру HTML, какие данные извлекать без такой информации. – Acorn

+0

BeautifulSoup позволяет получить набор таблиц и набор строк для каждой таблицы в нескольких строках кода. Получение «ЧАСТИ № (// ЭТО, ЧТО Я ХОЧУ)» тоже довольно легко. Предоставьте некоторый образец, который вызывает проблему. – Kirill

ответ

0

пример вы предоставили не совсем понятно, но вот фрагмент кода, который будет получать часть # из вашего примера источник HTML:

columns = soup.findAll('td') 
for col in columns: 
    try: 
     part = col.find("font", {"color": "#7b1010"}).contents[0] 
     print(part) 
    except: 
     pass 
+0

Это потрясающе. Спасибо –

+0

Думаю, что я просто сохранил это в списке, а затем вытащил данные из стандартного списка. Единственная проблема заключается в том, что каждый раз приходится различное количество таблиц ... т.е. иногда часть # находится в части [5] , иногда это частично [9] Есть ли способ, которым я могу специально искать «PART CODE:», а затем запустить этот код? Любые советы о том, как это сделать. –

+0

@Jen Scott. Трюк состоит в том, чтобы определить наименьший возможный раздел страницы, который будет содержать все необходимые данные для правильного анализа. В этом случае я бы предложил сделать soup.findAll() на элементах страницы tr, затем rows.findAll() для каждого tr, чтобы получить столбцы. Если оба параметра PART CODE и PART # присутствуют в строке, вы знаете, чтобы сохранить данные. – Condiment

-1

Люди lxml утверждают, что хорошо работают с искаженным HTML.

2

Вы также можете сделать это с помощью lxml вместо beautifulsoup. Я переключился на использование lxml.html вместо beautifulsoup из-за метода cssselect(). Он принимает правила css точно так же, как вы использовали бы в файле css или jQuery.

from lxml.html import fromstring 

raw_html_data = """ ... your html data here ... """ 

doc = fromstring(raw_html_data) 
part_number = doc.cssselect('td[align=left] font')[0].text 
# part_number.strip() # optionally strip leading and trailing whitespace 

Вы можете использовать pip установить lxml.

$ pip install lxml 

Серебро решение блюдо:

# ... starting with doc from above 
info = [] 
target_trs = doc.cssselect('table tr') # tweak based on actual html 
for tr in trs: 
    target_cells = tr.cssselect('td font') 
    label = target_cells[0].text.strip() 
    data = target_cells[1].text.strip() 
    info.append((label,data)) 
# now you have an array of (label,data) pairs in info 
+0

Это не работает. Я предполагаю, что trs должен быть target_trs, но я все еще получаю ошибку атрибута: у объекта nonetype нет атрибута 'strip', который запускает это. –

+0

Да, опечатка ... s/target-trs/trs /. Играйте с этим в консоли (консоль python или консоль браузера с javascript), чтобы все было правильно. Вам действительно нужно просто начать играть с этим материалом, и вы узнаете все, что вам нужно, чтобы понять вещи, используя либо beautifulsoup, либо lxml. Ваша проблема с NoneType звучит так, как ваш html не отформатирован на 100% последовательно или, возможно, вам нужно попробовать что-то еще, чтобы выбрать конечные ячейки-мишени.Повторите тест с меньшим фрагментом html, чтобы убедиться, что он работает, а затем проверьте весь html страницы. Удачи. – istruble