BeautifulSoup, найти с текстом «цена», а затем получить цену от следующего - PullRequest
5 голосов
/ 31 июля 2010

Мой HTML выглядит так:

<td>
   <table ..>
      <tr>
         <th ..>price</th>
         <th>$99.99</th>
      </tr>
   </table>
</td>

Итак, я нахожусь в текущей ячейке таблицы, как я могу получить значение 99.99?

Пока у меня есть:

td[3].findChild('th')

Но мне нужно сделать:

Найдите th с текстом 'price', затем получите строковое значение следующего тега.

Ответы [ 2 ]

8 голосов
/ 31 июля 2010

Подумайте об этом «в шагах» ... учитывая, что некое x является корнем рассматриваемого вами поддерева

x.findAll(text='price')

- это список всех элементов в этом поддереве, содержащий текст 'price'. Родители этих предметов тогда, конечно, будут:

[t.parent for t in x.findAll(text='price')]

и если вы хотите оставить только тех, чье "имя" (тег) 'th', тогда, конечно,

[t.parent for t in x.findAll(text='price') if t.parent.name=='th']

и вам нужны «ближайшие братья и сестры» из них (но только если они тоже 'th' с), поэтому

[t.parent.nextSibling for t in x.findAll(text='price')
 if t.parent.name=='th' and t.parent.nextSibling and t.parent.nextSibling.name=='th']

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

Редактировать : добавлен допуск для строки текста между родителем th и «следующим братом», а также допуск для последнего, равный td вместо этого, для комментария ОП.

for t in x.findAll(text='price'):
  p = t.parent
  if p.name != 'th': continue
  ns = p.nextSibling
  if ns and not ns.name: ns = ns.nextSibling
  if not ns or ns.name not in ('td', 'th'): continue
  print ns.string

Я добавил ns.string, который будет предоставлять содержимое следующего брата тогда и только тогда, когда они будут просто текстовыми (без дополнительных вложенных тегов) - конечно, вы можете вместо этого анализировать дальше на этом этапе, в зависимости от приложения. потребности -!). Точно так же я представляю, что вы будете делать не просто print, а что-то более умное, но я даю вам структуру.

Говоря о структуре, обратите внимание, что дважды я использую if...: continue: это уменьшает вложенность по сравнению с альтернативой инвертирования условия if и отступа всех следующих операторов в цикле - и "flat лучше, чем nested "- это один из коанов в Zen of Python (import this в интерактивном режиме, чтобы увидеть их всех и медитировать; -).

0 голосов
/ 31 июля 2010

С помощью функции pyparsing легко получить доступ к середине некоторого HTML-кода для шаблона тега, подобного следующему:

from pyparsing import makeHTMLTags, Combine, Word, nums

th,thEnd = makeHTMLTags("TH")
floatnum = Combine(Word(nums) + "." + Word(nums))
priceEntry = (th + "price" + thEnd + 
              th + "$" + floatnum("price") + thEnd)

tokens,startloc,endloc = priceEntry.scanString(html).next()

print tokens.price

Помощник Pyparsing makeHTMLTags возвращает пару выражений pyparsing, одно для начального тега иодин для конечного тега.Шаблон начального тега - это гораздо больше, чем просто добавление символов «<>» вокруг заданной строки, но он также позволяет использовать дополнительные пробелы, регистр переменных, а также наличие или отсутствие атрибутов тега.Например, обратите внимание, что хотя я и указал «TH» в качестве тега заголовка таблицы, он также будет соответствовать «th», «Th», «tH» и «TH».Поведение пропуска пробелов по умолчанию в Pyparsing также будет обрабатывать дополнительные пробелы, между тегом и «$», между «$» и числовой ценой и т. Д., Без необходимости разбрасывать индикаторы «ноль или более пробелов могут идти сюда».Наконец, присваивая имя результата «цена» (после floatum в определении priceEntry), это позволяет очень просто получить доступ к этому конкретному значению из полного списка токенов, соответствующих общему выражению priceEntry.

(Объединение используется для 2 целей: оно запрещает пробелы между компонентами числа; вместо списка возвращается один объединенный токен "99,99" * ["99", ".", "99"].)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...