Python: parse(date) 返回的有符号整数大于最大值
给定一个像下面这样的项目列表(列之间用制表符分隔):
- 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)
,这样测试过的项目就会被移除——但这并没有改变任何事情。
- 所有的
s_(value)
一开始都是NULL
。 - 如果任何项目是10位数字(用正则表达式检查),就认为它是
s_msisdn
。 - 如果任何项目仅仅是m、f、male或female,就认为它是
s_gender
。 - 如果任何项目包含关键词city、ave等(list_ad)或者与地点列表(list_place)中的某个项目匹配,就认为它是
s_address
。 - 如果任何项目可以被解析为日期,就自动认为它是
s_birthdate
。 - 否则,它可能是
s_name
。 - 编辑:从列表中移除该项目。
- 整个过程都在一个尝试-异常块中。
我很确定我的逻辑中会有明显的漏洞,但我真的想不到其他的办法。
话虽如此,即使有这样的杂乱逻辑,我也遇到了一些问题,特别是上面第5个项目,它不太好地返回了以下错误:
signed integer is greater than maximum
我知道这一点,因为把它从循环中拿出来后,其他代码就能正常工作了。
请问我能得到一些帮助吗?
谢谢。
附言:我在使用Mac/UNIX,如果这有什么意义的话。
3 个回答
试试这个:
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
你可能需要调整一下测试的顺序。这个想法是,一旦找到一个匹配的项目,其他的测试就不再进行。这也会提高速度。
它试图把你的 msisdn(手机号码)当作日期来解析,这样会引发一个错误,而不是返回假值,这就是为什么 if parse(...): 这种写法不管用的原因。你可以试试下面这种写法:
try:
parse(item)
continue
except ValueError:
pass
(如果不是 ValueError,那就检查一下抛出的是什么类型的错误,然后用那个来处理)
在很多情况下,区分名字和地址几乎是不可能的(比如说"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'