【问题标题】:Extracting data by regex and writing to CSV, Python glob (pandas?)通过正则表达式提取数据并写入 CSV、Python glob(熊猫?)
【发布时间】:2014-02-27 14:59:56
【问题描述】:

我有一个包含各种格式的电话号码的各种脏 CSV 列表。我想要的是梳理所有这些并以简单的格式导出到已清理电话号码的单列 CSV。到目前为止,我已经拼凑了一些工作,虽然它有一些问题:(部分修订如下)

import csv
import re
import glob
import string

with open('phonelist.csv', 'wb') as out:
    seen = set()
    output = []
    out_writer = csv.writer(out)
    csv_files = glob.glob('CSVs\*.csv')
    for filename in csv_files:
        with open(filename, 'rbU') as ifile:
            read = csv.reader(ifile)
            for row in read:
                for column in row:
                    s1 = column.strip()
                    if re.match(r'\b\d\d\d\d\d\d\d\d\d\d\b', s1):
                        if s1 not in seen:
                            seen.add(s1)
                            output.append(s1)
                    elif re.search(r'\b\(\d\d\d\) \d\d\d-\d\d\d\d\b', s1):
                        s2 = filter(lambda x: x in string.digits, s1)
                        if s2 not in seen:
                            seen.add(s2)
                            output.append(s2)
    for val in output:
        out_writer.writerow([val])

我在没有正式的 Python 知识的情况下将这些放在一起,只是拼凑我在这个网站上收集到的东西。任何关于 pythonic 风格化或使用 pandas 库的快捷方式的建议都将受到欢迎。

第一个问题:过滤到匹配值的最简单方法是什么? IE,我可能会得到9815556667 John Smith,但我只想要号码。

第二个问题:这需要很长时间。我认为这是 lambda 部分。有没有更快或更有效的方法?

第三个问题:我如何在程序目录和 CSVs 目录(写的)中 glob *.csv?

我知道这同时是几个问题,但我半途而废。任何额外的指针表示赞赏。


例如,请求,这不是来自文件(这些是数 GB 的文件),但这是我正在寻找的:

John Smith, (981) 991-0987, 9987765543 extension 541, 671 Maple St 98402
(998) 222-0011, 13949811123, Foo baR Us, 2567 Appleberry Lane
office, www.somewebpage.com, City Group, Anchorage AK
9281239812
(345) 666-7777

应该变成:

9819910987
9987765543
9982220011
3949811123
3456667777

(我忘了我也需要从 11 位数字中去掉前导 1)


编辑:我已更改当前代码以纳入 Shahram 的建议,所以现在,从上面的 for column in row,我有,而不是上面:

for column in row:
    s1 = column.strip()
    result = re.match(
        r'.*(\+?[2-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)? ?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1) or re.match(
        r'.*(\+?[2-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)?-?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1)
    if result:
        tempStr = result.group(1)
        for ch in ['(', ')', '-', ' ']:
            tempStr = tempStr.replace(ch, '')
        if tempStr not in seen:
            seen.add(tempStr)
            output.append(tempStr)

这似乎适用于我的目的,但我仍然不知道如何 glob 当前目录和子目录,我仍然不知道我的代码是否存在我不知道的问题,因为我的大杂烩-跳槽。此外,在我较大的目录中,这需要很长时间 - 例如,大约 20 分钟左右的 CSV 演出对我来说(由我的手)超时。我不知道它是否遇到了障碍,但从 python 通常咀嚼任意数量的 CSV 的速度来看,感觉就像我错过了一些东西。

【问题讨论】:

  • Eagle 的视角:\d+ 似乎是正则表达式的最佳方式,但请参阅 this 了解为什么这不是一个好主意...
  • 您可以在某处上传示例 csv 或在此处发布几行吗?

标签: python regex python-2.7 csv pandas


【解决方案1】:

关于您的第一个问题,您可以使用下面的正则表达式来捕获不同类型的电话号码:

  result = re.match(r'.*(\+?[0-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)?-?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1)
  if result:
    if result.group(1) not in seen:
       seen.add(result.group(1))
       output.append(result.group(1))

关于你的第二个问题:你可能想看看替换功能。所以上面的代码可以改成:

  result = re.match(r'.*(\+?[0-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)?-?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1)
  if result:
    if result.group(1) not in seen:
       tempStr = result.group(1)
       tempStr.replace('-','')
       seen.add(tempStr)
       output.append(tempStr)

【讨论】:

  • 这个例子严重遗漏了我使用的最常见的例子:例如(998) 222-0011 因为空间。不过,我对result = re.match( r'.*(\+?[2-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)? ?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1) or re.match( r'.*(\+?[2-9]?[0-9]?[0-9]?-?\(?[0-9][0-9][0-9]\)?-?[0-9][0-9][0-9]-?[0-9][0-9][0-9][0-9]).*', s1) 很幸运——事实上,我会根据这个效果进行编辑。
猜你喜欢
  • 2018-09-06
  • 2017-04-24
  • 2021-11-06
  • 2020-01-15
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 2019-05-26
相关资源
最近更新 更多