web-dev-qa-db-ja.com

pythonでURLを正規化するにはどうすればよいですか?

PythonでURLを正規化することを知りたいです。

たとえば、次のようなURL文字列がある場合: " http://www.example.com/foo goo/bar.html"

pythonのライブラリが必要です。これは、余分なスペース(またはその他の正規化されていない文字)を適切なURLに変換します。

70
Tom Feiner

このモジュールをご覧ください: werkzeug.utils 。 (今 werkzeug.urls

探している関数は「url_fix」と呼ばれ、次のように機能します。

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

次のようにWerkzeugに実装されています。

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))
68
Armin Ronacher

Python 2.7その問題の実際の修正

正しい解決策は次のとおりです。

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

詳細については、 Issue918368: "urllibはサーバーが返すURLを修正しません" を参照してください。

58
Oleg Sakharov

_urllib.quote_または_urllib.quote_plus_を使用します

rllibドキュメント から:

quote(string [、safe])

「%xx」エスケープを使用して、stringの特殊文字を置き換えます。文字、数字、および文字「_.-」は引用されません。オプションのsafeパラメーターは、引用符で囲まない追加の文字を指定します。デフォルト値は「/」です。

例:quote('/~connolly/')は_'/%7econnolly/'_を生成します。

quote_plus(string [、safe])

Quote()に似ていますが、HTMLフォームの値を引用するために必要に応じて、スペースをプラス記号に置き換えます。元の文字列のプラス記号は、セーフに含まれていない限りエスケープされます。また、安全なデフォルトの「/」もありません。

編集:@ΤΖΩΤΖΙΟΥが指摘しているように、URL全体にurllib.quoteまたはurllib.quote_plusを使用すると、URLが破損します。

_>>> 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
_

@ΤΖΩΤΖΙΟΥは、 rlparse.urlparseおよびurlparse.urlunparse を使用してURLを解析し、パスのみをエンコードする関数を提供します。これはあなたにとってより便利かもしれませんが、既知のプロトコルとホストからURLを構築しているが、疑わしいパスを使用している場合、urlparseを避け、URLの疑わしい部分を引用して、既知の安全な部品。

24
Blair Conrad

このページは、トピックに関するGoogle検索の上位結果であるため、URLの正規化で行われた、Pythonはスペース文字のエンコードを超えたものです。デフォルトのポート、大文字と小文字、末尾のスラッシュがないなど。

Atomシンジケーションフォーマットが開発されていたとき、URLを正規フォーマットに正規化する方法についての議論がありました。これはAtom/Pieの記事 PaceCanonicalIds に記載されています。 wiki。その記事はいくつかの良いテストケースを提供します。

この議論の結果の1つは、Mark Nottinghamの rlnorm.py ライブラリであり、いくつかのプロジェクトで良い結果が得られたと思います。ただし、このスクリプトは、この質問で指定されたURLでは機能しません。したがって、より良い選択は Sam Rubyのurlnorm.pyのバージョン です。これはそのURLを処理し、前述のAtom wikiのテストケースのすべてです。

13
cobra libre

Py3

from urllib.parse import urlparse, urlunparse, quote
def myquote(url):
    parts = urlparse(url)
    return urlunparse(parts._replace(path=quote(parts.path)))

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/~user/with%20space/index.html?a=1&b=2'

Py2

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

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/%7Euser/with%20space/index.html?a=1&b=2'

これは、パスコンポーネントのみを引用しています。

9
tzot

ちなみに、urlnormはgithubに移動しました: http://Gist.github.com/246089

4
Mark Nottingham

有効なPython 3.5:

import urllib.parse

urllib.parse.quote([your_url], "\./_-:")

例:

import urllib.parse

print(urllib.parse.quote("http://www.example.com/foo goo/bar.html", "\./_-:"))

出力は http://www.example.com/foo%20goo/bar.html になります

フォント: https://docs.python.org/3.5/library/urllib.parse.html?highlight=quote#urllib.parse.quote

2
Hélder Lima

このような問題が発生しました。スペースのみを引用する必要があります。

fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]")は役立ちますが、複雑すぎます。

そこで、私は簡単な方法を使用しました:url = url.replace(' ', '%20')、それは完全ではありませんが、最も簡単な方法であり、この状況で機能します。

1
WKPlus