0

urllib が有効な % エンコードされた文字列のみを引用解除できるようにする方法は?

html_parser = HTMLParser.HTMLParser()
url = 'Time-@#*%ed%20&'
print urllib2.unquote(url)
print html_parser.unescape(url)

結果は

Time-@#*� &
Time-@#*%ed%20&

urllib は '%20' を ' ' に引用解除しますが、'%ed' を '�' に引用解除するのも間違っています

HTMLParser は「&」をエスケープできます '&' に変換できますが、'%20' を ' ' に変換できません

- - - - - - - 編集 - - -

私の質問をうまく説明できなかったことをお詫びします。実際、処理する文字列がたくさんあります。URL もそうでないものもあります。元の文字列は ですが、両方の状況を含むようにTime-@#*%ed文字列を にしました。Time-@#*%ed%20&1 行のコードで両方の状況を処理するのは難しいことがわかりました。答えを読んだ後、私は自分の関数を書きます

#!/bin/env python
#coding: utf8

import sys
import os
import HTMLParser
import re
import urllib

html_parser = HTMLParser.HTMLParser()
url_pattern = re.compile('^(ftp|http|https)://.{4,}', flags=re.I)
def unquote_string(url):
    if url_pattern.search(url):
        while True:
            url1 = urllib.unquote(url)
            if url1 == url: break
            url = url1
    else:
        while True:
            url1 = html_parser.unescape(url)
            if url1 == url: break
            url = url1

    return url

url = 'Time-@#*%ed%20&'
print urllib.unquote(url)
print html_parser.unescape(url)
print unquote_string(url)
4

3 に答える 3

3

問題は%ed ed有効な 16 進値であるため、有効な % エンコード文字であることです。%をそのままにしておく場合は、%またはとしてエンコードする必要があります%。したがって、実際の問題は、url文字列が正しくエンコードされていないことです。%edそのままにしておく場合、文字列は次のようにする必要があります。

url = 'Time-@#*%ed%20&'

正しくエンコードされていないため (ところで、どうやって入手したのですか?)、標準ツールに正しくデコードできるように依頼することはできません。%20処理する必要があるが、処理してはならないことをどのように知ることができ%edますか?

その時点でできる最善の方法は、カスタム デコーダーを作成することです。

url2 = url.replace('%20', ' ')
print html_parser.unescape(url2)

を与える:

Time-@#*%ed &
于 2015-01-05T06:47:42.590 に答える
2

&html entityURL ではなく、html ページで使用するためのものです。そのurl unquotingため、動作しません。

一方、%ed%20url escapes、URL の一部として転送するためにフォーマットされているため、html unescaping動作しません。

HTML エンティティと URL エスケープの両方を変換する場合は、各シーケンスを個別に処理する必要があります。

import urllib 
import HTMLParser
import re

html_parser = HTMLParser.HTMLParser()

data = 'Time-@#*%ed%20&'

pattern = r"""
      %               #Match a '%' sign, followed by...
      [0-9a-f]{2}     #two hex digits..
    |               #OR
      &               #an ampersand, followed by... 
      .*?             #any character, 0 or more times, non-greedy, followed by...
      ;               #a semi-colon
"""

regex = re.compile(pattern, flags=re.X | re.I)

def replace_func(match_obj):
    match = match_obj.group(0)

    if match.startswith('%'):
        my_str = urllib.unquote(match)
        my_str = unicode(my_str, 'iso-8859-1').encode('utf-8')

    elif match.startswith('&'):
        unicode_str = html_parser.unescape(match)
        my_str = unicode_str.encode('utf-8')

    return my_str

result = re.sub(regex, replace_func, data)
print result

--output:--
Time-@#*í &

1 つの問題: 一連のランダムなバイトedを文字に変換するには、それらのバイトが文字を表すと想定されるエンコーディングを知っている必要があります。推測しただけですが、知っておく必要があります。そうしないと、通常、そのような文字列の変換を行うことができなくなります。

于 2015-01-05T06:46:39.617 に答える
1

unquote() によって返される文字列は、latin1 でエンコードされます。これを試して:

import urllib2
url = 'Time-@#*%ed%20&'
x = urllib2.unquote(url)
u = x.decode('iso-8859-1')
print u

uユニコード文字列になります。

Wikipedia のパーセント エンコーディングに関するページ(リンク)x.decode('utf-8')によると、パーセント エンコーディングは UTF-8 データのエンコードにも使用される可能性があるため、代わりに使用する必要がある場合があります。それはすべて、このデータがどこから来ているか、およびコンテキストに依存します。

于 2015-01-05T06:51:15.580 に答える