2012-05-14 36 views
9

Tôi đang tìm một chức năng thư viện để chuẩn hóa một URL bằng Python, để loại bỏ các phần "./" hoặc "../" trong đường dẫn hoặc thêm cổng mặc định hoặc thoát các ký tự đặc biệt, v.v. Kết quả phải là một chuỗi duy nhất cho hai URL trỏ đến cùng một trang web. Ví dụ: http://google.comhttp://google.com:80/a/../ sẽ trả về cùng một kết quả.Canonicalize/bình thường hóa URL?

Tôi thích Python 3 và đã xem qua mô-đun urllib. Nó cung cấp các chức năng để phân tách các URL nhưng không có gì để chuẩn hóa chúng. Java có chức năng URI.normalize() thực hiện một điều tương tự (mặc dù nó không xem xét cổng mặc định 80 bằng không có cổng đã cho), nhưng có điều gì đó như thế này là python không?

+0

Là một lưu ý phụ, một nguồn tài nguyên như 'http: // google.com /' là không giống nhau hơn 'http: // google .com: 80/a /../ '. Nghĩa là, nếu '/ a' không tồn tại, thì đường thứ hai sẽ thất bại. Bởi "canonicalizing" nó, bạn bị mất trường hợp đặc biệt và kết thúc với một URI hợp lệ khi bạn bắt đầu với một không hợp lệ ... –

Trả lời

0

Theo sau good start, tôi đã soạn một phương thức phù hợp với hầu hết các trường hợp thường thấy trong web.

def urlnorm(base, link=''): 
    '''Normalizes an URL or a link relative to a base url. URLs that point to the same resource will return the same string.''' 
    new = urlparse(urljoin(base, url).lower()) 
    return urlunsplit((
    new.scheme, 
    (new.port == None) and (new.hostname + ":80") or new.netloc, 
    new.path, 
    new.query, 
    '')) 
4

Làm thế nào về điều này:

In [1]: from urllib.parse import urljoin 

In [2]: urljoin('http://example.com/a/b/c/../', '.') 
Out[2]: 'http://example.com/a/b/' 

Lấy cảm hứng từ câu trả lời cho this question. Nó không bình thường hóa các cổng, nhưng nó sẽ được đơn giản để whip lên một chức năng mà không.

+0

Tôi không có 'urllib.parse', nhưng tôi có' urlparse'. – osa

+3

'urllib.parse' là vị trí Python 3 - câu hỏi ban đầu được hỏi về Py 3. –

4

Đây là những gì tôi sử dụng và nó đã hoạt động cho đến nay. Bạn có thể lấy urlnorm từ pip.

Lưu ý rằng tôi sắp xếp các tham số truy vấn. Tôi đã tìm thấy điều này là cần thiết.

from urlparse import urlsplit, urlunsplit, parse_qsl 
from urllib import urlencode 
import urlnorm 

def canonizeurl(url): 
    split = urlsplit(urlnorm.norm(url)) 
    path = split[2].split(' ')[0] 

    while path.startswith('/..'): 
     path = path[3:] 

    while path.endswith('%20'): 
     path = path[:-3] 

    qs = urlencode(sorted(parse_qsl(split.query))) 
    return urlunsplit((split.scheme, split.netloc, path, qs, '')) 
+0

tốt đẹp, loại bỏ thư mục cha không hợp lệ – hoju

+0

Bạn cần thay thế' split [2] .split ('') [0] 'bằng' urllib.parse.quote (split [2]) '- trong một số trường hợp, có khoảng trống trong URL là hoàn toàn bình thường và trên thực tế là bắt buộc. Ngoài ra, urlnorm cũng chỉ là py2k –

+0

Ngoài ra, bạn đang loại bỏ phân đoạn, mà thực sự có thể là thành phần URL bắt buộc, trong một số trường hợp bất thường. Có, có một số không khác các trang web trong đó 'blah.com/# wat' là một trang hoàn toàn khác, sau đó là' blah.com/'. Nó thường được thực hiện với javascript, và là một PITA khổng lồ, nhưng nó tồn tại. –

2

Module urltools bình thường hóa nhiều dấu gạch chéo, ... thành phần mà không rối tung lên các dấu gạch chéo đôi trong http://.

Khi bạn làm pip install urltools việc sử dụng như sau:

print urltools.normalize('http://domain.com:80/a////b/../c') 
>>> 'http://domain.com/a/c'