[英]Can beautiful soup give a chuck of file based on span class=?
我正在嘗試從HTML頁面提取一些簡單的字段。 這是一個包含一些重復數據的表。
每個記錄都有一個FIRST_NAME(以及其他一些東西),但並不是每個記錄都有一個WEBSITE。 因此,我的xpath解決方案返回了10個名稱,但僅返回9個網站URL。
fname= tree.xpath('//span[@class="given-name"]/text()')
fweb = tree.xpath('//a[@class="url"]/text()')
使用這種方法,我無法確定哪個記錄缺少該URL。
所以現在我想將文件分成多個塊; 每個塊都將以跨度類GIVEN-NAME開始,並在下一個GIVEN-NAME之前結束。
我怎么做? 在我的代碼中,我有一個無限循環,該循環不斷返回跨度類FIRST-NAME的第一個實例,它不會在HTML文件中進行。
with open('sample A.htm') as f:
soup = bs4.BeautifulSoup(f.read())
many_names= soup.find_all('span',class_='given-name')
print len(many_names)
for i in range(len(many_names)):
first_name = soup.find('span', class_='given-name').text
website = soup.find('a', class_='url').text
myprint (i, first_name, last_name, aco, city, qm, website)
soup.find_next('span', class_='given-name')
最后一條語句(find_next)似乎沒有任何作用。
無論是否使用它,循環都是從頭開始一遍又一遍地讀取。 什么是正確的方法?
編輯:來自HTML文件的示例(我編輯了一些內容,因為還有更多內容)物理上,布局是跨度給定名稱等等URL埋藏在某個地方,然后是另一個跨度給定名稱
enter code here
</div>
<div class="connections-list cn-list-body cn-clear" id="cn-list-body">
<div class="cn-list-section-head" id="cn-char-A"></div><div class="cn-list-row-alternate vcard individual art-literary-agents celebrity-nonfiction-literary-agents chick-lit-fiction-literary-agents commercial-fiction-literary-agents fiction-literary-agents film-entertainment-literary-agents history-nonfiction-literary-agents literary-fiction-literary-agents military-war-literary-agents multicultural-nonfiction-literary-agents multicultural-fiction-literary-agents music-literary-agents new-york-literary-agents-ny nonfiction-literary-agents photography-literary-agents pop-culture-literary-agents religion-nonfiction-literary-agents short-story-collection-literary-agents spirituality-literary-agents sports-nonfiction-literary-agents usa-literary-agents womens-issues-literary-agents" id="richard-abate" data-entry-type="individual" data-entry-id="19337" data-entry-slug="richard-abate"><div id="entry-id-193375501ffd6551a6" class="cn-entry">
<table border="0px" bordercolor="#E3E3E3" cellspacing="0px" cellpadding="0px">
<tr>
<td align="left" width="55%" valign="top">
<span class="cn-image-style"><span style="display: block; max-width: 100%; width: 125px"><img height="125" width="125" sizes="100vw" class="cn-image logo" alt="Logo for Richard Abate" title="Logo for Richard Abate" srcset="http://literaryagencies.com/wp-content/uploads/connections-images/richard-abate/richard-abate-literary-agent_logo_1-7bbdb1a0dbafe8417e994150608c55e4.jpg 1x" /></span></span>
</td>
<td align="right" valign="top" style="text-align: right;">
<div style="clear:both; margin: 5px 5px;">
<div style="margin-bottom: 5px;">
<span class="fn n"> <span class="given-name">Richard</span> <span class="family-name">Abate</span> </span>
<span class="title">3 Arts Entertainment</span>
<span class="org"><span class="organization-unit">Query method(s): Postal Mail *</span></span>
</div>
<span class="address-block">
<span class="adr"><span class="address-name">Work</span> <span class="street-address">16 West 22th St</span> <span class="locality">New York</span> <span class="region">NY</span> <span class="postal-code">10010</span> <span class="country-name">USA</span><span class="type" style="display: none;">work</span></span>
</span>
</div>
</td>
</tr>
<tr>
<td valign="bottom" style="text-align: left;">
<a class="cn-note-anchor toggle-div" id="note-anchor-193375501ffd6551a6" href="#" data-uuid="193375501ffd6551a6" data-div-id="note-block-193375501ffd6551a6" data-str-show="Show Notes" data-str-hide="Close Notes">Show Notes</a> | <a class="cn-bio-anchor toggle-div" id="bio-anchor-193375501ffd6551a6" href="#" data-uuid="193375501ffd6551a6" data-div-id="bio-block-193375501ffd6551a6" data-str-show="Show Bio" data-str-hide="Close Bio">Show Bio</a>
</td>
<td align="right" valign="bottom" style="text-align: right;">
<a class="url" href="http://www.3arts.com" target="new" rel="nofollow">http://www.3arts.com</a>
<span class="cn-image-style"><span style="display: block; max-width: 100%; width: 125px"><img height="125" width="125" sizes="100vw" class="cn-image logo" alt="Logo for Andree Abecassis" title="Logo for Andree Abecassis" srcset="http://literaryagencies.com/wp-content/uploads/connections-images/andree-abecassis/andree-abecassis-literary-agent_logo_1-b531cbac02864497b301e74bc6b37aa9.jpg 1x" /></span></span>
</td>
<td align="right" valign="top" style="text-align: right;">
<div style="clear:both; margin: 5px 5px;">
<div style="margin-bottom: 5px;">
<span class="fn n"> <span class="given-name">Andree</span> <span class="family-name">Abecassis</span> </span>
enter code here
我很確定情況並非如此,假設您已正確復制並粘貼了代碼,那么最后一條語句將為您提供SyntaxError
; 而是會給您一個AttributeError
因為您拼寫錯誤的方法名稱findNext
調用了它,而出於某種神秘的原因而改為find_next
。 通常, 復制並粘貼您的追溯,而不要嘗試“解釋”它。
但是,由於您已經有了與相關類有關的所有范圍的列表,所以最簡單的方法是更改第二個循環以在每個范圍內進行搜索:
for i, a_span in enumerate(many_names):
first_name = a_span.text
website = a_span.find('a', class_='url')
if website is None:
website = '*MISSING*'
else:
website = website.text
last_name = aco = city = qm = 'YOU NEVER EXTRACT THESE!!!'
myprint(i, first_name, last_name, aco, city, qm, website)
假設您確實使用所有這些參數定義了函數myprint
。
您會注意到我設置了四個變量,以提醒您您永遠不要提取這些值-我懷疑您想解決這個問題,對吧?
編輯:現在看來,要查找的標簽之間的關系不在 HTML的結構中,而是對標簽在HTML文本中的出現順序的脆弱依賴,因此需要一種非常不同的方法。 這是一種可能性:
from bs4 import BeautifulSoup
with open('ha.txt') as f:
soup = BeautifulSoup(f)
def tag_of_interest(t):
if t.name=='a': return t.attrs.get('class')==['url']
if t.name=='span': return t.attrs.get('class')==['given-name']
return False
for t in soup.find_all(tag_of_interest):
print(t)
例如,當我在編輯后將現在在Q中給出的HTML代碼段保存在ha.txt
時,此腳本將發出:
<span class="given-name">Richard</span>
<a class="url" href="http://www.3arts.com" rel="nofollow" target="new">http://www.3arts.com</a>
<span class="given-name">Andree</span>
因此,現在剩下的就是適當地對標簽的相關序列進行分組了(我認為還應該包括其他序列,例如帶有last-name
&c類的范圍)。 一個class
似乎是適當的(並且可以將myprint
class
功能完全重鑄為該類的方法,但我將跳過該部分)。
class Entity(object):
def __init__(self)
self.first_name = self.last_name = self.website = None # &c
entities = []
for t in soup.find_all(tag_of_interest):
if t.name=='span' and t.class==['given-name']:
ent = Entity()
ent.given-name = t.text
entities.append(ent)
else:
if not entities:
print 'tag', t, 'out of context'
continue
ent = entities[-1]
if t.name=='a' and t.class==['url']:
ent.website = t.text
# etc for other tags of interest
最后,可以檢查entities
列表以查找缺少必填數據位的實體,依此類推。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.