1

使用 Python,我想从一堆包含硬编码数据的 javascript 文件中提取下面显示的数据行到 csv 文件,如下所示:

....html 代码....

酒店[0] = 新酒店数据();
酒店[0].hotelName = "曼哈顿";
酒店[0].hotelPhone = "";
酒店[0].hotelSalesPhone = "";
Hotels[0].hotelPhone = '电话:888-350-6432 
'; 酒店[0].hotelStreet = "11 大道 787 号"; 酒店[0].hotelCity = "纽约"; 酒店[0].hotelState = "纽约"; 酒店[0].hotelZip = "10019"; 酒店[0].hotelId = "51543"; 酒店[0].hotelLat = "40.7686";; 酒店[0].hotelLong = "-73.992645";; 酒店[1] = 新酒店数据(); 酒店[1].hotelName = "KOEPPEL"; 酒店[1].hotelPhone = ""; 酒店[1].hotelSalesPhone = ""; Hotels[1].hotelPhone = '电话:718-721-9100
'; Hotels[1].hotelStreet = "57-01 NORTHERN BLVD."; 酒店[1].hotelCity = "WOODSIDE"; 酒店[1].hotelState = "纽约"; 酒店[1].hotelZip = "11377"; 酒店[1].hotelId = "51582"; 酒店[1].hotelLat = "40.75362";; 酒店[1].hotelLong = "-73.90366";; var mykey = "AlvQ9gNhp7oNuvjhkalD4OWVs_9LvGHg0ZLG9cWwRdAUbsy-ZIW1N9uVSU0V4X-8"; 变种地图=空; var pin = null; 变量我 = 空; var box = new Array(); var currentBox = null; var mapOptions = { 凭据:mykey, enableSearchLogo:假, 显示地图类型选择器:假, enableClickableLogo: 假 } .....html代码......

因此,所需的 csv 输出将类似于上述数据的行:

曼哈顿,,,电话:888-350-6432 ...
科佩尔,,,电话:718-721-9100 ...

我应该使用代码生成工具直接解析上述语句来获取数据吗?将数千个 Javascript 文件中包含的此类数据转换为 csv 表格格式的最有效 Python 方法是什么?

更新:

理想情况下,我希望解决方案将 JavaScript 语句解析为 Python 对象,然后将其存储到 CSV 以获得最大程度的独立于输入脚本代码的排序和格式

4

3 回答 3

1

我建议使用正则表达式来挑选所有“hotel[#]. ...”行,然后将所有结果添加到字典中。然后,使用字典,输出到 CSV 文件。以下应该有效:

import re
import csv


src_text = your_javascript_text
p = re.compile(r'hotels\[(?P<hotelid>\d+)\].(?P<attr>\w+) = ("|\')(?P<attr_val>.*?)("|\');', re.DOTALL)

hotels = {}
fieldnames = []
for result in [m.groupdict() for m in p.finditer(src_text)]:
    if int(result['hotelid']) not in hotels:
        hotels[int(result['hotelid'])] = {}
    if result['attr'] not in fieldnames:
        fieldnames.append(result['attr'])

    hotels[int(result['hotelid'])][result['attr']] = result['attr_val']

output = open('hotels.csv','wb')
csv_writer = csv.DictWriter(output, delimiter=',', fieldnames=fieldnames, quoting=csv.QUOTE_ALL)
csv_writer.writerow(dict((f,f) for f in fieldnames))
for hotel in hotels.items():
    csv_writer.writerow(hotel[1])

您现在有一个带有属性的酒店字典,按 Javascript 中的 ID 分组,以及输出文件“hotels.csv”(带有标题行和适当的转义)。我确实做了一些真正没有必要的命名组之类的事情,但发现它更具自我评论性。

需要注意的是,如果同一个组在 Javascript 中提供了两次,比如hotelPhone,最后一个是唯一存储的。

在处理此类问题时,您需要判断自己需要多大的容忍度和卫生条件。您可能需要修改正则表达式以处理未提供的小样本的示例(即更改捕获组,将匹配限制为行首的匹配等);或转义换行符,如电话号码中的那些);或删除某些文本(例如,电话号码中的“电话:”)。我们没有真正的方法知道这一点,所以请记住这一点。

干杯!

于 2013-06-26T17:06:33.520 回答
0

如果这是你必须经常做的事情,并且你想让这个过程完全自动化,我认为最简单的方法就是使用 Python 解析文件,然后使用csv Python 模块写入 csv 。

您的代码可能看起来像这样:

with open("datafile.txt") as f:
    hotel_data = []
    for line in f:
        # Let's make sure the line not empty
        if line:
            if "new hotelData();" in line:
                if hotel_data:
                    write_to_csv(hotel_data)
                    hotel_data = []
        else:
            # Data, still has ending quote and semi colon
            data = line.split("= ")[1]
            # Remove ending quote and semi colon 
            data = data[:-2]
            hotel_data.append(data)

def write_to_csv(hotel_data):
    with open('hotels.csv', 'wb') as csvfile:
        spamwriter = csv.writer(csvfile, delimiter=',',
                                quotechar='""', quoting=csv.QUOTE_MINIMAL)

        spamwriter.writerow(hotel_data)

请注意,我没有测试此代码,它只是为了帮助您并为您指明正确的方向,它不是完整的解决方案。

于 2013-06-26T14:05:35.840 回答
0

如果每个酒店都在文件中声明了每个字段(即,如果所有酒店的行数相同,即使其中一些是空的),您可以尝试使用简单的正则表达式来提取用引号括起来的每个值 ( “xxx”),然后按数字分组(例如,将每 5 个字段分组为一行,然后添加换行符)。

一个可以工作的简单正则表达式是["'][^"']*["'](编辑:这是因为我看到一些文件(即电话)使用单引号,其余使用引号)。

要进行搜索,请使用findall

compPattern = re.compile(pattern)
results = compPattern.findall(compPattern)
于 2013-06-26T14:06:32.933 回答