2012-02-03 35 views
1

私はPHPベースのショッピングアプリケーションに取り組んでいます。私は、私が知っている同じ製品を表す文字列のリストを持っています。これらの文字列には、完全な製品名またはその一部(通常、ブランド名+モデル名の完全な製品名)が含まれている可能性があります。文字列のセットから製品名を抽出する方法は? (PHP)

このような製品名の抽出を行うには、どのような方法が最適かと思います。ここで例えば

、同じ製品を表す文字列のリスト:

  • TKG BOUILLOIRE TKG - JK 1008 RWD
  • TKG Jkの1008 RWD
  • TKG Kalorik - JK 1008 RWD - Bouilloire ELECTRIQUEサンセリフフィル360°
  • TKG BouilloireのELECTRIQUEのサンセリフFIL 1,7リットル2000ワットのPOI TKGルージュらブラン
  • TKG Kalorik - JK 1008 RWD - Bouilloire ELECTRIQUE SANのフィル360°
  • TKG JK 1008 RWD BOUILLOIRES

私は、製品名 "TKG JK 1008 RWD" を抽出することを期待。ストリング4は部分的な情報しか含んでいないことに注意してください。

私はすべての文字列で繰り返し単語を数えたときにアプローチを試みました。そこから、さらに進むことは困難です。

手掛かりはありますか?

乾杯 ニコラス

+0

こんにちは、販売Webサイトのようにこの情報を基にしています。もっと具体的になりますか? html出力を変更できますか?それはドロップダウンメニューとして使用されていますか? –

+1

あなたが何を抽出する必要があるかを既に知っているなら、それをまったく抽出する必要はありません。事前に抽出する必要があるものがわからない場合は、抽出するパターン***を記述する必要があります。そうしないと、誰もあなたの質問に答えられません。 – FtDRbwLXw6

+1

私の意見では、あなたはどこかにデザイン上の問題があるように思えます。独自の製品番号を使用して、購入および注文の内容に関する混乱を避けます。上記の各文字列を固有の製品番号で開始または終了します。 – phpmeh

答えて

2

あなたは、文字列が重なってどのくらいの分析(そのほとんどに表示された単語/ストリングのリストを生成)、次に最も関連性の高い単語を選ぶことができます。

たとえば、単語が特定の割合の文字列で表示されている場合は、それらを製品名の最も可能性の高い候補と見なすことができます。 (あなたのやっていることに似ていますが、しきい値を追加する - たとえば、5つの単語が88%の文字列に表示され、他の文字列がはるかに低い割合で表示されていることがわかります - 次に、トップ5を製品名として選択します。私は恐れがあり、手動で調整する必要があります)。これは情報の大部分を収集することができますが、決して完璧ではありません。

さらに、ブランドの定義済みリストを用意して、それらの単語をフィルタリングすることができます。また、手動データ入力のプロダクトになる可能性があるため、単語の部分的な一致を考慮して、常にタイプミスが存在する可能性があります。単にそれらを破棄するだけで十分な "信号"が得られれば、心配する必要はありません。

手動キュレーションの項目をマークするために別のフィルタを指定することもできますが、これは非常に時間がかかることがあります。

わかりやすい回答はありません。あなたがやっているのは基本的にテキストマイニングです。私はちょうど始めるのを助けることができるいくつかのアイデアと出発点を投げた。

複数のソースから日付をまとめようとしている自動クローラを構築していると仮定すると、上記はうまくいきます。訪問者があなたのサイトを検索してすべてのクエリの正しい製品ページを返すようにしたい場合は、テキスト検索(主なデータ分析の誰ですか?)に潜むように勧めます。または既製のソリューションを使用してください。

+0

Petrありがとう - 本当に便利です。探検するたくさんのアイデア。 –

1

ただ、いくつかの考え

<?php 
// to lower case 
$string = strtolower(
'Tkg BOUILLOIRE TKG - JK 10o8 RWD 
Tkg Jk 10o8 Rwd 
Tkg Kalorik - JK 10o8 RWD - Bouilloire Électrique sans Fil 360° 
TKG Bouilloire électrique sans fil 1,7 litre 2000 watts Pois TKG Rouge et blanc 
Tkg Kalorik - JK 10o8 RWD - Bouilloire Électrique sans Fil 360° 
Tkg JK 10o8 RWD BOUILLOIRES' 
); 

// remove new lines and explode by spaces 
$data = explode(' ', str_replace(array("\r\n", "\n", "\r"), ' ', $string)); 
// count most popular words 
$count = array_count_values($data); 
// sort 
arsort($count); 
// get first 6 most popular words 
$product = array_slice($count, 0, 6); 
// print product 
var_dump(implode(' ', array_keys($product))); 
?> 

出力は次のとおりです(特にこの問題にされていないが)、私はあなたが述べたような問題があることを推測する

tkg rwd 1008 jk - bouilloire 
+0

ありがとうTomas;非常に良い戦術&私のための良い出発点! –

2

は、比較ショッピングエンジンで働いていました非常に難しい。私の提案はあきらめて、 "the"という製品名(とにかく漠然とした概念です)を合成または抽出しようとするのではなく、文字列の "最高"を選ぶことです。製品名の抽出に使用するほとんどのアイデアは、一貫性がなく、不満足な結果をもたらすでしょう。たとえば、あなたが与えた例だけを見れば、素朴なアルゴリズムは恐らく "Jk 1008 Rwd"のような潜在的な結果、または "BouilloireÉlectrique"のような非常に曖昧なものを生成するでしょう。 Tomasの賢明で見栄えの良い結果でさえ、多くの製品で失敗するか、恥ずかしいほど文法的な結果を生み出します。私の心に浮かぶ多くのアイデアは、 "BouilloireÉlectrique"のようなカテゴリの単語を取り除く傾向があります。これは、ユーザーエクスペリエンスやSEOに最適ではないでしょう。

私があなたの立場にいたなら、私はおそらくタイトルの中の各単語のidfの重みを計算します(このカテゴリのすべての製品またはすべての製品をドキュメントのスペースとして表示します)。次に、各製品ストリングをidfウェイトベクトルに変換し、製品のすべてのウェイトベクトルの重心を計算します。その重心に最も近い文字列を見つけて、それを「最高」と呼んでください。その文字列を製品名として使用します。それは完璧ではありませんが、ほとんどの場合うまくいく可能性があります。 Luceneに(またはあなたが使っている検索データベースに)プラグインやクエリがあり、これがあなたのためにたくさんできるかもしれません。

与えられた文字列のリストでは、このメソッドは、重みの高いモデル番号1008(おそらく電気ケトルには共通しない)が含まれないため、4番目の不完全な文字列から離れる傾向があります。情報量が少なく不完全な製品名が多い場合は、問題になる可能性があります。その重心は、モデル番号を含む名前に特に近くないかもしれません。私が言ったように、それは難しい問題です。

その他のアイデア:私はそれがない推測しているよりも、最も一般的な単語は良い仕事かもしれない最初のnを選ぶの

  1. トーマスヒューリスティック。あるいは、それがうまくいかないときを検出するための別のヒューリスティックがあるかもしれません。
  2. ほとんどの文字列に共通する長い部分文字列を探し、最も大きなIDF重み合計を持つ文字列を選択します。

さらに読書:

TF-IDF

Centroid

Vector Space Model

+0

ありがとう!あなたが私に指摘してくれた素敵な記事! –

0

皆さんがもたらしたいくつかのアイデアを実装で最初刺します。

class ProductNameExtraction { 

    private $brandName = NULL; 
    private $categoryName = NULL; 

    private $modelName = NULL; 

    /** 
     * @param $A Array of string discribing the same product 
     */ 
    public function __construct($A, $brandName, $categoryName) { 
     $this->brandName = $brandName; 
     $this->categoryName = $categoryName; 

     $res = array();  
     foreach ($A as $k => $title) { 
      $res[] = $this->cleanTitle($title); 
     } 

     $this->modelName = $this->computeProductName($res); 
    } 

    public function getModelName() { 
     return $this->modelName; 
    } 

    private function computeProductName($A) { 
     $s = NULL; 

     foreach ($A as $k => $title) { 
      $s .= $title . ' '; 
     } 
     $s = trim($s); 

     $data = explode(' ', $s); 

     // count most popular words 
     $count = array_count_values($data); 

     // Remove brand & category names 
     unset($count[$this->cleanTitle($this->brandName)]); 
     unset($count[$this->cleanTitle($this->categoryName)]); 

     $s = ''; 
     $totalnb = sizeof($A);   
     foreach ($count as $k => $val) { 
      if ($val/$totalnb > 0.5) { 
       $s .= $k . ' '; 
      } 
     } 

     return $s; 
    } 

    private function cleanTitle($title) { 
     // Remove extra spaces 
     $title = trim($title); 
     $title = preg_replace('/\s\s+/', ' ', $title); 

     // Remove noise 
     $title = str_replace(' - ', ' ', $title); 
     $title = str_replace(array("\r\n", "\n", "\r"), ' ', $title); 

     return strtoupper($title); 
    } 

} 
関連する問題