2009-04-01 3 views
3

Вот фрагмент HTML-файла, который я изучаю с помощью Beautiful Soup.Complex Beautiful Soup query

<td width="50%"> 
    <strong class="sans"><a href="http:/website">Site</a></strong> <br /> 

Я хотел бы получить <a href> для любой линии, которая имеет <strong class="sans"> и которая находится внутри <td width="50%">.

Можно ли запросить HTML-файл для этих нескольких условий с помощью Beautiful Soup?

ответ

9

Механизмы поиска BeautifulSoup допускают вызываемые вызовы, которые, как представляется, рекомендуют для вашего случая: «Если вам нужно наложить сложные или блокирующие ограничения на атрибуты тега, передайте вызываемый объект для имени ...». (хорошо ... они говорят об атрибутах конкретно, но совет отражает базовый дух API BeautifulSoup).

Если вы хотите Однострочник:

soup.findAll(lambda tag: tag.name == 'a' and \ 
tag.findParent('strong', 'sans') and \ 
tag.findParent('strong', 'sans').findParent('td', attrs={'width':'50%'})) 

Я использовал лямбда в этом примере, но на практике вы можете определить вызываемую функцию, если у вас есть несколько прикованных требований, как это лямбда имеет сделать два звонка findParent('strong', 'sans'), чтобы избежать повышения исключения, если тег <a> не имеет родителя strong. Используя правильную функцию, вы можете сделать тест более эффективным.

0
>>> BeautifulSoup.BeautifulSoup("""<html><td width="50%"> 
...  <strong class="sans"><a href="http:/website">Site</a></strong> <br /> 
... </html>""") 
<html><td width="50%"> 
<strong class="sans"><a href="http:/website">Site</a></strong> <br /> 
</td></html> 
>>> [ a for a in strong.findAll("a") 
      for strong in tr.findAll("strong", attrs = {"class": "sans"}) 
       for tr in soup.findAll("td", width = "50%")] 
[<a href="http:/website">Site</a>]