2017-10-07 11 views
0

JSON形式の製品のリストと、JSON形式の別のファイルの製品を一致させようとしています。これは、レコード連結、エンティティ解決、参照調整、または単にマッチングと呼ばれることがあります。リスティングから新しいJSONリストへのJSONlinesの照合

これは、サードパーティの小売業者の商品リスト(例: 「Nikon D90 12.3MPデジタル一眼レフカメラ(ボディのみ)」を既知の製品、例えば"Nikon D90"

詳細

データは、オブジェクト

製品

{ 
"product_name": String // A unique id for the product 
"manufacturer": String 
"family": String // optional grouping of products 
"model": String 
"announced-date": String // ISO-8601 formatted date string, e.g. 2011-04-28T19:00:00.000-05:00 
} 

リスト

{ 
"title": String // description of product for sale 
"manufacturer": String // who manufactures the product for sale 
"currency": String // currency code, e.g. USD, CAD, GBP, etc. 
"price": String // price, e.g. 19.99, 100.00 
} 

結果

{ 
"product_name": String 
"listings": Array[Listing] 
} 

データ 2つのファイルが含まれています: products.txt - 700の製品 listings.txtの周りに含まれています - (のpythonを使用して)約20,000の製品リストに

現在のコードが含まれています:上記

import jsonlines 
import json 
import re 
import logging, sys 

logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) 

with jsonlines.open('products.jsonl') as products: 
    for prod in products: 
    jdump = json.dumps(prod) 
    jload = json.loads(jdump) 
    regpat = re.compile("^\s+|\s*-| |_\s*|\s+$") 
    prodmatch = [x for x in regpat.split(jload["product_name"].lower()) if x] 
    manumatch = [x for x in regpat.split(jload["manufacturer"].lower()) if x] 
    modelmatch = [x for x in regpat.split(jload["model"].lower()) if x] 
    wordmatch = prodmatch + manumatch + modelmatch 
    #print (wordmatch) 
    #logging.debug('product first output') 
    with jsonlines.open('listings.jsonl') as listings: 
     for entry in listings: 
     jdump2 = json.dumps(entry) 
     jload2 = json.loads(jdump2) 
     wordmatch2 = [x for x in regpat.split(jload2["title"].lower()) if x] 
     #print (wordmatch2) 
     #logging.debug('listing first output') 
     contained = [x for x in wordmatch2 if x in wordmatch] 
     if contained: 
      print(contained) 
     #logging.debug('contained first match') 

コードは、最大分割製品ファイル内のproduct_name、model、およびmanufacturerの単語を検索し、リストファイルから文字列を一致させようとしていますが、これは遅すぎるため、より良い方法が必要です。どんな助けにも感謝します

+0

何が問題なのですか?答えが必要な場合は、質問する必要があります。 –

+0

ネストされたforループはすべてのデータを通過しますが、私のマッチはあまり正確ではありません。 –

+0

を解析するには時間がかかりすぎます。フルテキスト検索のデータベースを探して、それを使用したい場合があります。また、このコードや全文検索データベースの使用を改善できるテキスト正規化に関するオンラインリソースもあります。私はこれがオープンエンドであることを知っていますが、それは大きなフィールドです、コーナーを選んで読み始めます。 :) – ldrg

答えて

0

最初に、ダンプ()の後ろにloads()が続いているかどうかはわかりません。あなたがここに投稿したコードから完全に冗長であるように見えるので、あなたは、各反復ですべてのシリアル化とシリアル化を避ける方法を見つけることができます。

2つ目は、これまでのように変更されていないため、データ構造のループの前に一度解析して(おそらくwordmap2の内容を派生したリストにマップする) products.jsonを解析する際の構造

次へ:multiprocessingを使用するようにこれを再調整する方法がある場合は、そうすることを強くお勧めします。あなたは完全にここのCPUに縛られており、これを簡単にすべてのコアで並列に実行することができます。

最後に、私はいくつかのファンキーな正規表現のセナニガンでそれを与えました。ここでの目標は、reがC言語で実装されているため、Pythonでこの文字列をすべて処理するよりもパフォーマンスが向上すると思っていたため、正規表現に多くのロジックを追加することです。

import json 
import re 

PRODUCTS = """ 
[ 
{ 
"product_name": "Puppersoft Doggulator 5000", 
"manufacturer": "Puppersoft", 
"family": "Doggulator", 
"model": "5000", 
"announced-date": "ymd" 
}, 
{ 
"product_name": "Puppersoft Doggulator 5001", 
"manufacturer": "Puppersoft", 
"family": "Doggulator", 
"model": "5001", 
"announced-date": "ymd" 
}, 
{ 
"product_name": "Puppersoft Doggulator 5002", 
"manufacturer": "Puppersoft", 
"family": "Doggulator", 
"model": "5002", 
"announced-date": "ymd" 
} 
] 
""" 


LISTINGS = """ 
[ 
{ 
"title": "Doggulator 5002", 
"manufacturer": "Puppersoft", 
"currency": "Pupper Bux", 
"price": "420" 
}, 
{ 
"title": "Doggulator 5005", 
"manufacturer": "Puppersoft", 
"currency": "Pupper Bux", 
"price": "420" 
}, 
{ 
"title": "Woofer", 
"manufacturer": "Shibasoft", 
"currency": "Pupper Bux", 
"price": "420" 
} 
] 
""" 

SPLITTER_REGEX = re.compile("^\s+|\s*-| |_\s*|\s+$") 
product_re_map = {} 
product_re_parts = [] 

# get our matching keywords from products.json 
for idx, product in enumerate(json.loads(PRODUCTS)): 
    matching_parts = [x for x in SPLITTER_REGEX.split(product["product_name"]) if x] 
    matching_parts += [x for x in SPLITTER_REGEX.split(product["manufacturer"]) if x] 
    matching_parts += [x for x in SPLITTER_REGEX.split(product["model"]) if x] 

    # store the product object for outputting later if we get a match 
    group_name = 'i{idx}'.format(idx=idx) 
    product_re_map[group_name] = product 
    # create a giganto-regex that matches anything from a given product. 
    # the group name is a reference back to the matching product. 
    # I use set() here to deduplicate repeated words in matching_parts. 
    product_re_parts.append("(?P<{group_name}>{words})".format(group_name=group_name, words="|".join(set(matching_parts)))) 
# Do the case-insensitive matching in C code 
product_re = re.compile("|".join(product_re_parts), re.I) 

for listing in json.loads(LISTINGS): 
    # we match against split words in the regex created above so we need to 
    # split our source input in the same way 
    matching_listings = [] 
    for word in SPLITTER_REGEX.split(listing['title']): 
     if word: 
      product_match = product_re.match(word) 
      if product_match: 
       for k in product_match.groupdict(): 
        matching_listing = product_re_map[k] 
        if matching_listing not in matching_listings: 
         matching_listings.append(matching_listing) 
    print listing['title'], matching_listings 
関連する問題