2017-01-11 5 views
0

htmlテーブルをjsonオブジェクトに変換してファイルに書き込もうとしています。基本的には、プリンタの設定ページから取得したプリンタデータです。htmlテーブルをPythonのjsonオブジェクトに変換する

これは

html_data = urllib2.urlopen('http://192.168.2.198/sys_count.html') 
soup = BeautifulSoup(html_data,"lxml") 

table_data = [[cell.text for cell in row("td")] 
         for row in soup.body.find_all('table', attrs={'class' : 'matrix'})] 



with open('/home/abc/Desktop/JsonData.txt', 'w') as outfile: 
    json.dump(table_data, outfile, sort_keys = 'true', indent = 4, separators=(',',':'), 
ensure_ascii=False) 

出力され、私のコードです:

[ 
    [ 
     "Black & White", 
     "79555", 
     "Full Colour", 
     "0" 
    ], 
    [ 
     "Copy", 
     "30697", 
     "Printer", 
     "48798", 
     "Others", 
     "60", 
     "Scan Send", 
     "Black & White", 
     "648", 
     "Full Colour", 
     "747" 
    ], 
    [ 
     "Document Feeder", 
     "11709", 
     "Duplex", 
     "13799" 
    ] 
] 

私は出力になりたい - 他のテーブルのための

{ 
    { 
     "Black & White":  "79555", 
     "Full Colour":  "0" 
    }, 

など....

は多くの方法を試しましたが、私がリストをdictに変換しようとすると、タイプエラーが発生します。助けが必要。

参考のため、私はPython 2.7を使用しています。それが助けば。

詳細については、[プリンタ]ページの画像を追加してください。

Snapshot of printer setup page

+2

編集質問と使用ボタン:


FWIWは、ここlist_to_dictのdictの理解バージョンです。 – furas

+0

(キー、値)のペアのリストがあれば、リストのリストをdictsのリストに簡単に変換できます。しかし、そこには値が一致しないキーのような "Scan Send"があります。それとも、「その他」キーの追加値です。または、それは「ブラック&ホワイト」、「648」、「フルカラー」、「747」のものを含むサブ辞書のキーです。これは、タスクを少しトリッキーにします。 –

+0

だから、 "Scan Send"はサブディクションのキーでなければなりません。しかし、あなたがテーブルのデータを抽出した方法がその構造情報を失うので、 'table_data'リストからそれを見るのは容易ではありません。それをプログラムにハードコーディングするだけです。 「スキャン送信」のように、サブディクテーションに必要なデータが続く他のキーが存在する可能性はありますか? –

答えて

2

あなたは試すことができます:

table_data = [ 
    [ 
     "Black & White", 
     "79555", 
     "Full Colour", 
     "0" 
    ], 
    [ 
     "Copy", 
     "30697", 
     "Printer", 
     "48798", 
     "Others", 
     "60", 
     "Scan Send", 
     "Black & White", 
     "648", 
     "Full Colour", 
     "747" 
    ], 
    [ 
     "Document Feeder", 
     "11709", 
     "Duplex", 
     "13799" 
    ] 
] 
final_data = [] 
for data in table_data: 
    d = dict([(k, v) for k,v in zip (data[::2], data[1::2])]) 
    final_data.append(d) 


print (final_data) 
[{'Black & White': '79555', 'Full Colour': '0'}, {'Others': '60', 'Printer': '48798', '648': 'Full Colour', 'Scan Send': 'Black & White', 'Copy': '30697'}, {'Document Feeder': '11709', 'Duplex': '13799'}] 
+0

ありがとうharsha。あなたのコードを試してみました。フルカラーキー値を除いて素晴らしい作品は、反転されます。 、 { "648" だから、出力は[ {:: "79556"、 "フルカラー" "0" "ブラック&ホワイト"}:このような何かがある "フルカラー"、 "コピー": "30697"、 "その他": "60"、 "プリンタ": "48799"、 "スキャン送信": "ブラック&ホワイト" }、 { "ドキュメントフィーダー": "11709"、 」 Duplex ":" 13799 " } ] – Matin

+0

いつも問題として@MatinはOryginal HTMLに2つのサブ要素がある' Scan Send'です。だから実際の問題は掻き取り中です。 – furas

1

たぶんrange(len())のない、より良いバージョンがあります。

table_data = [ 
    [ 
     "Black & White", 
     "79555", 
     "Full Colour", 
     "0" 
    ], 
    [ 
     "Copy", 
     "30697", 
     "Printer", 
     "48798", 
     "Others", 
     "60", 
     "Scan Send", 
     "Black & White", 
     "648", 
     "Full Colour", 
     "747" 
    ], 
    [ 
     "Document Feeder", 
     "11709", 
     "Duplex", 
     "13799" 
    ] 
] 

result = [] 

for row in table_data: 
    d = dict() 
    for i in range(0, len(row)-1, 2): 
     d[row[i]] = row[i+1] 
    result.append(d) 

結果:それは今奇妙に見える'648': 'Full Colour'を与えるよう

[ 
    { 
    'Black & White': '79555', 
    'Full Colour': '0' 
    }, 
    { 
    '648': 'Full Colour', 
    'Copy': '30697', 
    'Others': '60', 
    'Printer': '48798', 
    'Scan Send': 'Black & White' 
    }, 
    { 
    'Document Feeder': '11709', 
    'Duplex': '13799' 
    } 
] 

しかし、そうです、一部のデータが正しくないことができます。データから最初に"Scan Send"を削除する必要があります。

+0

「スキャン送信」の質問に対する私のコメントを参照してください。 –

+0

プリンタの設定ページからこのデータを直接取得しようとしています。このコードを一般的なものにして、IPアドレスを変更するだけで別のプリンタの値を取得できるようにしようとしています。私は、参考のためにプリンタ設定ページのスナップショットを追加しました。 – Matin

+0

@ PM2Ring私は私の結果を見たときにこの問題を見た。いつもそうであるとは限らないので、問題になる可能性があります。「スキャン送信」 – furas

0

を私がコメントで言ったように、あなたがテーブルのデータを抽出してきた方法は、元のHTMLテーブルから重要な構造情報を失うため、このタスクはトリッキーです。

しかし、とにかく...ここでは"Scan Send"を扱う解決策があります。サブディクテーションを導入する"Scan Send"のような他のキーがある場合は、special_keysセットに追加することができます。

list_to_dictは、rowリストから再帰的に辞書を作成します。まず、rowからイテレータオブジェクトを作成します。そのイテレータの次のアイテムを&とします。それが特別なキーであれば、行の残りの部分で再帰し、返されたdictをそのキーの値として使用します。それ以外の場合は、イテレータから次の文字列を取得し、それを現在のキーの値として使用します。

import json 

table_data = [ 
    ["Black & White", "79555", "Full Colour", "0"], 
    ["Copy", "30697", "Printer", "48798", "Others", "60", 
     "Scan Send", "Black & White", "648", "Full Colour", "747"], 
    ["Document Feeder", "11709", "Duplex", "13799"] 
] 

special_keys = {"Scan Send"} 

def list_to_dict(row): 
    d = {} 
    it = iter(row) 
    for s in it: 
     if s in special_keys: 
      v = list_to_dict(it) 
     else: 
      v = next(it) 
     d[s] = v 
    return d 

table_dicts = [list_to_dict(row) for row in table_data] 
print(json.dumps(table_dicts, sort_keys=True, indent = 4)) 

この戦略はのみ仕事私たちは与えられた行の特別なキー以下のすべての項目がのサブ辞書に行くことになっていることを保証できるかどう

[ 
    { 
     "Black & White": "79555", 
     "Full Colour": "0" 
    }, 
    { 
     "Copy": "30697", 
     "Others": "60", 
     "Printer": "48798", 
     "Scan Send": { 
      "Black & White": "648", 
      "Full Colour": "747" 
     } 
    }, 
    { 
     "Document Feeder": "11709", 
     "Duplex": "13799" 
    } 
] 

出力その特別なキー。そうでない場合は、別の戦略が必要です...それらをより読みやすくするために - {} `コードと出力をフォーマットするために、`

def list_to_dict(row): 
    it = iter(row) 
    return {s: list_to_dict(it) if s in special_keys else next(it) for s in it} 
関連する問題