parse.unquote_plus类型错误

1 投票
2 回答
1095 浏览
提问于 2025-04-15 15:39

我正在尝试格式化一个文件,以便可以将其插入到数据库中。这个文件最开始是压缩的,大小大约是1.3MB。

每一行的内容大概是这样的:

398,%7EAnoniem+001%7E,543,480,7525010,1775,0

这是用来解析这个文件的代码:

   Village = gzip.open(Root+'\\data'+'\\' +str(Newest_Date[0])+'\\' +str(Newest_Date[1])+'\\' +str(Newest_Date[2])\
               +'\\'+str(Newest_Date[3])+' village.gz');
Village_Parsed = str
for line in Village:
    Village_Parsed = Village_Parsed + urllib.parse.unquote_plus(line);
print(Village.readline());

当我运行这个程序时,出现了这个错误:

Village_Parsed = Village_Parsed + urllib.parse.unquote_plus(line);

文件 "C:\Python31\lib\urllib\parse.py",第404行,在unquote_plus中 字符串 = 字符串.replace('+', ' ') 类型错误:期望一个具有缓冲区接口的对象

你知道这里出了什么问题吗?非常感谢任何帮助 :)

2 个回答

2

问题1是,urllib.unquote_plus不喜欢你传给它的line。它的提示信息应该是“请提供一个字符串对象” :-) 我建议你先解决下面的问题2,然后在你的for语句后面插入:

print('line', type(line), repr(line))

这样你就可以看到line里到底是什么内容。

你会发现它返回的是字节对象:

>>> [line for line in gzip.open('test.gz')]
[b'nudge nudge\n', b'wink wink\n']

使用'r'模式几乎没有效果:

>>> [line for line in gzip.open('test.gz', 'r')]
[b'nudge nudge\n', b'wink wink\n']

我建议你不要直接把line传给解析程序,而是传line.decode('UTF-8')...或者使用写入gz文件时用的编码。

问题2出现在这一行:

Village_Parsed = str

str是一个类型。你需要一个空的字符串对象。要得到这个,你可以调用这个类型,也就是str(),这在形式上是正确的,但和直接用字符串常量''相比,显得不太实用/不太常见/有点可笑/奇怪……所以这样做:

Village_Parsed = ''

你还有问题3:你最后的语句试图在文件结束后继续读取gz文件。

0
import gzip, os, urllib.parse

archive_relpath = os.sep.join(map(str, Newest_Date[:4])) + ' village.gz'  
archive_path = os.path.join(Root, 'data', archive_relpath)

with gzip.open(archive_path) as Village:
    Village_Parsed = ''.join(urllib.parse.unquote_plus(line.decode('ascii'))
                             for line in Village)
    print(Village_Parsed)

输出:

398,~Anoniem 001~,543,480,7525010,1775,0

注意:RFC 3986 - 统一资源标识符 (URI):通用语法中提到:

这个规范并没有规定任何特定的字符编码来将URI字符和用于存储或传输这些字符的字节进行映射。当URI出现在协议元素中时,字符编码由该协议定义;如果没有这样的定义,URI会被假定为与周围文本使用相同的字符编码。

所以在line.decode('ascii')这段代码中,'ascii'应该替换成你用来编码文本的字符编码。

撰写回答