Как извлечь данные таблицы в парах, используя BeautifulSoup? - PullRequest
6 голосов
/ 15 ноября 2011

Мой образец данных:

<table id = "history">
<tr class = "printCol">
<td class="name">Google</td><td class="date">07/11/2001</td><td class="state">
<span>CA</span>
</td>
</tr>
<tr class = "printCol">
<td class="name">Apple</td><td class="date">27/08/2001</td>
</tr>
<tr class = "printCol">
<td class="name">Microsoft</td><td class="date">01/11/1991</td>
</tr>
</table>

код Beautifulsoup:

table = soup.find("table", id = "history")

rows = table.findAll('tr')
for tr in rows:
    cols = tr.findAll('td')
    for td in cols:
        print td.find(text=True)

Требуемый вывод для хранилища MySQL (список):

['Google|07/11/2001|CA', 'Apple|27/08/2001', 'Microsoft|01/11/1991']

Вывод у меня (сложно связать правильную дату с нужной компанией):

Google
07/11/2001


Apple
27/08/2001
Microsoft
01/11/1991

Я написал функцию для извлечения элементов из каждого tr , но я подумал, что есть гораздо более эффективный способ сделать все это в оригинальном цикле для . Я хочу сохранить их в виде пары данных. Мысли?

Ответы [ 2 ]

17 голосов
/ 15 ноября 2011

Понимание списка облегчит задачу:

table = soup.find("table", id = "history")
rows = table.findAll('tr')
data = [[td.findChildren(text=True) for td in tr.findAll("td")] for tr in rows]
# data now contains:
[[u'Google', u'07/11/2001'],
 [u'Apple', u'27/08/2001'],
 [u'Microsoft', u'01/11/1991']]

# If the data may contain extraneous whitespace you can clean it up
# Additional processing could also be done - but once you hit much more
# complex than this later maintainers, yourself included, will thank you
# for using a series of for loops that call clearly named functions to perform
# the work.
data = [[u"".join(d).strip() for d in l] for l in data]

# If you want to store it joined as name | company
# then simply follow that up with:
data = [u"|".join(d) for d in data]

Понимание списка в основном является обратным for циклом с агрегацией:

[[td.findNext(text=True) for td in tr.findAll("td")] for tr in rows]

переводится в *:

final_list = []
intermediate_list = []

for tr in rows:
    for td in tr.findAll("td")
        intermediate_list.append(td.findNext(text=True))

    final_list.append(intermediate_list)
    intermediate_list = []

data = final_list

* Грубо - мы не учитываем удивительность, связанную с генераторами , а не при создании промежуточных списков, поскольку я не могу сейчас добавить генераторы, не загромождая пример ,

2 голосов
/ 15 ноября 2011

Вот небольшой вариант ответа Шона, если вам нужно именно то, что вы написали в вопросе,

table = soup.find("table", id = "history")

rows = table.findAll('tr')

data = ['|'.join([td.findNext(text=True) for td in tr.findAll("td")]) for tr in rows]
print data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...