2014-09-02 3 views
2

Я пытался в гневе разобрать следующий репрезентативной HTML экстракт, используя BeautifulSoup и LXML:Python - Разбор HTML класс

[<p class="fullDetails"> 
<strong>Abacus Trust Company Limited</strong> 
<br/>Sixty Circular Road 

      <br/>DOUGLAS 

      <br/>ISLE OF MAN 
      <br/>IM1 1SA 
      <br/> 
<br/>Tel: 01624 689600 
      <br/>Fax: 01624 689601 
     <br/> 
<br/> 
<span class="displayBlock" id="ctl00_ctl00_bodycontent_MainContent_Email">E-mail: </span> 
<a href="mailto:[email protected]" id="ctl00_ctl00_bodycontent_MainContent_linkToEmail">[email protected]</a> 
<br/> 
<span id="ctl00_ctl00_bodycontent_MainContent_Web">Web: </span> 
<a href="http://www.abacusiom.com" id="ctl00_ctl00_bodycontent_MainContent_linkToSite">http://www.abacusiom.com</a> 
<br/> 
<br/><b>Partners(s) - ICAS members only:</b> S H Fleming, M J MacBain 
     </p>] 

Что я хочу сделать:

  • Extract 'сильный' текст в company_name

  • Извлечение тегов 'бр' текст в company_line_x

  • Извлечение текста '' MainContent_Email в company_email

  • Извлечение текста '' MainContent_Web в company_web

Проблемы, у меня был:

1) Я мог бы извлечь весь текст с помощью .findall (текст = True), но в каждой строке было много отступов

2) Иногда возвращаются символы не ASCII, и это приведет к сбою csv.writer. Я не уверен на 100%, как справиться с этим правильно. (Ранее я использовал unicodecsv.writer)

Любые советы были бы очень ценными!

В данный момент моя функция только принимает данные страницы и изолирует «р класс»

def get_company_data(page_data): 
    if not page_data: 
     pass 
    else: 
     company_dets=page_data.findAll("p",{"class":"fullDetails"}) 
     print company_dets 
     return company_dets 
+0

Как вы получаете данные страницы в первую очередь? – alecxe

+0

Спасибо за ответ. Я извлекаю данные с помощью модуля Requests и просто передаю данные страницы этой функции. –

+0

Хорошо, вы используете ответный текст или атрибут контента? – alecxe

ответ

3

Вот полное решение:

from bs4 import BeautifulSoup, NavigableString, Tag 

data = """ 
your html here 
""" 

soup = BeautifulSoup(data) 
p = soup.find('p', class_='fullDetails') 

company_name = p.strong.text 
company_lines = [] 
for element in p.strong.next_siblings: 
    if isinstance(element, NavigableString): 
     text = element.strip() 
     if text: 
      company_lines.append(text) 

company_email = p.find('span', text=lambda x: x.startswith('E-mail:')).find_next_sibling('a').text 
company_web = p.find('span', text=lambda x: x.startswith('Web:')).find_next_sibling('a').text 

print company_name 
print company_lines 
print com[enter link description here][1]pany_email, company_web 

Печать:

Abacus Trust Company Limited 
[u'Sixty Circular Road', u'DOUGLAS', u'ISLE OF MAN', u'IM1 1SA', u'Tel: 01624 689600', u'Fax: 01624 689601', u'S H Fleming, M J MacBain'] 
[email protected] http://www.abacusiom.com 

Обратите внимание, что, чтобы получить линии компании мы должны итерацию над strong tag's next siblings и получить все текстовые узлы. company_email и company_web извлекаются ярлыками, другими словами, by the text предшествующих им span тегов.

1

То же, что вы сделали для p данных, используя findall()

(я использую lxml для ниже образцов кодов)

Чтобы получить название компании:

company_name = '' 
for strg in root.findall('strong'): 
    company_name = strg.text  # this will give you Abacus Trust Company Limited 

Чтобы получить линии компании/детали:

company_line_x = '' 
lines = [] 
for b in root.findall('br'): 
    if b.tail: 
     addr_line = b.tail.strip() 
     lines.append(addr_line) if addr_line != '' else None 

company_line_x = ', '.join(lines) # this will give you Sixty Circular Road, DOUGLAS, ISLE OF MAN, IM1 1SA, Tel: 01624 689600, Fax: 01624 689601 
+0

OP использует 'BeautifulSoup'. – alecxe

+0

OP говорит _using BeautifulSoup и lxml_, поэтому я основывал свои предложения на lxml. В любом случае идея остается более или менее такой же. – sk11

+0

Вы правы, неправильно читаете эту часть. Обратите внимание, что в настоящее время отсутствуют элементы «электронная почта» и «веб-сайт». Благодарю. – alecxe

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