簡體   English   中英

美麗的湯能根據span class =給出文件嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM