2008-09-23 13 views
64

Tôi muốn biết làm cách nào để chuẩn hóa URL trong python.Tôi có thể chuẩn hóa một URL trong python

Ví dụ, Nếu tôi có một chuỗi url như: "http://www.example.com/foo goo/bar.html có"

Tôi cần một thư viện trong python đó sẽ làm thay đổi không gian thêm (hoặc bất kỳ nhân vật không bình thường khác) vào một thích hợp URL.

+0

Có một câu trả lời cho nhật hơn trên StackOverflow tại đây: http://stackoverflow.com/questions/10584861/canonize-normali ze-an-url-in-python/15629657 – stuckintheshuck

+1

Tôi không nghĩ rằng đó là tốt hơn ... –

Trả lời

10
import urlparse, urllib 
def myquote(url): 
    parts= urlparse.urlparse(url) 
    return urlparse.urlunparse(parts[:2] + urllib.quote(parts[2]) + parts[3:]) 

Chỉ trích dẫn thành phần đường dẫn này.

Nếu không, bạn có thể làm: urllib.quote(url, safe=":/")

+2

Đó chỉ trích tất cả các ký tự. Điều đó sẽ không giúp anh ta. –

+0

Trong ví dụ này, nó cũng sẽ trích dẫn ký tự ':' (không phải tất cả). Cảm ơn bạn đã bình luận. – tzot

21

sử dụng urllib.quote hoặc urllib.quote_plus

Từ urllib documentation:

quote (string [, an toàn])

Thay thế ký tự đặc biệt trong chuỗi bằng cách sử dụng thoát "% xx". Các chữ cái, chữ số và các ký tự "_.-" là không bao giờ được trích dẫn. Thông số an toàn tùy chọn chỉ định thêm ký tự không được trích dẫn - giá trị mặc định của nó là '/'.

Ví dụ: quote('/~connolly/') sản lượng '/%7econnolly/'.

quote_plus (string [, an toàn])

Giống như quote(), mà còn thay thế không gian bởi dấu cộng, theo yêu cầu trích dẫn giá trị dạng HTML. Dấu cộng trong số chuỗi gốc được thoát trừ khi chúng được đưa vào an toàn. Nó cũng không có mặc định an toàn cho '/'.

EDIT: Sử dụng urllib.quote hoặc urllib.quote_plus trên toàn bộ URL sẽ mangle nó, như @ ΤΖΩΤΖΙΟΥ chỉ ra:

>>> quoted_url = urllib.quote('http://www.example.com/foo goo/bar.html') 
>>> quoted_url 
'http%3A//www.example.com/foo%20goo/bar.html' 
>>> urllib2.urlopen(quoted_url) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "c:\python25\lib\urllib2.py", line 124, in urlopen 
    return _opener.open(url, data) 
    File "c:\python25\lib\urllib2.py", line 373, in open 
    protocol = req.get_type() 
    File "c:\python25\lib\urllib2.py", line 244, in get_type 
    raise ValueError, "unknown url type: %s" % self.__original 
ValueError: unknown url type: http%3A//www.example.com/foo%20goo/bar.html 

@ ΤΖΩΤΖΙΟΥ cung cấp một chức năng sử dụng urlparse.urlparse and urlparse.urlunparse để phân tích url và chỉ mã hóa đường dẫn. Điều này có thể hữu ích hơn cho bạn, mặc dù nếu bạn đang xây dựng URL từ một giao thức và máy chủ đã biết nhưng với đường dẫn đáng ngờ, bạn có thể làm tốt để tránh urlparse và chỉ trích dẫn phần nghi ngờ của URL, nối với các bộ phận an toàn đã biết.

+2

Vì vậy, những gì hiện trở lại urllib.quote trao dụ url của câu hỏi? – tzot

+1

Rác. Tại sao một câu trả lời rõ ràng sai được chấp nhận là giải pháp? –

+0

@ ΤΖΩΤΖΙΟΥ: điểm tuyệt vời. Giải quyết @Armin Ronacher: có thể vì người trả lời và accepter đã không nhận thức được vấn đề - không phải tất cả các vấn đề được rõ ràng cho tất cả. –

66

Hãy xem mô-đun này: werkzeug.utils.(Nay thuộc werkzeug.urls)

Chức năng bạn đang tìm kiếm được gọi là "url_fix" và các công trình như thế này:

>>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)') 
'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29' 

Nó thực hiện trong Werkzeug như sau:

import urllib 
import urlparse 

def url_fix(s, charset='utf-8'): 
    """Sometimes you get an URL by a user that just isn't a real 
    URL because it contains unsafe characters like ' ' and so on. This 
    function can fix some of the problems in a similar way browsers 
    handle data entered by the user: 

    >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)') 
    'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29' 

    :param charset: The target charset for the URL if the url was 
        given as unicode string. 
    """ 
    if isinstance(s, unicode): 
     s = s.encode(charset, 'ignore') 
    scheme, netloc, path, qs, anchor = urlparse.urlsplit(s) 
    path = urllib.quote(path, '/%') 
    qs = urllib.quote_plus(qs, ':&=') 
    return urlparse.urlunsplit((scheme, netloc, path, qs, anchor)) 
+0

Trong khi điều này là từ một http rfc2616 có lẽ là giải pháp chính xác hơn, tôi nghĩ rằng đó là overkill, hoặc làm tôi bỏ lỡ một cái gì đó? –

+1

Có. Bạn có thể đã bỏ lỡ câu hỏi. Anh ta có một URL từ đầu vào của người dùng và muốn chuyển đổi nó thành URL thực. (Aka: làm những gì thanh vị trí firefox hiện) –

+3

'url_fix' hiện được đặt tại' werkzeug.urls' – sebpiq

55

Real fix in Python 2.7 for that problem

giải pháp phải là:

# percent encode url, fixing lame server errors for e.g, like space 
# within url paths. 
fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]") 

Để biết thêm thông tin, xem Issue918368: "urllib doesn't correct server returned urls"

+4

Câu trả lời xuất sắc, súc tích và hữu ích. Vì sự thay đổi này nằm bên trong urllib, mã muốn thực hiện tương tự nên 'import urllib' và gọi' urllib.quote() 'với các tham số ở trên. –

+0

Barfs này trên thư ä, nhưng tôi cho nó bỏ phiếu của tôi gây ra nó đơn giản, và không requite nào khác nhập khẩu. – mlissner

+0

hoạt động như sự quyến rũ! exaclty những gì tôi đã tìm kiếm –

12

Bởi vì trang này là kết quả hàng đầu cho Google tìm kiếm về chủ đề này, tôi nghĩ rằng nó có giá trị nhắc đến một số công việc đã được thực hiện trên bình thường URL với Python mà đi xa hơn các nhân vật không gian urlencoding. Ví dụ: xử lý các cổng mặc định, vỏ ký tự, thiếu dấu gạch chéo, v.v.

Khi định dạng cung cấp Atom được phát triển, đã có một số thảo luận về cách chuẩn hóa URL thành định dạng chuẩn; điều này được ghi lại trong bài viết PaceCanonicalIds trên wiki Atom/Pie. Bài viết đó cung cấp một số trường hợp thử nghiệm tốt.

Tôi tin rằng một kết quả của cuộc thảo luận này là thư viện urlnorm.py của Mark Nottingham, mà tôi đã sử dụng với kết quả tốt trên một vài dự án. Tuy nhiên, tập lệnh đó không hoạt động với URL được đưa ra trong câu hỏi này. Vì vậy, một lựa chọn tốt hơn có thể là Sam Ruby's version of urlnorm.py, mà xử lý URL đó, và tất cả các trường hợp thử nghiệm nói trên từ wiki Atom.

1

tôi gặp phải một vấn đề như: cần phải trích dẫn không gian mà thôi.

fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]") làm giúp đỡ, nhưng nó quá phức tạp.

Vì vậy, tôi đã sử dụng một cách đơn giản: url = url.replace(' ', '%20'), nó không hoàn hảo, nhưng đó là cách đơn giản nhất và nó hoạt động cho tình huống này.