2012-02-08 10 views
0

私はbeautifulstonesoupとpythonを使用してGoogleからのXMLフィードを解析しています。私もcsvを作成してGoogle Docsにアップロードしていますが、これもうまくいきます。問題は、xmlの空のテキスト属性に遭遇したときにパーサが停止することです。すべての属性にデータがあるので、今は問題ではありませんが、初めてデータがないと、データが破損します。BeautifulSoupのNoneType属性を渡す

コード:

import atom 
import gdata.auth 
import gdata.contacts 
import gdata.contacts.client 
import gdata.docs.service 
import gdata.docs.data 
from BeautifulSoup import BeautifulStoneSoup as Soup 
import csv 

email = '[email protected]' 
password = 'password' 
domain = 'domain.com' 

ms_client = gdata.docs.service.DocsService() 
gd_client = gdata.contacts.client.ContactsClient(domain=domain) 
gd_client.ClientLogin(email, password, 'profileFeedAPI') 
ms_client.ClientLogin(email, password, 'peopleCSVupload') 

profiles_feed = gd_client.GetProfilesFeed('https://www.google.com/m8/feeds/profiles/domain/domain.com/full?max-results=300') 

soup = Soup(str(profiles_feed), selfClosingTags=['ns0:category','ns3:status', 'ns0:link','ns1:email']) 

a = soup.findAll('ns0:entry') 
f = open('C:\\people.csv', 'wb') 

writer = csv.writer(f, quoting=csv.QUOTE_NONE, escapechar =' ') 

for entry in a: 
    writer.writerow([entry.find('ns1:familyname').text + ',' + entry.find('ns1:givenname').text + ',' + entry.find('ns1:fullname').text + ',' + entry.find('ns1:orgtitle').text + ',' + entry.find('ns1:orgdepartment').text + ',' + entry.find('ns1:orgname').text + ',' + entry.find('ns1:email',primary=True)['address']]) 

f.close() 

ms = gdata.data.MediaSource(file_path="C:\\people.csv", content_type=gdata.docs.service.SUPPORTED_FILETYPES['CSV']) 
csv_entry = ms_client.Upload(ms, "People File") 

私はこれを行うことができます知っている:

for entry in a: 
    if entry.find('ns1:orgtitle') != None: 
     print entry.find('ns1:orgtitle').text 
    elif entry.find('ns1:orgtitle') == None: 
     print('') 
    if entry.find('ns1:familyname') != None: 
     print entry.find('ns1:familyname').text 
    elif entry.find('ns1:familyname') == None: 
     print('') 
     etc... 

しかし、それは非常に長く、私が表示されるようにデータを集中させる方法がわかりません1行どんな助けでも、大いに感謝します。

答えて

6

あなたはこのように見つけるラップすることができます:

tags = ['ns1:familyname', 'ns1:givenname', ... ] # your tags 
s = map(lambda tag: findnonempty(entry, tag), tags) 
"".join(s) 
+0

バイエルがスローされます、私は週末のために離れていました。これは素晴らしい解決策ですが、私には1つの質問しかありません。最後の項目は、電子メールアドレスが属性であり、テキストフィールドではありません。そのデータをどのように抽出することができますか? – Kevin

+0

Nevermindは、entry.find( 'ns1:email'、primary = True)['address']という変数tを宣言し、ブロック内のforエントリにs.append(t)を実行しました。この。 – Kevin

+0

ようこそ、ケビン。 –

0

のようにそれは十分に簡単です、)

def findnonempty(entry, arg): 
    result = entry.find(arg): 
    if result: 
     return result.text 
    else: 
     return "" 

あなたが7つの通話お互いの後にいずれかの操作を実行するか、またはあなたが(マップを使用することができます値の取得と印刷を機能にカプセル化します。

def find(entry, spec, default=None): 
    value = entry.find(spec) 
    return default if value is None else value.text 

def findandprint(entry, spec, default=None, newline=True): 
    value = find(entry, spec, default) 
    if value is not None: # if we still don't have a value even after 
     print value,   # considering default, don't print anything 
     if newline: 
      print 

は、その後のことができます。ちょうど:あなたは、属性の多くを持っているし、それらを処理したい場合は

for entry in a: 
    findandprint(entry, 'ns1:orgtitle', default="") 
    findandprint(entry, 'ns1:familyname', default="") 

はすべて同じ、それらあまりにも反復処理:

for entry in a: 
    for attribute in ('ns1:orgtitle', 'ns1:familyname', ...): 
     findandprint(entry, attribute, default="") 
1

で最初に私はあなたがそれが壊れそうだと思った理由を見ませんでした...あなたは "怒っている"データスニペットを持っていませんでした。 BeautifulSoupは空の文字列を返すことをうれしく思います。

「あなたのイントロで言ったように」属性を探していることが最終的にはっきりしています。

entry.find('ns1:email',primary=True)['address'] 

空のテキストノード(例:entry.find('ns1:familyname').text)と同じように空の属性は返されません。

は恐れることはありません、ただ.get('address','')['address']表記を代用し、それが空の場合は、空の文字列を返すのではなくこんなに遅く、このを見て申し訳ありませんKeyError例外

+0

XMLフィードは、アドレス属性が存在しない電子メールエントリを生成しません。 NoneType値を持つフィールドを解析しているため、OrgNameなどのテキストフィールドが空の場合に発生します。 – Kevin

関連する問題