【问题标题】:Transform hard coded initialization values to CSV将硬编码的初始化值转换为 CSV
【发布时间】:2013-06-23 16:38:21
【问题描述】:

我想使用 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,以最大限度地独立于输入脚本代码的排序和格式

【问题讨论】:

    标签: python parsing csv code-generation


    【解决方案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,最后一个是唯一存储的。

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

    干杯!

    【讨论】:

      【解决方案2】:

      如果这是你必须经常做的事情,并且你想让这个过程完全自动化,我认为最简单的方法就是使用 Python 解析文件,然后使用 csv Python module 写入 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)
      

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

      【讨论】:

      • 感谢您的建议,但我想按照问题更新中的建议解析这些语句以获得最大的独立性。
      【解决方案3】:

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

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

      要进行搜索,请使用findall:

      compPattern = re.compile(pattern)
      results = compPattern.findall(compPattern)
      

      【讨论】:

        猜你喜欢
        • 2021-01-23
        • 1970-01-01
        • 2015-03-18
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多