1

私は辞書のリストの辞書を持っています。なぜ私はこの奇妙なアプローチを選んだのですか? これは、大規模な Web ページのさまざまなセクションをさまざまな辞書に保存している Web スクレイピングの取り組みの一部です。データを追跡するための列名があります。Python 2.6.6 を使用しているため、dicts を注文していません。

このデータを保存するより効率的な方法は何ですか (mysql の辞書)? Web サイトをスクレイピングするたびに、さらに処理するためにデータを保存する一時テーブルを作成します。最初に ID のレコードを作成してから、その ID の列を更新します。それを行うためのより迅速で効率的な方法はありますか?ありがとうございました!

パイソン

import MySQLdb

db=MySQLdb.connect(db="mydb")
c=db.cursor()

mydict = {'1': [{'First': 'John', 'Last': 'Doe'}, {'Company': 'Trulia Inc.', 'Title': 'CEO', 'YearsattheCompany': 4}, {'Cell': '216-453-4322', 'Home': None}]}

for key, value in mydict.items():
    id = key
    c.execute("insert into deldictmysql (id) values (%s)" % id)
    for eachdict in value:
        print eachdict
        for finalkey, finalvalue in eachdict.items():
            print finalkey, finalvalue
            if finalvalue:
                query = "update deldictmysql set %s = '%s'"
                c.execute(query % (finalkey, finalvalue))

c.close()

MySQL

create table deldictmysql (id integer, first varchar(40), last varchar(40), company varchar(200), title varchar(200), yearsatthecompany integer, cell varchar(20), home varchar(20));

出力

select * from deldictmysql;

"id"    "first" "last"  "company"   "title" "yearsatthecompany" "cell"  "home"
"1" "John"  "Doe"   "Trulia Inc."   "CEO"   "4" "216-453-4322"  ""
4

3 に答える 3

2

辞書を平らにして挿入するだけです:

def encoding(val):
    if isinstance(val, unicode):
        return val.encode('utf-8')
    else:
        return str(val)


for id, val in mydict.items():
    data = dict(reduce(lambda x, y: x+y, [v.items() for v in val]) + [('id', id)])
    sorted_keys = sorted(map(str, data.keys()))
    sorted_vals = map(encoding, [v[k] for k in sorted_keys])  # sorted by keys
    format = ', '.join(["'%s'"] * len(sorted_vals))
    c.execute("insert into deldictmysql
               (%s) values (%s)" % (', '.join(sorted_keys), format), sorted_vals)

UPD: キーの任意の数と値

于 2012-06-26T22:00:22.290 に答える
0

できる改善の 1 つは、1 つの更新クエリを発行することです。

for key, value in mydict.iteritems():
    id = key
    c.execute("insert into deldictmysql (id) values (%s)" % id)
    for eachdict in value:
        print eachdict
        items = [item for item in eachdict.iteritems() if item[1]]
        query_values = tuple(itertools.chain(*items))
        query = "update deldictmysql set "+", ".join("%s = '%s'" for i in items)
        c.execute(query % query_values)

またはさらに良いのは、1 つの挿入クエリです。

for key, value in mydict.iteritems():
    id = key
    keys = []
    values = []
    for eachdict in value:
        print eachdict
        for finalkey, finalvalue in eachdict.iteritems():
            if not finalvalue: continue
            keys.append(finalkey)
            values.append(finalvalue)
    keys_part = ", ".join("%s" for k in keys)
    values_part = ", ".join("'%s'" for v in values)
    query_values = keys+[id]+values
    c.execute("insert into deldictmysql (id, "+keys_part+") values (%s"+values_part+")" % query_values)

dict のすべての値が同じキーを持つことを保証できる場合は、同じロジックに従って、1 つのクエリですべての挿入を発行できます。"insert into deldictmysql (id, "+keys_part+") values "+(", ".join("(%s"+values_part+")" for i in range(len(mydict)))) % query_values(最後に一連のことをお許しください):))のようなもので、query_valuesそれに応じて構築します。

また、print ステートメントから Python 2.7 を使用していることに気付いたので、リストの代わりに反復子を返す のiteritems代わりに使用する方が良いと思いますitems。これは、辞書に多くの項目がある場合に便利です。

そして、これらすべての中で最も重要なことは、クエリをサニタイズしていないということです。それは悪いことです. ここでの問題は、従来c.execute(sql, params)の , を使用してパラメーターをバインドできないことです。列名でさえ動的であり、これはカバーされていないためです。したがって、これらを手動でサニタイズする必要があり、おそらくそれらをサニタイズできないため、キーも信頼する必要があります。

これにより、おおよそ次のようになります。

values.append(MySQLdb.escape_string(finalvalue))

値を追加するとき。

これは何ができるかのアイデアを与えるだけであり、多くの場合失敗することに注意してください。

それが役に立てば幸い。

于 2012-06-26T22:04:23.167 に答える
0
  1. この種のデータを保存するには、redis のようなものを使用することを検討してください。
  2. モジュールを使用してjson、テキストとしてシリアル化できます。
于 2012-06-26T22:25:53.577 に答える