一些基本的Python问题

5 投票
4 回答
2709 浏览
提问于 2025-04-15 11:08

我对Python完全是个新手,请多多包涵。我想让Python扫描一个HTML页面,把里面的Microsoft Word字符替换成UTF-8兼容的格式。

我的问题是,怎么在Python中做到这一点呢?我在网上查过,但到现在为止还没找到清晰的答案。我想先试试Python,所以觉得像这样的简单任务是个不错的开始。看起来我需要:

  1. 把从MS Word复制的文本加载到一个变量里
  2. 对这些内容运行某种替换功能
  3. 输出结果

在PHP中,我会这样做:

$test = $_POST['pasted_from_Word']; //for example “Going Mobile”

function defangWord($string) 
{
    $search = array(
        (chr(0xe2) . chr(0x80) . chr(0x98)),
        (chr(0xe2) . chr(0x80) . chr(0x99)),
        (chr(0xe2) . chr(0x80) . chr(0x9c)), 
        (chr(0xe2) . chr(0x80) . chr(0x9d)), 
        (chr(0xe2) . chr(0x80) . chr(0x93)),
        (chr(0xe2) . chr(0x80) . chr(0x94)), 
        (chr(0x2d))
    ); 

    $replace = array(
        "‘",
        "’",
        "“",
        "”",
        "–",
        "—",
        "–"
    );

    return str_replace($search, $replace, $string); 
} 

echo defangWord($test); 

那在Python中该怎么做呢?

编辑:嗯,暂时忽略我对UTF-8和字符实体的困惑。输入的内容是从MS Word复制的文本。像是弯引号这样的字符显示成了奇怪的符号。我用的各种PHP函数都没能给我想要的结果。通过在十六进制编辑器中查看那些奇怪的符号,我发现它们对应的就是我上面提到的符号(0xe2, 0x80等等)。所以我只是把那些奇怪的字符换成了HTML实体。那么,如果我上面提到的内容已经是UTF-8格式,从MS Word粘贴进来的东西为什么会导致出现奇怪的符号呢?

编辑2:所以我开始学习一些Python,发现我对编码的理解其实不太够。我想解决的问题其实可以通过确保从头到尾的编码一致来简单处理。如果输入是UTF-8,存储输入的数据库是UTF-8,输出的页面也是UTF-8……从Word粘贴的内容就能正常工作。根本不需要特殊的函数。现在,关于学习一点Python的事……

4 个回答

2

如果你想清理从Word导出的HTML代码,最好的办法就是使用HTML Tidy这个工具,它专门有一个模式来处理这个问题。如果你想通过编程的方式来做这件事,还有一些Python的封装库可以使用。

3

这个Python代码的结构是一样的。

只需要把所有的PHP相关的部分换成Python相关的部分。

首先要创建一个文件对象。调用file.read()的结果是一个字符串对象。字符串有一个“替换”的操作。

20

首先,这些不是微软Word的东西,它们 UTF-8格式的字符。你正在把它们转换成HTML实体。

用Python写这样的代码:

chr(0xe2) . chr(0x80) . chr(0x98)

更好的写法是:

'\xe2\x80\x98'

不过,Python本身就有内置的功能,可以帮你完成你想要的转换:

def defang(string):
    return string.decode('utf-8').encode('ascii', 'xmlcharrefreplace')

这个功能会把字符串中的UTF-8代码,比如,替换成像“这样的数字实体。

如果你想把这些数字实体尽可能替换成有名字的实体,可以这样做:

import re
from htmlentitydefs import codepoint2name

def convert_match_to_named(match):
    num = int(match.group(1))
    if num in codepoint2name:
        return "&%s;" % codepoint2name[num]
    else:
        return match.group(0)

def defang_named(string):
    return re.sub('&#(\d+);', convert_match_to_named, defang(string))

然后这样使用它:

>>> defang_named('\xe2\x80\x9cHello, world!\xe2\x80\x9d')
'“Hello, world!”'

为了完整回答你的问题,处理文件的代码大概是这样的:

# in Python, it's common to operate a line at a time on a file instead of
# reading the entire thing into memory

my_file = open("test100.html")
for line in my_file:
    print defang_named(line)
my_file.close()

请注意,这个回答是针对Python 2.5的;在Python 3及以上版本中,Unicode的处理方式有很大不同。

我也同意bobince下面的评论:如果你能保持文本为UTF-8格式,并且发送时使用正确的内容类型和字符集,那就这样做;如果你需要用ASCII格式,那就继续使用数字实体——其实没必要使用有名字的实体。

撰写回答