2013-02-21 3 views
0

Я в ситуации, когда мне нужно что-то сделать с хакетом. Входящие данные не под моим контролем, поэтому решение НЕ «просто сохраняет его более эффективно», насколько мне бы хотелось, чтобы это было так.Обработка таблицы BeautifulSoup

Вещи, которые я получаю как выглядит

<table> 
    <tr> 
    <td>Key 1</td> 
    <td>Key 2</td> 
    <td>Key 3</td> 
    ... 
    </tr> 
    <tr> 
    <td>Val 1</td> 
    <td>Val 2</td> 
    <td>Val 3</td> 
    ... 
    </tr> 
    ... 
</table> 

и то, что я хочу, чтобы вишневого выбрать некоторые пары ключ/значение из определенных таблиц. Так, что-то вроде

{ 'Key 4': 'Val 4', 'Key 32': 'Val 32' ... } 

Я знаю, что соответствующие ключи раньше времени, но я не обязательно знать, где они расположены, или что каждая пара tr с представляет к/V пар (table s привыкаешь для позиционирования, а также для представления данных. Нет, я не знаю почему.), поэтому наиболее простым решением является get me the contents of the nth cell of the next row where n is this cells' index.

Что у меня есть

def findField(soup, fieldName): 
    kTd = soup.find(text=fieldName).parent 
    ix = len(kTd.findPreviousSiblings('td')) 
    valTd = kTd.parent.findNext('tr').findAll('td')[ix] 
    return (kTd, valTd) 

def fieldsToDict(soup, fieldNames): 
    return dict([findField(soup, k) for k in fieldNames]) 

fieldsToDict(soup, ['Key 4', 'Key 32' ..]) 

, но кажется, что там должно быть более изящным и/или эффективный способ выразить это.

Любые мысли?

EDIT: Я буду более конкретным, хотя я могу переоценить это, и этот вопрос, вероятно, должен был быть помещен в codereview.se, а не в SO. Две конкретные вещи, на которые я хотел обратить внимание, у кого-то, у кого больше Python/BeautifulSoup, чем у меня.

Во-первых,

... 
    ix = len(soup.findPreviousSiblings('td')) 
... 

выглядит, как он мог бы получить, чтобы быть относительно дорогим для больших строк. И похоже, что информация, которую я пытаюсь получить, может быть получена во время начального разбора HTML. Есть ли встроенный метод/слот по линиям indexAmongPeers?

Второй

... 
    return dict([findField(soup, k) for k in fieldNames]) 

dict в этой строке кажется, что это придется сделать еще один обход списка, выходящего из этого понимания. Это оптимизируется в этом случае? Есть ли способ сделать это за один проход?

+0

Это выглядит довольно хорошо для меня. – icktoofay

+0

Да, у вас уже все хорошо. – deadfoxygrandpa

ответ

0

Я думаю, глядя вверх немного трудно следовать - я бы пойти на следующее:

rows = [tr.strings for tr in soup('tr')] 
lookup = {k:v for k,v in zip(*rows) if k in {'Key 1', 'Key 2'}} 
# {u'Key 1': u'Val 1', u'Key 2': u'Val 2'} 
+0

Это может работать для отдельных строк, но, как я сказал, не каждая пара 'tr' представляет пары k/v (некоторые содержат подтаблицы и нерелевантную информацию). Отмеченный фрагмент был одной конкретной подкатегорией, присутствующей в 'супе', и я даже не хочу все это. Если бы данные, которые я получал, использовали только для представления данных, тогда да, я просто 'izip' попал' tr' и вытащил бы оттуда. – Inaimathi

Смежные вопросы