【问题标题】:Python Inserting Unwanted CharactersPython插入不需要的字符
【发布时间】:2013-06-21 12:46:56
【问题描述】:

我正在尝试使用 Python 生成一组 HTML 表格,其中包含从 CSV 中提取的值。该脚本运行良好,但是它会在任何拉入值的地方添加奇数的“¬†”字符。

这是我用来抓取 CSV 数据的代码:

import csv
import fileinput
import re

out=open("audiencestats.csv","rU")
data=csv.reader(out)
values =[row for row in data]
metrics = values.pop(0) 
out.close()

这会创建一个函数来制作 html 表格:

def maketable(leftmetric, rightmetric, leftvalue, rightvalue):
  template = '''
  <table width="99%%" border="1"> 
   <tbody>
    <tr>
    <td align="center" valign="middle">
    <h3>%s</h3>
    </td>
    <td align="center" valign="middle">
    <h3>%s</h3>
    </td>
    </tr>
    <tr>
    <td align="center" valign="middle"> %s</td>
    <td align="center" valign="middle"> %s</td>
    </tr>
    </tbody>
  </table>
  '''
  file.write(template % (leftmetric, rightmetric, leftvalue, rightvalue))

然后将表格写入文本文件:

for i in values:
  filename = "%s.txt" % i[0]
  file = open(filename , 'w')
  file.write(header)
  maketable(metrics[1],metrics[2],i[1],i[2])
  maketable(metrics[3],metrics[4],i[3],i[4])
  maketable(metrics[5],metrics[6],i[5],i[6])
  maketable(metrics[7],metrics[8],i[7],i[8])
  maketable(metrics[9],metrics[10],i[9],i[10])
  maketable(metrics[11],metrics[12],i[11],i[12])
  file.write(header2)
  print makesocial(i[13],i[14],i[15])
  file.close()

我尝试将下面的 re.sub 添加到 for 循环中,但十字仍然存在。

for line in fileinput.input(inplace=1):
    line = re.sub(' ','', line.rstrip())
    print(line)

我错过了什么吗?我的电脑变成宗教了吗?

下面也复制了输出示例:

<h1>Audience</h1>
  <table width="99%" border="1"> 
   <tbody>
    <tr>
    <td align="center" valign="middle">
    <h3>UVs (000)</h3>
    </td>
    <td align="center" valign="middle">
    <h3>PVs (000)</h3>
    </td>
    </tr>
    <tr>
    <td align="center" valign="middle"> 580.705</td>
    <td align="center" valign="middle"> 1003</td>
    </tr>
    </tbody>
  </table>

【问题讨论】:

  • 它是某种 Unicode 货币符号吗? CSV 文件中有什么内容?这两个字符的二进制值是多少?
  • 这听起来像是编码问题。 CSV 文件采用什么编码?您可以将其上传(一小部分)到某处,还是将其作为二进制文件和print(' '.join(hex(ord(c)) for c in f.readline())) 或类似文件打开?
  • 另外,你为什么要尝试使用re.sub 来替换固定的子字符串?只需使用 str.replace 即可。
  • 另外,您可能正在使用 Python 2.x。如果是这样,将非 ASCII 字符放入像 '¬†' 这样的非 Unicode 文字中是一个非常非常糟糕的主意,将非 ASCII 字符放入没有 encoding declaration 的源文件中是一个更糟糕的主意,以及更糟糕的想法是将它们放入源文件而不知道(并在您的问题中提及)您的文本编辑器使用什么编码。
  • csv是一行表头,然后是30行左右的数据,看起来是这样的:name,metric1,metric2,metric3john,a,b,c,dbill,e,f,g,hharry,i,j,k,l

标签: python html regex html-table import-from-csv


【解决方案1】:

您的数据没有任何问题——它是纯 ASCII。问题出在您的源代码中。

单击“编辑”按钮复制您的实际源代码,而不是格式化的源代码,它在 template 字符串文字的中间有不间断空格 (U+00A0) 字符。

假设您的编辑器和您从中复制和粘贴到的浏览器运行正常,这意味着您的实际 UTF-8 源代码具有 '\xc2\xa0' 序列。

由于您将非 ASCII 字符放入 str/bytes 文字中(正如我在另一个答案中解释的那样,总是是个坏主意),这意味着您的字符串以 '\xc2\xa0' 序列结尾。

在屏幕和屏幕之间的某个地方,还有一个额外的编码问题,这会被混淆成'\xc2\xac\xe2\x80\xa0' 序列——当解释为 UTF-8 时,会显示为 u'¬†'

我们可以尝试找出额外问题的来源,但这并不重要。

直接的解决方法是将源代码中的所有不间断空格替换为纯 ASCII 空格。

除此之外,您还需要弄清楚您正在使用什么来生成这些不间断的空间。通常,这是在文字处理器而不是文本编辑器中编辑源代码的标志;如果是这样,请停止这样做。

如果您实际上没有任何故意非 ASCII 源代码,那么在文件顶部使用 # coding=ascii 而不是 # coding=utf-8 是捕获此类错误的好方法。 (您仍然可以处理 UTF-8 值;所有编码声明都说源代码本身是 UTF-8。)

【讨论】:

  • 太棒了!明白了。如果您在 maketable 函数中查看上面的源代码,那么在读取 &lt;td align="center" valign="middle"&gt; %s&lt;/td&gt; 的行上有一个额外的空格 %s 之前的空格被转换为叉号。非常感谢!
【解决方案2】:

你还没有回答我为澄清这一点而提出的问题,所以我在这里猜测一下。

首先,您的 re.sub 不起作用的原因是您的模式是 UTF-8 ¬† ('\xc2\xac\xe2\x80\xa0'),但您尝试匹配 cp1252 ¬† ('\xac\x86') .显然,这些不匹配。

其次,您首先收到垃圾的原因是您的 CSV 文件正在由不使用 UTF-8 的东西处理,即使您认为它是。可能是您的电子表格程序、文本编辑器或命令行工具。

很可能,您只是在链上的某个步骤将一种 8 位编码与另一种混合在一起——将一些文本写为 cp1252,然后尝试将其编辑为 UTF-8,反之亦然。

但是 很有趣。那是U+2020。如果您有一些 UTF-16-LE 文本,并将其编辑为 UTF-8(或 ASCII 或 cp1252),并尝试添加一对空格,那么您实际上添加了一个 U+2020。通常,您会认为很难混淆 UTF-16 和 UTF-8。但很明显,您只是在注视文本,而不是实际查看字节,如果您的所有数据都符合 Latin-1,那么 UTF-16 对您的眼球来说看起来非常好——当然,每个真实的后面都有一个不可见的 NUL 字符角色,但你看不到看不见的东西。

无论如何,确切的细节是什么并不重要。解决这个问题的唯一方法是查看链上每个步骤生成的文件中的实际字节,找出你做错的地方,并适当地修复它。如果您不知道如何完成其​​中的任何部分,则需要向其他人提供足够的信息来为您完成。

但是,如果您只想快速解决问题:将您输入 Python 脚本的文件放入十六进制编辑器中查看。找到这两个垃圾字符,并记录它们是什么字节。如果他们是ac 86,只需更改您的代码以执行s = s.replace('\xac\x86', '')

【讨论】:

  • 感谢您的深入分析,很有启发性。我在十六进制编辑器(Hex Fiend)中打开了 CSV,但没有看到乱码。所有数据点都由逗号分隔的“2C”分隔,但没有 ¬† 的痕迹。我也尝试替换 '\xac\x86' 和 '\xc2\xac\xe2\x80\xa0' 但字符仍然显示。这是我通过将 csv 作为二进制文件打开并按照您的建议运行 print(' '.join(hex(ord(c)) for c in f.readline())) 得到的几行十六进制代码。我已经在下一条评论中发布了它们。
  • 0x32 0x25 0x2c 0x33 0x30 0x2e 0x37 0x36 0x33 0x2c 0x38 0x33 0x2e 0x35 0x30 0x38 0x2c 0x33 0x31 0x35 0x2e 0x34 0x36 0x39 0x2c 0x38 0x32 0x25 0x2c 0x2c 0x2c 0x2c 0x2c 0x35 0x36 0x2c 0x35 0x37 0x38 0x39 0x2c 0x37 0x37 0x38 0x30 0xd 0x50 0x6f 0x74 0x68 0x6f 0x6c 0x65 0x73 0x20 0x49 0x6e 0x20 0x4d 0x79 0x20 0x42 0x6c 0x6f 0x67 0x2c
  • 文件中没有奇怪的字符(它以Potholes In My Blog,结尾,如果有帮助的话)。特别是,这仍然是第一行的一部分,用于metrics 而不是i,奇怪的字符似乎出现在i 值中,所以......你能发布某个地方的整个文件,还是比这更大的初始片段的十六进制转储?
  • 当然,试试这个链接:cl.ly/text/280a1U1N1D44 这是保存到 .txt 的整个十六进制转储,除非有更好的方法来保存十六进制值而无需担心编码。
  • 这就够了;您总是可以在 Python 交互式解释器中以单行方式对它进行 unhexlify(对于这种格式,[int(x, 16) for x in s.split()] 有效)。无论如何,任何地方都没有非 ASCII (>0x7f) 字符,所以……我不知道问题出在哪里。我会尝试对它运行你的代码,看看当我有机会时会发生什么。
【解决方案3】:

试试这个:

line = re.sub(r'(?u) ','', line.rstrip())

然后正则表达式将您的字符串视为 unicode。

【讨论】:

  • re.UNICODE/?u 标志所做的只是改变了内置字符类的含义。见the docs。此外,将?u 与非Unicode 模式字符串一起使用通常是个坏主意。
猜你喜欢
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 2011-02-16
  • 2020-04-08
  • 1970-01-01
相关资源
最近更新 更多