问题:我试图从中收集数据的网站使用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字典格式。
我想我可以用字符串读取它,然后使用XPATH和一些时髦的字符串编辑来转换它,但这对于已经格式化为Javascript变量的东西来说似乎太多了。
那么,在使用python时,我可以在这里从这个变量中提取这种类型的有组织数据? (我最熟悉python和BS4)
答案 0 :(得分:7)
如果您的格式只是一个或多个var foo = [JSON array or object literal];
,您可以编写一个dotall正则表达式来提取它们,然后将每个格式解析为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']]]
当然这会做出一些假设:
var line2 = [[1]] + line1;
之类的语句,则会导致问题。请注意,如果数据可能包含并非所有有效JSON的JavaScript文字,但都是有效的Python文字(这不太可能,但也不是不可能),您可以使用ast.literal_eval
在他们而不是json.loads
。但除非你知道情况确实如此,否则我不会这样做。
答案 1 :(得分:4)
好的,有几种方法可以做到,但我最后只是使用正则表达式查找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)
#evaluate list as python code => turn into list in python
newParsed = eval(parsed[0])
当你有良好的编码时,正则表达式很好,但这种方法比这里的任何其他答案更好(编辑:或更糟!)?
编辑:我最终使用了以下内容:
#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])
答案 2 :(得分:0)
以下做了一些假设,例如了解页面的格式,但是在 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
答案 3 :(得分:-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
设置为带有列表的列表。
而且你可以使用这样的东西:
for list in line1:
print(list[0], list[1], list[2])
# Or do something else with those values, like save them to a file