2015-01-05 55 views
0

如何讓urllib只引用有效的%編碼字符串?python urllib無法引用損壞

html_parser = HTMLParser.HTMLParser() 
url = '[email protected]#*%ed%20&' 
print urllib2.unquote(url) 
print html_parser.unescape(url) 

結果是

[email protected]#*� & 
[email protected]#*%ed%20& 

的urllib引文結束 '%20' '',但它也錯引文結束 '%ED' 到 ''

的HTMLParser能逃脫「&安培; 「爲 '&',但它不能將 '%20' ''

--------------編輯------

我道歉不能很好地解釋我的問題,實際上我有很多字符串需要處理,有些是URL,有些則不是。原始字符串是[email protected]#*%ed,我將字符串設爲[email protected]#*%ed%20&以包含這兩種情況。事實證明,很難在一行代碼中處理這兩種情況。閱讀的答案後,我寫我自己的函數

#!/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 = '[email protected]#*%ed%20&' 
print urllib.unquote(url) 
print html_parser.unescape(url) 
print unquote_string(url) 

回答

3

問題是%ed有效的%編碼字符,因爲ed是一個有效的十六進制值。如果%要保持不變,則應將其編碼爲%%。所以你真正的問題是,你url字符串編碼不正確:如果%ed要保持不變,該字符串應該是:(?順便說一句,你是怎麼得到它)

url = '[email protected]#*%ed%20&' 

由於它的編碼不正確你不能要求標準工具能夠正確解碼。如何能夠知道%20必須處理,但%ed不得?

在這一點上,你可以做的最好的是建立一個自定義的解碼器。

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

其給出:

[email protected]#*%ed & 
+0

看起來我混淆了'%'和'&':-(。Post updated –

1

&是在HTML頁面中使用html entity - 不是在一個URL。所以url unquoting將無法​​正常工作。

在另一方面,%ed%20url escapes格式與運輸爲URL的一部分,因此html unescaping不會對他們的工作。

如果你既想HTML實體和URL逃逸轉換,就需要分別處理每個序列:

import urllib 
import HTMLParser 
import re 

html_parser = HTMLParser.HTMLParser() 

data = '[email protected]#*%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:-- 
[email protected]#*í & 

一個問題:隨機字節序列轉換像ed到一個角色,你必須知道這些字節應該表示字符的編碼。我只是猜測 - 但你必須知道,否則你通常不能做這樣的字符串轉換。

1

通過引文結束()返回的字符串是latin1的編碼。試試這個:

import urllib2 
url = '[email protected]#*%ed%20&' 
x = urllib2.unquote(url) 
u = x.decode('iso-8859-1') 
print u 

u將是一個unicode字符串。

根據百分比編碼的百科頁面(link)百分比編碼也可用於編碼UTF-8數據,因此您可能需要使用x.decode('utf-8')來代替。這一切都取決於這些數據來自何處和上下文。