2013-08-21 2 views
9

문제 : 데이터를 수집하려고하는 웹 사이트에서 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을 사용하고 있음을 알았지 만, 형식이 약간 다르기 때문에이 특정 문제에 적용하는 방법을 잘 모르겠습니다. 사실,이 문제에서 코드는 JSON 사전 형식의 모든 유형보다 Python과 비슷하게 보입니다.

문자열로 읽은 다음 XPATH와이를 변환하는 펑키 문자열 편집을 사용한다고 가정합니다. 그러나 이것은 이미 Javascript 변수로 포맷 된 것에 대해서는 너무 많은 작업처럼 보입니다.

그래서이 변수에서이 유형의 구성 데이터를 가져 오려면 어떻게해야합니까? 다음은 페이지를 포맷하는 방법을 알고 같은 몇 가지 가정을

+0

을'='후 줄 바꿈과'var' 키워드를 제외하고, 나머지는 파이썬 –

+0

에서 유효 실제 코드가? 또는리스트의리스트 인'line1'이라는 변수입니까? 만약 후자라면'do_something_with (list [0], list [1], list2])의''line1 'list에 대해서'' – IPDGino

+0

'은 load의 페이지 내용의 일부인 line1이라는 변수이고 list 목록. –

답변

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= 사이 ; 모든 것을 찾을 수있는 정규 표현식을 사용하여 종료되지만, 이 방법은 (편집 : 또는 더 나쁜!) 다른 답변보다 여기에?

편집 : 나는 궁극적으로 다음과 같은 사용 :인가

#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'처럼 좀 더 제한적인 것을 사용하는 것이 거의 항상 더 좋습니다. 물론, 완벽하게 안전하고 (abc '+'def '와 같은) 리터럴이 아니더라도 작동하는 Python 코드로서 유효 할 수 있지만, 적어도 표현식을 실행할 가능성은 있습니다 이는 파이썬과 다른 무언가를 의미하거나 심지어 안전하지 않은 무언가를 의미합니다.(누군가가'var line1 = __ import __ ('os') 시스템 ('rm -rf ~ /')'...)을 주면 어떻게되는지 상상해보십시오. – abarnert

-1

(I 파이썬과 BS4와 가장 잘 알고)하지만, 파이썬의 메모리로 예를 얻기의 방법이

# 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'을 사용하지 않을 것입니다. 유효한 파이썬 리터럴을 다루고 싶다면'ast.literal_eval'을 사용하십시오. 하지만 당신은 그럴 필요조차하지 않습니다. – abarnert

+0

당신은 기본적으로 내가 염두에 두었던 것과 똑같은 것을 가지고 있었지만, 대신에 정규 표현식을 사용했습니다. 비록 내가 eval을 사용하여 결국 ... –

-1

"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]; 더, 당신은 단지 그들을 추출하는 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

당신은 정말로 세미콜론을 제거 할 필요가 없습니다; 파이썬에서 문장을 분리하는 것만으로도 유효 문장 구분 기호가됩니다. 그러나 더 중요한 것은, 변수 이름이'a_line' 일 수 있다면'strip ("var;")'은 위험 할 것입니다 ... – abarnert

+0

더 중요한 것은, JS를 파이썬으로 변형시키고 실행하는 것입니다. 정말 해키하고 안전하지 않아. 똑같은 경우 똑같은 경우 안전하게 작동 할 것입니다. 오른쪽에 'ast.literal_eval'을 호출하면 훨씬 안전 할 것이고, 원하는 곳에 변수를 저장할 수 있습니다 (예 : dict에서) 지역 주민들에게 강요하는 대신에 (당신이 원하는 것은 거의 없습니다). – abarnert

6

, 다음 JSON 각 하나를 구문 분석합니다. 이 몇 가지 가정을 물론

>>> 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는 파이썬 스타일의 다중 행 문자열을 가지고 있지 않기 때문에 안전해야합니다.
  • JS에서는 선택 사항이지만 실제로 코드의 끝에는 세미콜론이 있습니다. 대부분의 JS 코드에는 세미콜론이 있지만 분명히 보장 할 수는 없습니다.
  • 배열 및 객체 리터럴은 실제로 JSON과 호환됩니다. 이것은 확실히 보장되지 않습니다. 예를 들어 JS는 작은 따옴표로 묶인 문자열을 사용할 수 있지만 JSON은 사용할 수 없습니다. 하지만 그것은 당신의 예를 위해 작동합니다.
  • 형식이 실제로 잘 정의되어 있습니다. 예를 들어, 코드 중간에 var line2 = [[1]] + line1;과 같은 명령문이 있으면 문제가 발생할 것입니다. 데이터가 모든 유효한 JSON 아니지만, (중, 가능성이 아니라, 불가능하지 않은) 모든 유효한 파이썬 리터럴 자바 스크립트 리터럴을 포함 할 수 있다면, 당신은에 ast.literal_eval를 사용할 수있는

주 대신 json.loads.그러나 당신이 이것을 알지 못한다면 나는 그것을하지 않을 것입니다.

+0

오른쪽. 나는 긁어 모으고있는 페이지가 꽤 잘 포맷되어 있다고 생각하지만, 여분의 라인 1을 = 어딘가에 가지고있는 것이 실제로 엉망이 될 것입니다. –

+0

길잃은'line1 ='어딘가, 또는 전에'var'없이'line1 ='을 갖는 것을 의미합니까? 전자는 일치하지 않고 건너 뛸 수 있습니다. 괜찮습니다. 후자는 또한 일치하지 않고 건너 뛸 수 있지만 괜찮지 않을 수도 있습니다. 그게 문제라면 다른 정규식이 필요합니다. 입력 형식을 명확하게 정의 할 수 없다면 정규식은 적절하지 않습니다. 형식을 추측하고 있다면 아마도 좀 더 느슨하고 좀더 장황한 것을 원할 것입니다. 아마도 실제 파서가'pyparsing '에 내장되어있을 것입니다. – abarnert

+0

이 프로젝트가 꽤 명확하게 정의되어있는 것처럼 보입니다. 이것이 정규식이 작동 한 이유입니다. 그러나, 나는 분명히 긁어 모으려는 다른 모든 페이지에 대해 알지 못합니다. 아마 뭔가 잘못 될 때까지 정규 표현식을 사용해야 할 것입니다. –

관련 문제