11

PythonでURLを正規化するライブラリ関数を探しています。つまり、パスの「./」または「../」の部分を削除したり、デフォルトのポートを追加したり、特殊文字をエスケープしたりします。結果は、同じWebページを指す2つのURLに固有の文字列になります。たとえば、http://google.comhttp://google.com:80/a/../は同じ結果を返します。

私はPython3を好み、すでにurllibモジュールを調べました。URLを分割する機能を提供しますが、それらを正規化する機能はありません。JavaにはURI.normalize()同様のことを行う機能がありますが(デフォルトのポート80は特定のポートがないとは見なされませんが)、Pythonのようなものはありますか?

4

6 に答える 6

4

これはどう:

In [1]: from urllib.parse import urljoin

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

この質問への回答に触発されました。ポートを正規化することはありませんが、正規化する関数を作成するのは簡単なはずです。

于 2012-05-14T16:34:01.517 に答える
4

これは私が使用しているもので、これまでのところ機能しています。pip から urlnorm を取得できます。

クエリ パラメータを並べ替えていることに注意してください。これが不可欠であることがわかりました。

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, ''))
于 2013-03-26T04:56:52.143 に答える
2

古い(廃止された)回答

[メンテナンスされなくなった] urltoolsモジュールは、複数のスラッシュ...コンポーネントを標準化しますhttp://

実行すると(作成者がレポの名前を変更したため、これは機能しなくなりました)、使用方法は次のとおりです。pip install urltools

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

モジュールは pip でインストールできなくなりましたが、単一のファイルであるため、その一部を再利用できます。

Python3 の更新された回答

Python3の場合は、モジュールurljoinからの使用を検討してください。urllib.urlparse

from urllib.parse import urljoin

urljoin('https://stackoverflow.com/questions/10584861/', '../dinsdale')
# Out[17]: 'https://stackoverflow.com/questions/dinsdale'
于 2016-06-11T17:01:04.180 に答える
0

良いスタートに続いて、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,
    ''))
于 2012-05-19T13:29:26.447 に答える