2013-08-21 21 views
9

問題:データを収集しようとしているWebサイトがJavascriptを使用してグラフを作成しています。私は、グラフで使用されているデータを引き出すことができるようにしたいと思いますが、どこから開始するのかはわかりません。たとえば、データは次のようになります。Pythonを使用してJavascript変数を解析するにはどうすればよいですか?

var line1= 
[["Wed, 12 Jun 2013 01:00:00 +0000",22.4916114807,"2 sold"], 
["Fri, 14 Jun 2013 01:00:00 +0000",27.4950008392,"2 sold"], 
["Sun, 16 Jun 2013 01:00:00 +0000",19.5499992371,"1 sold"], 
["Tue, 18 Jun 2013 01:00:00 +0000",17.25,"1 sold"], 
["Sun, 23 Jun 2013 01:00:00 +0000",15.5420341492,"2 sold"], 
["Thu, 27 Jun 2013 01:00:00 +0000",8.79045295715,"3 sold"], 
["Fri, 28 Jun 2013 01:00:00 +0000",10,"1 sold"]]; 

これは価格データ(日付、価格、量)です。私はここで別の質問が見つかりました - Parsing variable data out of a js tag using python - 私はJSONとBeautifulSoupを使用することを示唆していますが、私はこの特定の問題にどのように適用するかはわかりません。実際、この問題では、PythonのコードはJSON辞書形式よりもPythonに似ています。

私はそれを文字列として読み込み、それを変換するためにXPATHといくつかのファンキーな文字列編集を使用すると思いますが、これはすでにJavascript変数としてフォーマットされているものにとってはあまりにも多くの作業のようです。

だから、このタイプの整理されたデータをこの変数から引き出すには、ここで何ができますか?以下は、そのようなページがフォーマットされているかを知ることなど、いくつかの仮定を行う

+0

、残りのpython –

+0

に有効である実際のコードことですか?リストのリストである 'line1'という変数ですか?これは後者の場合、 'line1のリストのためのものです:do_something_with(list [0]、list [1]、list2])' – IPDGino

+0

これは、loadのページコンテンツの一部である、line1という変数です。リストの。 –

答えて

2

わかりましたので、それを行うにはいくつかの方法がありますが、私は単にあなたが良いコーディングを持っている場合

#Read page data as a string 
pageData = sock.read() 
#set p as regular expression 
p = re.compile('(?<=line1=)(.*)(?=;)') 
#find all instances of regular expression in pageData 
parsed = p.findall(pageData) 
#evaluate list as python code => turn into list in python 
newParsed = eval(parsed[0]) 

正規表現がいいですline1=間と;すべてを見つけるために正規表現を使用して終了しているが、この方法は他の答えより良い(EDIT:悪い!)

編集:私は最終的に次のように使用: `` =の後に改行と `var`キーワードを除く

#Read page data as a string 
pageData = sock.read() 
#set p as regular expression 
p = re.compile('(?<=line1=)(.*)(?=;)') 
#find all instances of regular expression in pageData 
parsed = p.findall(pageData) 
#load as JSON instead of using evaluate to prevent risky execution of unknown code 
newParsed = json.loads(parsed[0]) 
+1

'eval'は多くの理由から悪いです。 'json.loads'や' ast.literal_eval'のように、より制限的なものを使う方が良いでしょう。確かに、完全に安全で有効なPythonコードとしては、リテラルではなく(たとえ 'abc' + 'def'のように)動作していても、少なくとも式にぶつかりそうですそれはPythonとは違う何かを意味しますし、安全でないものも意味します。(誰かがあなたに 'var line1 = __ import __( 'os')を与えた場合どうなるか想像してください)system( 'rm -rf〜/')' ...) – abarnert

-1

(私はPythonとBS4に最も精通しています)が、Pythonの上のメモリにあなたの例を得るための方法は、この

# example data 
data = 'foo bar foo bar foo bar foo bar\r\nfoo bar foo bar foo bar foo bar \r\nvar line1=\r\n[["Wed, 12 Jun 2013 01:00:00 +0000",22.4916114807,"2 sold"],\r\n["Fri, 14 Jun 2013 01:00:00 +0000",27.4950008392,"2 sold"],\r\n["Sun, 16 Jun 2013 01:00:00 +0000",19.5499992371,"1 sold"],\r\n["Tue, 18 Jun 2013 01:00:00 +0000",17.25,"1 sold"],\r\n["Sun, 23 Jun 2013 01:00:00 +0000",15.5420341492,"2 sold"],\r\n["Thu, 27 Jun 2013 01:00:00 +0000",8.79045295715,"3 sold"],\r\n["Fri, 28 Jun 2013 01:00:00 +0000",10,"1 sold"]];\r\nfoo bar foo bar foo bar foo bar\r\nfoo bar foo bar foo bar foo bar' 
# find your variable's start and end 
x = data.find('line1=') + 6 
y = data.find(';', x) 
# so you can get just the relevant bit 
interesting = data[x:y].strip() 
# most dangerous step! don't do this on unknown sources 
parsed = eval(interesting) 
# maybe you'd want to use JSON instead, if the data has the right syntax 
from json import loads as JSON 
parsed = JSON(interesting) 
# now parsed is your data 
のようなものです
+2

私は間違いなくここで 'eval'を使用しません。有効なPythonリテラルであるものを処理したい場合は、 'ast.literal_eval'を使用してください。しかし、あなたはおそらくそれを望んでいない。 – abarnert

+0

あなたは基本的に同じことを思いついていましたが、代わりに正規表現を使用しました。私はevalを使用して終了しましたが... –

-1

JavaScriptライン/ブロックを持つPython変数が"var line1 = [[a,b,c], [d,e,f]];"のような文字列であるとすると、次のようなコード行を使用できます。

>>> code = """var line1 = [['a','b','c'], ['d','e','f'], ['g','h','i']];""" 
>>> python_readable_code = code.strip("var ;") 
>>> exec(python_readable_code) 
>>> print(line1) 
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']] 

exec()文字列として書式設定されたコードを実行します。この場合、変数line1をリストのリストに設定します。

そして、あなたはこのような何か使用することができますより:あなたの形式は実際には一つ以上のvar foo = [JSON array or object literal];であれば、あなたはちょうどそのJSONとしてそれぞれ1を解析し、それらを抽出するためにDOTALLの正規表現を書くことができます

for list in line1: 
    print(list[0], list[1], list[2]) 
    # Or do something else with those values, like save them to a file 
+0

セミコロンを削除する必要はありません。それらはPythonの文の区切りとしては有効です。しかし、もっと重要なのは、変数名が 'a_line'などと言えば、' strip( "var;") 'は危険になります... – abarnert

+0

さらに重要なのは、JSをPythonに変換して実行しようとしていることです。本当にハッキーで危険です。まったく同じケースで安全に動作し、右側の 'ast.literal_eval'を呼び出すだけで安全ですが、これはもっと安全になり、必要な場所に変数を格納することができます(例えば、dict地元の人々に強制するのではなく(あなたが望むことはほとんどありません)。 – abarnert

6

を。これは、いくつかの仮定を行うもちろん

>>> j = '''var line1= 
[["Wed, 12 Jun 2013 01:00:00 +0000",22.4916114807,"2 sold"], 
["Fri, 14 Jun 2013 01:00:00 +0000",27.4950008392,"2 sold"], 
["Sun, 16 Jun 2013 01:00:00 +0000",19.5499992371,"1 sold"], 
["Tue, 18 Jun 2013 01:00:00 +0000",17.25,"1 sold"], 
["Sun, 23 Jun 2013 01:00:00 +0000",15.5420341492,"2 sold"], 
["Thu, 27 Jun 2013 01:00:00 +0000",8.79045295715,"3 sold"], 
["Fri, 28 Jun 2013 01:00:00 +0000",10,"1 sold"]];\s*$''' 
>>> values = re.findall(r'var.*?=\s*(.*?);', j, re.DOTALL | re.MULTILINE) 
>>> for value in values: 
...  print(json.loads(value)) 
[[['Wed, 12 Jun 2013 01:00:00 +0000', 22.4916114807, '2 sold'], 
    ['Fri, 14 Jun 2013 01:00:00 +0000', 27.4950008392, '2 sold'], 
    ['Sun, 16 Jun 2013 01:00:00 +0000', 19.5499992371, '1 sold'], 
    ['Tue, 18 Jun 2013 01:00:00 +0000', 17.25, '1 sold'], 
    ['Sun, 23 Jun 2013 01:00:00 +0000', 15.5420341492, '2 sold'], 
    ['Thu, 27 Jun 2013 01:00:00 +0000', 8.79045295715, '3 sold'], 
    ['Fri, 28 Jun 2013 01:00:00 +0000', 10, '1 sold']]] 

:たとえば

  • 行末のセミコロンは、実際の文の区切りではなく、文字列の途中でなければなりません。 JSにはPythonスタイルの複数行文字列がないので、これは安全です。
  • JSではオプションですが、実際には各ステートメントの末尾にセミコロンがあります。ほとんどのJSコードはセミコロンを持っていますが、明らかに保証されていません。
  • 配列とオブジェクトのリテラルは、実際にJSONと互換性があります。これは間違いなく保証されています。たとえば、JSではシングルクォートの文字列を使用できますが、JSONでは使用できません。しかし、それはあなたの例のために働く。
  • 実際のフォーマットは、この定義が明確です。たとえば、コードの途中にvar line2 = [[1]] + line1;のようなステートメントがあると、問題が発生します。

データは、すべての有効なJSONではありませんが、(そうではありませんが、どちらか、不可能ではない)すべての有効なPythonのリテラルJavaScriptのリテラルが含まれている可能性がある場合は、あなたがast.literal_evalを使用することができますそれらはjson.loadsの代わりに。しかし、あなたがこれを知っていない限り、私はそれをしません。

+0

私は掻き集めているページはかなり整形されていると思いますが、余分な行1 =があれば、実際にはうまくいきません。 –

+0

あなたは 'line1 ='のどこかに浮遊していることを意味していますか、あるいは 'line1 ='の前に 'var'がないことを意味していますか?前者はちょうど一致してスキップされませんでしたが、これは問題ありません。後者は一致してスキップされませんが、うまくいかないかもしれません。それが問題なら、別の正規表現が必要です。正規表現は入力フォーマットを明確に定義できない限り適切ではありません。形式を推測しているだけなら、おそらくもっと冗長でもっと冗長なもの、おそらく実際のパーサーは 'pyparsing'で構築されていると思うでしょう。 – abarnert

+0

このプロジェクトはかなり明確に定義されているようですが、これが正規表現が機能する理由です。しかし、私は明らかに、私が掻き取ろうとしている他のすべてのページについては知りません。私はたぶん何かが壊れてそこから行くまで正規表現を使わなければならないでしょう。 –

関連する問題