Python: parse(date) 返回的有符号整数大于最大值

0 投票
3 回答
4255 浏览
提问于 2025-04-18 17:33

给定一个像下面这样的项目列表(列之间用制表符分隔):

  • 9123456780 \t John Dude \t City of Address \t 1980年7月19日 \t M
  • 9123456781 \t Jane Dudette \t Province of Address \t 1980年8月19日 \t f
  • 9123456782 \t Sam Pol Data \t Etc. City \t 1991年1月1日 \t
  • 9123456783 \t May Anaise \t Some City \t 1993年 \t f
  • 9123456784 \t Mark Mywards \t City of Address \t M
  • 9123456785 \t City of Address \t 1980年7月19日 \t M
  • 9123456780 \t M
  • Mira Nova \t City of Address \t 1980年7月19日

我需要确定哪个是MSISDN(10位数字)、姓名、地址、日期和性别。

我很确定这不可能做到100%正确,因为缺乏比较点,并且经常缺少数据。

所以我做了以下事情:

逐行遍历这个列表。每一行都用制表符(\t)分开,变成一个列表。然后在一个循环中测试列表中的每个项目:

for item in csv_cols:
    if reg_msisdn.match(item):
        s_msisdn = item
    if item.lower() in list_male or item.lower() in list_female:
        s_gender = item
    if parse(item):
        s_birthdate = item
    if any(ext in item.lower() for ext in list_place) or any(ext in item.lower() for ext in list_ad):
        s_address = item
    else:
        s_name = item

    s_all = s_msisdn + "^" + s_name + "^" + s_address + "^" + s_birthdate + "^" + s_gender

编辑:我在每个s_(value) = item之后添加了csv_cols.remove(item),这样测试过的项目就会被移除——但这并没有改变任何事情。

  1. 所有的s_(value)一开始都是NULL
  2. 如果任何项目是10位数字(用正则表达式检查),就认为它是s_msisdn
  3. 如果任何项目仅仅是m、f、male或female,就认为它是s_gender
  4. 如果任何项目包含关键词city、ave等(list_ad)或者与地点列表(list_place)中的某个项目匹配,就认为它是s_address
  5. 如果任何项目可以被解析为日期,就自动认为它是s_birthdate
  6. 否则,它可能s_name
  7. 编辑:从列表中移除该项目。
  8. 整个过程都在一个尝试-异常块中。

我很确定我的逻辑中会有明显的漏洞,但我真的想不到其他的办法。

话虽如此,即使有这样的杂乱逻辑,我也遇到了一些问题,特别是上面第5个项目,它不太好地返回了以下错误:

signed integer is greater than maximum

我知道这一点,因为把它从循环中拿出来后,其他代码就能正常工作了。

请问我能得到一些帮助吗?

谢谢。

附言:我在使用Mac/UNIX,如果这有什么意义的话。

3 个回答

0

试试这个:

if reg_msisdn.match(item):
        s_msisdn = item
    elif item.lower() in list_male or item.lower() in list_female:
        s_gender = item
    elif parse(item):
        s_birthdate = item
    elif any(ext in item.lower() for ext in list_place) or 
         any(ext in item.lower() for ext in list_ad):
        s_address = item
    else:
        s_name = item

你可能需要调整一下测试的顺序。这个想法是,一旦找到一个匹配的项目,其他的测试就不再进行。这也会提高速度。

1

它试图把你的 msisdn(手机号码)当作日期来解析,这样会引发一个错误,而不是返回假值,这就是为什么 if parse(...): 这种写法不管用的原因。你可以试试下面这种写法:

try:
    parse(item)
    continue
except ValueError:
    pass

(如果不是 ValueError,那就检查一下抛出的是什么类型的错误,然后用那个来处理)

1

在很多情况下,区分名字和地址几乎是不可能的(比如说"Jack Street"是名字还是地址呢?)。最好的办法是先假设名字总是在地址之前,这样就不用处理各种复杂的查找了。

我会逐行处理数据,首先把每一行转换成一个列表,像这样:

>>> row = "9123456780 \t John Dude \t City of Address \t July 19, 1980 \t M"
>>> row = [entry.strip() for entry in row.split("\t")]
>>> row
['9123456780', 'John Dude', 'City of Address', 'July 19, 1980', 'M']

接下来,我会定义一些函数,试着判断每个条目代表的是什么。确定MSISDN号码、性别和日期应该比较简单。

要判断一行中的某个条目是否是十位数的MSISDN号码,可以用以下方法:

import re

def is_msisdn(entry):
    if re.match(r"[0-9]{10}", entry):
         return True

要判断一行中的某个条目是否表示性别,可以用以下方法:

def is_gender(entry):
    if entry in ("m", "f", "M", "F"):
         return True

要判断一行中的某个条目是否表示日期,可以用以下方法:

from dateutil.parser import parse

def is_date(entry):
    try: 
        parse(entry)
        return True
    except ValueError:
        return False

现在,利用这些函数来构建另一个函数,解析这一行的条目:

def parse_row(row):

    s_all = ["<blank>"] * 5

    for entry in row:

        if is_msisdn(entry):
            s_all[0] = entry

        elif is_gender(entry):
            s_all[4] = entry

        elif is_date(entry):
            s_all[3] = entry

        elif s_all[1] == "<blank>":
            s_all[1] = entry

        else:
            s_all[2] = entry

    return " ^ ".join(s_all)

这样就可以得到例如:

>>> row = ['Mira Nova', 'City of Address', 'July 19, 1980']
>>> parse_row(row)
'<blank> ^ Mira Nova ^ City of Address ^ July 19, 1980 ^ <blank>'

>>> row = ['9123456784', 'Mark Mywards', 'City of Address', 'M']
>>> parse_row(row)
'9123456784 ^ Mark Mywards ^ City of Address ^ <blank> ^ M'

撰写回答