urllib.parse --- تجزیه URLها به کامپوننت‌ها

کد منبع: Lib/urllib/parse.py


این ماژول یک رابط استاندارد را برای تجزیه‌ی رشته‌های مکان‌یاب منبع یکپارچه (URL) به کامپوننت‌ها (طرح‌واره آدرس‌دهی، محل شبکه، مسیر و غیره)، ترکیب مجدد کامپوننت‌ها به یک رشته‌ی URL، و تبدیل یک «URL نسبی» به یک URL مطلق با توجه به یک «URL پایه» تعریف می‌کند.

این ماژول برای مطابقت با RFC اینترنتی مربوط به Relative Uniform Resource Locators طراحی شده است. این ماژول از طرح‌های URL زیر پشتیبانی می‌کند: file، ftp، gopher، hdl، http، https، imap، itms-services، mailto، mms، news، nntp، prospero، rsync، rtsp، rtsps، rtspu، sftp، shttp، sip، sips، snews، svn، svn+ssh، telnet، wais، ws، wss.

گنجاندن طرح‌واره URL itms-services می‌تواند مانع از پذیرفته شدن یک برنامه در فرآیند بازبینی اپ‌استور اپل برای اپ‌استورهای macOS و iOS شود. مدیریت طرح‌واره itms-services همیشه در iOS حذف می‌شود؛ در macOS، ممکن است در صورتی حذف شود که CPython با گزینه‌ی --with-app-store-compliance ساخته شده باشد.

ماژول urllib.parse توابعی را تعریف می‌کند که به دو دسته کلی تقسیم می‌شوند: تجزیه‌ی URL و کدگذاری URL (URL quoting). این موارد در بخش‌های زیر با جزئیات پوشش داده شده‌اند.

توابع این ماژول از اصطلاح منسوخ‌شده netloc (یا net_loc) استفاده می‌کنند که در RFC 1808 معرفی شد. با این حال، این اصطلاح توسط RFC 3986 از رده خارج شده است، که اصطلاح authority را به‌عنوان جایگزین آن معرفی کرد. استفاده از netloc برای سازگاری با نسخه‌های پیشین ادامه دارد.

تجزیه‌ی URL

توابع تجزیه‌ی URL بر تقسیم یک رشته‌ی URL به کامپوننت‌های آن، یا ترکیب کامپوننت‌های URL در یک رشته‌ی URL تمرکز دارند.

urllib.parse.urlsplit(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False)

یک URL را به پنج جزء تجزیه می‌کند و یک تاپل نام‌دار ۵ عضوی به شکل SplitResult یا SplitResultBytes برمی‌گرداند. این ساختار با ساختار کلی یک URL مطابقت دارد: scheme://netloc/path?query#fragment. هر آیتم تاپل یک رشته است که احتمالاً خالی است، یا اگر مقدار missing_as_none برابر با درست (true) باشد، None است. اجزای تعریف‌نشده به صورت یک رشته‌ی خالی (به طور پیش‌فرض) یا اگر missing_as_none درست باشد به صورت None نمایش داده می‌شوند. جداکننده‌هایی که در بالا نشان داده شده‌اند بخشی از نتیجه نیستند، به جز یک اسلش پیشرو در جزء path که در صورت وجود حفظ می‌شود.

علاوه بر این، خصوصیت netloc به این ویژگی‌های اضافی که به شیء برگردانده‌شده افزوده شده‌اند، تفکیک می‌شود: username، password، hostname و port.

دنباله‌های کدگذاری‌شده با درصد کدگشایی نمی‌شوند.

برای مثال:

>>> from urllib.parse import urlsplit
>>> urlsplit("scheme://netloc/path?query#fragment")
SplitResult(scheme='scheme', netloc='netloc', path='/path',
            query='query', fragment='fragment')
>>> o = urlsplit("http://docs.python.org:80/3/library/urllib.parse.html?"
...              "highlight=params#url-parsing")
>>> o
SplitResult(scheme='http', netloc='docs.python.org:80',
            path='/3/library/urllib.parse.html',
            query='highlight=params', fragment='url-parsing')
>>> o.scheme
'http'
>>> o.netloc
'docs.python.org:80'
>>> o.hostname
'docs.python.org'
>>> o.port
80
>>> o._replace(fragment="").geturl()
'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params'
>>> urlsplit("http://docs.python.org?")
SplitResult(scheme='http', netloc='docs.python.org', path='',
            query='', fragment='')
>>> urlsplit("http://docs.python.org?", missing_as_none=True)
SplitResult(scheme='http', netloc='docs.python.org', path='',
            query='', fragment=None)

طبق مشخصات سینتکس در RFC 1808، urlsplit() تنها در صورتی یک netloc را تشخیص می‌دهد که به‌درستی با '//' معرفی شده باشد. در غیر این صورت، فرض می‌شود ورودی یک URL نسبی است و بنابراین با یک کامپوننت مسیر شروع می‌شود.

>>> from urllib.parse import urlsplit
>>> urlsplit('//www.cwi.nl:80/%7Eguido/Python.html')
SplitResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
            query='', fragment='')
>>> urlsplit('www.cwi.nl/%7Eguido/Python.html')
SplitResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html',
            query='', fragment='')
>>> urlsplit('help/Python.html')
SplitResult(scheme='', netloc='', path='help/Python.html',
            query='', fragment='')
>>> urlsplit('help/Python.html', missing_as_none=True)
SplitResult(scheme=None, netloc=None, path='help/Python.html',
            query=None, fragment=None)

آرگومان scheme طرح‌واره‌ی آدرس‌دهی پیش‌فرض را ارائه می‌دهد که فقط در صورتی استفاده می‌شود که URL یکی را مشخص نکرده باشد. این آرگومان باید از همان نوع (متن یا بایت) urlstring باشد یا None، با این تفاوت که '' همیشه مجاز است و در صورت لزوم به طور خودکار به b'' تبدیل می‌شود.

اگر آرگومان allow_fragments نادرست باشد، شناسه‌های قطعه (fragment) شناخته نمی‌شوند. در عوض، آن‌ها به عنوان بخشی از مسیر (path) یا جزء پرس‌وجو (query) تجزیه می‌شوند و fragment در مقدار بازگشتی روی None یا رشته‌ی خالی (بسته به مقدار missing_as_none) تنظیم می‌شود.

مقدار بازگشتی یک named tuple است، بدین معنا که می‌توان به آیتم‌های آن با اندیس یا به‌عنوان ویژگی‌های نام‌دار دسترسی داشت، که عبارتند از:

ویژگی

اندیس

مقدار

مقدار در صورت عدم وجود

scheme

0

مشخص‌کننده‌ی طرح‌واره URL

پارامتر scheme یا رشته‌ی خالی [1]

netloc

1

بخش موقعیت شبکه

مقدار None یا رشته‌ی خالی [1]

path

2

مسیر سلسله‌مراتبی

رشته خالی

query

3

کامپوننت پرس‌وجو

مقدار None یا رشته‌ی خالی [1]

fragment

۴

شناسه قطعه

مقدار None یا رشته‌ی خالی [1]

username

نام کاربری

None

password

گذرواژه

None

hostname

نام میزبان (حروف کوچک)

None

port

شماره‌ی پورت به‌صورت عدد صحیح، در صورت وجود

None

خواندن ویژگی port در صورتی که پورت نامعتبری در URL مشخص شده باشد، باعث پرتاب یک ValueError می‌شود. برای اطلاعات بیشتر درباره شیء نتیجه، بخش نتایج تجزیه‌ی ساختاریافته را ببینید.

کروشه‌های جفت‌نشده در ویژگی netloc باعث پرتاب یک ValueError می‌شود.

نویسه‌های موجود در ویژگی netloc که در نرمال‌سازی NFKC (که در رمزگذاری IDNA استفاده می‌شود) به هرکدام از /، ?، #، @ یا : تجزیه شوند، باعث ایجاد ValueError می‌شوند. اگر URL پیش از تجزیه، تجزیه‌ی نرمال‌سازی‌شده باشد، خطایی ایجاد نخواهد شد.

در پیروی از برخی از WHATWG spec که RFC 3986 را به‌روزرسانی می‌کند، نویسه‌های کنترلی C0 و نویسه‌های فاصله در ابتدای URL از URL حذف می‌شوند. نویسه‌های \n، \r و تب \t در هر جای URL از URL حذف می‌شوند.

همان‌طور که برای همه‌ی تیوپل‌های نام‌دار (named tuples) صدق می‌کند، این زیرکلاس چند متد و ویژگی اضافی دارد که به‌ویژه مفید هستند. یکی از این متدها _replace() است. متد _replace() یک شیء جدید SplitResult بازمی‌گرداند که فیلدهای مشخص‌شده در آن با مقادیر جدید جایگزین شده‌اند.

>>> from urllib.parse import urlsplit
>>> u = urlsplit('//www.cwi.nl:80/%7Eguido/Python.html')
>>> u
SplitResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
            query='', fragment='')
>>> u._replace(scheme='http')
SplitResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
            query='', fragment='')

هشدار

urlsplit() اعتبارسنجی انجام نمی‌دهد. برای جزئیات، امنیت تجزیه URL را ببینید.

تغییر یافته در نسخه‌ی 3.2: قابلیت‌های تجزیه‌ی URLهای IPv6 افزوده شد.

تغییر یافته در نسخه‌ی 3.3: قطعه (fragment) اکنون برای همه طرح‌های URL (مگر اینکه allow_fragments نادرست باشد)، مطابق با RFC 3986 تجزیه می‌شود. پیش‌تر، یک فهرست مجاز از طرح‌هایی که از قطعه‌ها پشتیبانی می‌کردند وجود داشت.

تغییر یافته در نسخه‌ی 3.6: شماره‌درگاه‌های خارج از محدوده اکنون به‌جای بازگرداندن None، خطای ValueError پرتاب می‌کنند.

تغییر یافته در نسخه‌ی 3.8: نویسه‌هایی که بر تجزیه‌ی netloc تحت نرمال‌سازی NFKC تأثیر می‌گذارند، اکنون ValueError پرتاب می‌کنند.

تغییر یافته در نسخه‌ی 3.10: نویسه‌های خط جدید و تب ASCII از URL حذف می‌شوند.

تغییر یافته در نسخه‌ی 3.12: نویسه‌های کنترلی C0 و فاصله‌ی WHATWG از ابتدای URL حذف می‌شوند.

تغییر یافته در نسخه‌ی 3.15: پارامتر missing_as_none اضافه شد.

urllib.parse.parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')

یک رشته‌ی کوئری داده‌شده به‌عنوان آرگومان رشته‌ای را تجزیه می‌کند (داده‌هایی از نوع application/x-www-form-urlencoded). داده‌ها به‌صورت یک دیکشنری بازگردانده می‌شوند. کلیدهای دیکشنری، نام‌های یکتای متغیرهای کوئری هستند و مقادیر، فهرست‌هایی از مقادیر برای هر نام هستند.

آرگومان اختیاری keep_blank_values پرچمی است که نشان می‌دهد آیا مقادیر خالی در کوئری‌های کدگذاری‌شده با درصد باید به‌عنوان رشته‌های خالی در نظر گرفته شوند یا خیر. مقدار درست نشان می‌دهد که مقادیر خالی باید به‌عنوان رشته‌های خالی حفظ شوند. مقدار پیش‌فرض نادرست نشان می‌دهد که مقادیر خالی باید نادیده گرفته شوند و به‌گونه‌ای با آن‌ها رفتار شود که گویی شامل نشده‌اند.

آرگومان اختیاری strict_parsing پرچمی است که مشخص می‌کند با خطاهای تجزیه چگونه برخورد شود. اگر نادرست باشد (پیش‌فرض)، خطاها به‌طور بی‌صدا نادیده گرفته می‌شوند. اگر درست باشد، خطاها یک استثنای ValueError را پرتاب می‌کنند.

پارامترهای اختیاری encoding و errors، همان‌گونه که متد bytes.decode() آن‌ها را می‌پذیرد، چگونگی کدگشایی دنباله‌های کدگذاری‌شده با درصد به نویسه‌های یونیکد را مشخص می‌کنند.

آرگومان اختیاری max_num_fields حداکثر تعداد فیلدهایی است که خوانده می‌شوند. اگر تنظیم شده باشد، در صورتی که بیش از max_num_fields فیلد خوانده شود، ValueError پرتاب می‌کند.

آرگومان اختیاری separator نمادی است که برای جداسازی آرگومان‌های پرس‌وجو به کار می‌رود. مقدار پیش‌فرض آن & است.

برای تبدیل چنین دیکشنری‌هایی به رشته‌های پرس‌وجو (query strings)، از تابع urllib.parse.urlencode() (با تنظیم پارامتر doseq روی True) استفاده کنید.

تغییر یافته در نسخه‌ی 3.2: افزودن پارامترهای encoding و errors.

تغییر یافته در نسخه‌ی 3.8: پارامتر max_num_fields افزوده شد.

تغییر یافته در نسخه‌ی 3.10: پارامتر separator با مقدار پیش‌فرض & افزوده شد. نسخه‌های پایتون پیش از پایتون 3.10 اجازه می‌دادند که از هر دو ; و & به‌عنوان جداکننده‌ی پارامتر کوئری استفاده شود. این رفتار تغییر کرده است تا تنها یک کلید جداکننده مجاز باشد، با & به‌عنوان جداکننده‌ی پیش‌فرض.

منسوخ شده از نسخه‌ی 3.14: پذیرفتن اشیایی با مقادیر کاذب (مانند 0 و []) به‌جز رشته‌های خالی، اشیاء شبه‌بایت و None اکنون منسوخ شده است.

urllib.parse.parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')

یک رشته‌ی پرس‌وجو (query string) را که به‌عنوان آرگومان رشته‌ای داده شده است، تجزیه می‌کند (داده‌هایی از نوع application/x-www-form-urlencoded). داده‌ها به‌صورت فهرستی از جفت‌های نام و مقدار بازگردانده می‌شوند.

آرگومان اختیاری keep_blank_values پرچمی است که نشان می‌دهد آیا مقادیر خالی در کوئری‌های کدگذاری‌شده با درصد باید به‌عنوان رشته‌های خالی در نظر گرفته شوند یا خیر. مقدار درست نشان می‌دهد که مقادیر خالی باید به‌عنوان رشته‌های خالی حفظ شوند. مقدار پیش‌فرض نادرست نشان می‌دهد که مقادیر خالی باید نادیده گرفته شوند و به‌گونه‌ای با آن‌ها رفتار شود که گویی شامل نشده‌اند.

آرگومان اختیاری strict_parsing پرچمی است که مشخص می‌کند با خطاهای تجزیه چگونه برخورد شود. اگر نادرست باشد (پیش‌فرض)، خطاها به‌طور بی‌صدا نادیده گرفته می‌شوند. اگر درست باشد، خطاها یک استثنای ValueError را پرتاب می‌کنند.

پارامترهای اختیاری encoding و errors، همان‌گونه که متد bytes.decode() آن‌ها را می‌پذیرد، چگونگی کدگشایی دنباله‌های کدگذاری‌شده با درصد به نویسه‌های یونیکد را مشخص می‌کنند.

آرگومان اختیاری max_num_fields حداکثر تعداد فیلدهایی است که خوانده می‌شوند. اگر تنظیم شده باشد، در صورتی که بیش از max_num_fields فیلد خوانده شود، ValueError پرتاب می‌کند.

آرگومان اختیاری separator نمادی است که برای جداسازی آرگومان‌های پرس‌وجو به کار می‌رود. مقدار پیش‌فرض آن & است.

برای تبدیل چنین فهرست‌هایی از جفت‌ها به رشته‌های پرس‌وجو، از تابع urllib.parse.urlencode() استفاده کنید.

تغییر یافته در نسخه‌ی 3.2: افزودن پارامترهای encoding و errors.

تغییر یافته در نسخه‌ی 3.8: پارامتر max_num_fields افزوده شد.

تغییر یافته در نسخه‌ی 3.10: پارامتر separator با مقدار پیش‌فرض & افزوده شد. نسخه‌های پایتون پیش از پایتون 3.10 اجازه می‌دادند که از هر دو ; و & به‌عنوان جداکننده‌ی پارامتر کوئری استفاده شود. این رفتار تغییر کرده است تا تنها یک کلید جداکننده مجاز باشد، با & به‌عنوان جداکننده‌ی پیش‌فرض.

urllib.parse.urlunsplit(parts)
urllib.parse.urlunsplit(parts, *, keep_empty)

یک نشانی‌وب از یک تاپلِ بازگردانده‌شده توسط urlsplit() می‌سازد. آرگومان parts می‌تواند هر شیء پیمایش‌پذیر پنج آیتمی باشد.

این کار ممکن است به یک URL کمی متفاوت اما معادل منجر شود، اگر URL که در ابتدا تجزیه شده است دارای جداکننده‌های غیرضروری بوده باشد (برای مثال، یک ? با پرس‌وجوی خالی؛ استاندارد RFC بیان می‌کند که این موارد معادل هستند).

اگر keep_empty برابر با True باشد، رشته‌های خالی در نتیجه حفظ می‌شوند (برای مثال، یک ? برای یک پرس‌وجو خالی)، و فقط اجزای None حذف می‌شوند. این کار بازسازی نشانی‌وب‌ای را که با گزینه‌ی missing_as_none=True تجزیه شده است، امکان‌پذیر می‌سازد. به طور پیش‌فرض، اگر parts نتیجه‌ی فراخوانی urlsplit() با missing_as_none=True باشد، keep_empty برابر با True است.

تغییر یافته در نسخه‌ی 3.15: پارامتر keep_empty اضافه شد.

urllib.parse.urlparse(urlstring, scheme=None, allow_fragments=True, *, missing_as_none=False)

این تابع مشابه urlsplit() است، اما علاوه بر آن، کامپوننت path را به path و params تقسیم می‌کند. این تابع یک named tuple ۶ آیتمی از نوع ParseResult یا ParseResultBytes برمی‌گرداند. آیتم‌های آن همان آیتم‌های نتیجه‌ی urlsplit() هستند، با این تفاوت که params در اندیس ۳، بین path و query درج شده است.

این تابع مبتنی بر RFC 1738 و RFC 1808 منسوخ‌شده است، که params را به‌عنوان کامپوننت اصلی URL فهرست کرده بودند. سینتکس جدیدتر URL اجازه می‌دهد پارامترها به هر بخش از قسمت path URL اعمال شوند (به RFC 3986 مراجعه کنید). به‌طور کلی باید به‌جای urlparse() از urlsplit() استفاده شود. برای جدا کردن بخش‌های مسیر و پارامترها، به تابع جداگانه‌ای نیاز است.

urllib.parse.urlunparse(parts)
urllib.parse.urlunparse(parts, *, keep_empty)

عناصر یک تاپلِ بازگردانده‌شده توسط urlparse() را به شکل یک رشته در قالب یک نشانی‌وب کامل ترکیب می‌کند. آرگومان parts می‌تواند هر شیء پیمایش‌پذیر شش آیتمی باشد.

این کار ممکن است به یک URL کمی متفاوت اما معادل منجر شود، اگر URL که در ابتدا تجزیه شده است دارای جداکننده‌های غیرضروری بوده باشد (برای مثال، یک ? با پرس‌وجوی خالی؛ استاندارد RFC بیان می‌کند که این موارد معادل هستند).

اگر مقدار keep_empty برابر با True باشد، رشته‌های خالی در نتیجه حفظ می‌شوند (برای مثال، یک ? برای یک پرس‌وجو خالی)، و فقط مؤلفه‌های None حذف می‌شوند. این کار امکان بازسازی یک URL که با گزینه‌ی missing_as_none=True تجزیه شده است را فراهم می‌کند. به‌طور پیش‌فرض، اگر parts نتیجه‌ی فراخوانی urlparse() با گزینه‌ی missing_as_none=True باشد، مقدار keep_empty برابر با True خواهد بود.

تغییر یافته در نسخه‌ی 3.15: پارامتر keep_empty اضافه شد.

urllib.parse.urljoin(base, url, allow_fragments=True)

با ترکیب یک «URL پایه» (base) با یک URL دیگر (url)، یک URL کامل («مطلق») بسازید. به‌طور غیررسمی، در این کار از کامپوننت‌های URL پایه، به‌ویژه طرح‌واره آدرس‌دهی، موقعیت شبکه و (بخشی از) مسیر، برای فراهم کردن کامپوننت‌های ناموجود در URL نسبی استفاده می‌شود. برای مثال:

>>> from urllib.parse import urljoin
>>> urljoin('http://www.cwi.nl/%7Eguido/Python.html', 'FAQ.html')
'http://www.cwi.nl/%7Eguido/FAQ.html'

آرگومان allow_fragments همان معنا و پیش‌فرض را دارد که برای urlsplit() وجود دارد.

نکته

اگر url یک URL مطلق باشد (یعنی با // یا scheme:// شروع شود)، نام میزبان و/یا طرح‌واره‌ی url در نتیجه وجود خواهد داشت. برای مثال:

>>> urljoin('http://www.cwi.nl/%7Eguido/Python.html',
...         '//www.python.org/%7Eguido')
'http://www.python.org/%7Eguido'

اگر آن رفتار را نمی‌خواهید، url را با urlsplit() و urlunsplit() پیش‌پردازش کنید و بخش‌های احتمالی scheme و netloc را حذف کنید.

هشدار

از آنجا که ممکن است یک نشانی وب مطلق (URL) به‌عنوان پارامتر url ارسال شود، استفاده از urljoin با url تحت کنترل مهاجم عموماً امن نیست. برای مثال، در urljoin("https://website.com/users/", username)، اگر username بتواند شامل یک نشانی وب مطلق باشد، نتیجه‌ی urljoin همان نشانی وب مطلق خواهد بود.

تغییر یافته در نسخه‌ی 3.5: رفتار به‌روزرسانی شد تا با معناشناسی تعریف‌شده در RFC 3986 مطابقت کند.

urllib.parse.urldefrag(url, *, missing_as_none=False)

اگر url شامل شناسه‌ی قطعه (fragment identifier) باشد، نسخه‌ی تغییریافته‌ای از url بدون شناسه‌ی قطعه، و شناسه‌ی قطعه را به عنوان یک رشته‌ی جداگانه برگردانید. اگر هیچ شناسه‌ی قطعه‌ای در url وجود نداشته باشد، url را دست‌نخورده و یک رشته‌ی خالی (به‌طور پیش‌فرض) یا اگر missing_as_none مقدار درست (true) باشد، None را برگردانید.

مقدار بازگشتی یک named tuple است؛ می‌توان به آیتم‌های آن با اندیس یا به‌عنوان ویژگی‌های نام‌دار دسترسی پیدا کرد:

ویژگی

اندیس

مقدار

مقدار در صورت عدم وجود

url

0

URL بدون قطعه (fragment)

رشته خالی

fragment

1

شناسه قطعه

مقدار None یا رشته‌ی خالی [3]

برای اطلاعات بیشتر درباره‌ی شیء نتیجه، بخش نتایج تجزیه‌ی ساختاریافته را ببینید.

تغییر یافته در نسخه‌ی 3.2: نتیجه یک شیء ساختاریافته است، نه یک تاپل دوتایی ساده.

تغییر یافته در نسخه‌ی 3.15: پارامتر missing_as_none اضافه شد.

urllib.parse.unwrap(url)

URL را از یک URL پوشیده‌شده استخراج می‌کند (یعنی رشته‌ای که به‌صورت <URL:scheme://host/path>، <scheme://host/path>، URL:scheme://host/path یا scheme://host/path قالب‌بندی‌شده باشد). اگر url یک URL پوشیده‌شده نباشد، بدون تغییر بازگردانده می‌شود.

امنیت تجزیه‌ی URL

APIهای urlsplit() و urlparse() اعتبارسنجی ورودی‌ها را انجام نمی‌دهند. ممکن است این APIها برای ورودی‌هایی که سایر برنامه‌ها آن‌ها را نامعتبر می‌دانند، خطا پرتاب نکنند. همچنین ممکن است برای برخی ورودی‌ها که ممکن است در جاهای دیگر به‌عنوان URL در نظر گرفته نشوند، با موفقیت عمل کنند. هدف آن‌ها عملکرد کاربردی است، نه خلوص.

آن‌ها به‌جای پرتاب کردن یک استثنا در ورودی‌های غیرمعمول، ممکن است برخی اجزا را به شکل رشته‌های خالی یا None برگردانند (بسته به مقدار آرگومان missing_as_none). یا ممکن است اجزا بیش از آنچه که احتمالاً باید، شامل اطلاعات باشند.

توصیه می‌کنیم کاربران این APIها، در مواردی که مقادیر ممکن است در هر جایی با پیامدهای امنیتی استفاده شوند، به‌صورت دفاعی کد بنویسند. پیش از اعتماد به یک کامپوننت بازگشتی، در کد خود مقداری اعتبارسنجی انجام دهید. آیا آن scheme منطقی است؟ آیا آن path معقول است؟ آیا مورد عجیبی درباره آن hostname وجود دارد؟ و غیره.

اینکه چه چیزی یک URL را تشکیل می‌دهد، به‌طور جهانی به‌خوبی تعریف نشده است. برنامه‌های کاربردی مختلف، نیازها و محدودیت‌های مطلوب متفاوتی دارند. برای نمونه، سند زنده‌ی WHATWG spec آنچه را کلاینت‌های وب رو به کاربر، مانند یک مرورگر وب، نیاز دارند توصیف می‌کند. در حالی که RFC 3986 کلی‌تر است. این توابع برخی جنبه‌های هر دو را در بر می‌گیرند، اما نمی‌توان ادعا کرد که با هیچ‌کدام از آن‌ها منطبق هستند. APIها و کد کاربر موجود با انتظارهایی نسبت به رفتارهای مشخص، پیش از هر دو استاندارد وجود داشته‌اند؛ این موضوع ما را در تغییر رفتار API بسیار محتاط می‌سازد.

تجزیه بایت‌های کدگذاری‌شده با ASCII

توابع تجزیه URL در ابتدا فقط برای کار با رشته‌های نویسه‌ای طراحی شده بودند. در عمل، مفید است که بتوان URLهایی را که به‌درستی نقل‌قول‌شده و کدگذاری‌شده‌اند، به‌صورت دنباله‌هایی از بایت‌های ASCII دستکاری کرد. بر همین اساس، توابع تجزیه URL در این ماژول همگی علاوه بر اشیاء str روی اشیاء bytes و bytearray نیز عمل می‌کنند.

اگر داده‌ای از نوع str ارسال شود، نتیجه نیز فقط شامل داده‌های str خواهد بود. اگر داده‌ای از نوع bytes یا bytearray ارسال شود، نتیجه فقط شامل داده‌های bytes خواهد بود.

تلاش برای ترکیب داده‌های str با bytes یا bytearray در یک فراخوانی تابع واحد، باعث پرتاب شدن TypeError می‌شود، در حالی که تلاش برای ارسال مقادیر بایتی غیر ASCII باعث پرتاب شدن UnicodeDecodeError می‌شود.

برای پشتیبانی از تبدیل آسان‌تر اشیای نتیجه بین str و bytes، همه‌ی مقادیر بازگشتی توابع تجزیه‌ی URL، یا یک متد encode() را ارائه می‌دهند (هنگامی که نتیجه شامل داده‌ی str باشد) یا یک متد decode() را (هنگامی که نتیجه شامل داده‌ی bytes باشد). امضای این متدها با امضای متدهای متناظر str و bytes مطابقت دارد (به‌جز اینکه کدگذاری پیش‌فرض 'ascii' است، نه 'utf-8'). هر یک مقداری از نوع متناظر تولید می‌کند که یا شامل داده‌ی bytes است (برای متدهای encode()) یا داده‌ی str (برای متدهای decode()).

برنامه‌های کاربردی که نیاز دارند URLهایی را پردازش کنند که ممکن است به‌طور نادرست نقل‌قول‌شده باشند و حاوی داده‌های غیر ASCII باشند، باید پیش از فراخوانی متدهای تجزیه‌ی URL، خود کدگشایی از بایت‌ها به نویسه‌ها را انجام دهند.

رفتار توصیف‌شده در این بخش فقط به توابع تجزیه‌ی URL اعمال می‌شود. توابع نقل‌قول URL (URL quoting) هنگام تولید یا مصرف دنباله‌های بایت از قوانین خود استفاده می‌کنند، همان‌طور که در مستندات هر یک از توابع نقل‌قول URL به تفصیل آمده است.

تغییر یافته در نسخه‌ی 3.2: توابع تجزیه‌ی URL اکنون دنباله‌های بایتی کدگذاری‌شده با ASCII را می‌پذیرند

نتایج تجزیه‌ی ساختاریافته

اشیاء نتیجه‌ی توابع urlsplit()، urlparse() و urldefrag() زیرکلاس‌هایی از نوع tuple هستند. این زیرکلاس‌ها ویژگی‌های فهرست‌شده در مستندات آن توابع، پشتیبانی از کدگذاری و کدگشایی توصیف‌شده در بخش پیشین، و نیز یک متد اضافی را اضافه می‌کنند:

urllib.parse.SplitResult.geturl()

نسخه‌ی دوباره‌ترکیب‌شده‌ی URL اصلی را به عنوان یک رشته برگردانید. این مقدار ممکن است با URL اصلی از این جهت متفاوت باشد که طرح‌واره ممکن است به حروف کوچک نرمال‌سازی شود و اجزای خالی حذف شوند. به‌طور خاص، پارامترها، پرس‌وجوها و شناسه‌های قطعه‌ی خالی حذف خواهند شد، مگر اینکه URL با missing_as_none=True تجزیه شده باشد.

برای نتایج urldefrag()، فقط شناسه‌های قطعه خالی حذف خواهند شد. برای نتایج urlsplit() و urlparse()، همه تغییرات ذکرشده روی URL برگردانده‌شده توسط این متد اعمال خواهند شد.

نتیجه‌ی این متد در صورتی که دوباره به تابع تجزیه‌ی اصلی داده شود، بدون تغییر باقی می‌ماند:

>>> from urllib.parse import urlsplit
>>> url = 'HTTP://www.Python.org/doc/#'
>>> r1 = urlsplit(url)
>>> r1.geturl()
'http://www.Python.org/doc/'
>>> r2 = urlsplit(r1.geturl())
>>> r2.geturl()
'http://www.Python.org/doc/'
>>> r3 = urlsplit(url, missing_as_none=True)
>>> r3.geturl()
'http://www.Python.org/doc/#'

کلاس‌های زیر پیاده‌سازی‌های نتایج تجزیه‌ی ساختاریافته را هنگام کار با اشیای str فراهم می‌کنند:

class urllib.parse.DefragResult(url, fragment)

کلاس مشخص برای نتایج urldefrag() که حاوی داده‌های str هستند. متد encode() نمونه‌ای از DefragResultBytes را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.2.

class urllib.parse.ParseResult(scheme, netloc, path, params, query, fragment)

کلاس عینی برای نتایج urlparse() که شامل داده‌های str هستند. متد encode() یک نمونه از ParseResultBytes را برمی‌گرداند.

class urllib.parse.SplitResult(scheme, netloc, path, query, fragment)

کلاس عینی برای نتایج urlsplit() که حاوی داده‌های str است. متد encode() نمونه‌ای از SplitResultBytes را برمی‌گرداند.

کلاس‌های زیر پیاده‌سازی‌های نتایج تجزیه را هنگام کار بر روی اشیای bytes یا bytearray ارائه می‌دهند:

class urllib.parse.DefragResultBytes(url, fragment)

کلاس عینی برای نتایج urldefrag() که حاوی داده‌های bytes هستند. متد decode() یک نمونه از DefragResult را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.2.

class urllib.parse.ParseResultBytes(scheme, netloc, path, params, query, fragment)

کلاس مشخص برای نتایج urlparse() که حاوی داده‌های bytes هستند. متد decode() یک نمونه از ParseResult را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.2.

class urllib.parse.SplitResultBytes(scheme, netloc, path, query, fragment)

کلاس مشخص برای نتایج urlsplit() که شامل داده‌های bytes است. متد decode() یک نمونه SplitResult را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.2.

کدگذاری URL (URL Quoting)

توابع نقل‌قول URL بر گرفتن داده‌های برنامه و ایمن کردن آن‌ها برای استفاده به‌عنوان کامپوننت‌های URL از طریق نقل‌قول کردن نویسه‌های خاص و کدگذاری مناسب متن غیر ASCII تمرکز دارند. آن‌ها همچنین از معکوس کردن این عملیات برای بازسازی داده‌های اصلی از محتوای یک کامپوننت URL پشتیبانی می‌کنند، اگر آن کار از قبل توسط توابع تجزیه URL بالا پوشش داده نشده باشد.

urllib.parse.quote(string, safe='/', encoding=None, errors=None)

نویسه‌های ویژه در string با استفاده از خنثی‌سازی %xx جایگزین می‌شوند. حروف، ارقام و نویسه‌های '_.-~' هرگز کدگذاری نمی‌شوند. به‌طور پیش‌فرض، این تابع برای کدگذاری بخش مسیر یک URL در نظر گرفته شده است. پارامتر اختیاری safe نویسه‌های ASCII اضافی را مشخص می‌کند که نباید کدگذاری شوند — مقدار پیش‌فرض آن '/' است.

string ممکن است یک شیء str یا bytes باشد.

تغییر یافته در نسخه‌ی 3.7: برای کدگذاری (quoting) رشته‌های URL، از RFC 2396 به RFC 3986 منتقل شد. اکنون «~» در مجموعه نویسه‌های بدون رزرو گنجانده شده است.

پارامترهای اختیاری encoding و errors مشخص می‌کنند که چگونه با نویسه‌های غیر ASCII برخورد شود، همان‌گونه که متد str.encode() آن‌ها را می‌پذیرد. اگرچه این پارامترها در امضای تابع مقدار پیش‌فرض None دارند، هنگام پردازش ورودی‌های str، مقدار پیش‌فرض encoding عملاً 'utf-8' و مقدار پیش‌فرض errors عملاً 'strict' است، به این معنا که نویسه‌های پشتیبانی‌نشده موجب پرتاب UnicodeEncodeError می‌شوند. اگر string یک bytes باشد، نباید encoding و errors ارائه شوند، در غیر این صورت یک TypeError پرتاب می‌شود.

توجه داشته باشید که quote(string, safe, encoding, errors) معادل quote_from_bytes(string.encode(encoding, errors), safe) است.

مثال: quote('/El Niño/') مقدار '/El%20Ni%C3%B1o/' را برمی‌گرداند.

urllib.parse.quote_plus(string, safe='', encoding=None, errors=None)

مانند quote()، اما فاصله‌ها را نیز با علامت‌های جمع جایگزین می‌کند، همان‌طور که برای نقل‌قول کردن مقادیر فرم HTML هنگام ساخت رشته‌ی پرس‌وجو (query string) برای قرار گرفتن در URL لازم است. علامت‌های جمع در رشته‌ی اصلی خنثی می‌شوند، مگر اینکه در safe گنجانده شده باشند. همچنین مقدار پیش‌فرض safe برابر با '/' نیست.

مثال: quote_plus('/El Niño/') مقدار '%2FEl+Ni%C3%B1o%2F' را نتیجه می‌دهد.

urllib.parse.quote_from_bytes(bytes, safe='/')

مانند quote()، اما یک شیء bytes را به‌جای یک str می‌پذیرد و کدگذاری رشته به بایت را انجام نمی‌دهد.

مثال: quote_from_bytes(b'a&\xef') مقدار 'a%26%EF' را برمی‌گرداند.

urllib.parse.unquote(string, encoding='utf-8', errors='replace')

گریزهای %xx را با معادل تک‌نویسه‌ای آن‌ها جایگزین می‌کند. پارامترهای اختیاری encoding و errors مشخص می‌کنند که دنباله‌های کدگذاری‌شده با درصد چگونه به نویسه‌های یونیکد کدگشایی شوند، همان‌گونه که متد bytes.decode() می‌پذیرد.

string ممکن است یک شیء str یا bytes باشد.

encoding به‌طور پیش‌فرض 'utf-8' است. errors به‌طور پیش‌فرض 'replace' است، به این معنا که دنباله‌های نامعتبر با یک نویسه جایگزین جایگزین می‌شوند.

مثال: unquote('/El%20Ni%C3%B1o/') '/El Niño/' را برمی‌گرداند.

تغییر یافته در نسخه‌ی 3.9: پارامتر string از شیءهای bytes و str پشتیبانی می‌کند (پیش‌تر فقط str).

urllib.parse.unquote_plus(string, encoding='utf-8', errors='replace')

مانند unquote() است، اما همچنین علامت‌های مثبت را با فاصله جایگزین می‌کند، همان‌طور که برای کدگشایی مقادیر فرم HTML لازم است.

string باید یک str باشد.

مثال: unquote_plus('/El+Ni%C3%B1o/') '/El Niño/' را برمی‌گرداند.

urllib.parse.unquote_to_bytes(string)

دنباله‌های خنثی‌سازی %xx را با معادل تک‌بایتی آن‌ها جایگزین می‌کند و یک شیء bytes را برمی‌گرداند.

string ممکن است یک شیء str یا bytes باشد.

اگر یک str باشد، نویسه‌های غیر ASCII خنثی‌نشده در string به بایت‌های UTF-8 کدگذاری می‌شوند.

مثال: unquote_to_bytes('a%26%EF') b'a&\xef' را برمی‌گرداند.

urllib.parse.urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus)

یک شیء نگاشت یا دنباله‌ای از تاپل‌های دو عنصری را، که ممکن است شامل اشیای str یا bytes باشد، به یک رشته متنی ASCII با کدگذاری درصدی تبدیل می‌کند. اگر رشته حاصل قرار باشد به‌عنوان data برای عملیات POST با تابع urlopen() استفاده شود، باید به بایت کدگذاری شود؛ در غیر این صورت منجر به TypeError خواهد شد.

رشته‌ی حاصل، مجموعه‌ای از جفت‌های key=value است که با نویسه‌های '&' از هم جدا شده‌اند؛ در آن هم کلید و هم مقدار با استفاده از تابع quote_via کدگذاری می‌شوند. به‌طور پیش‌فرض، quote_plus() برای کدگذاری مقدارها استفاده می‌شود، به این معنا که فاصله‌ها به‌صورت نویسه‌ی '+' کدگذاری می‌شوند و نویسه‌های '/' به‌صورت %2F کدگذاری می‌شوند، که از استاندارد درخواست‌های GET (application/x-www-form-urlencoded) پیروی می‌کند. تابع جایگزینی که می‌توان به‌عنوان quote_via ارسال کرد، quote() است که فاصله‌ها را به‌صورت %20 کدگذاری می‌کند و نویسه‌های '/' را کدگذاری نمی‌کند. برای حداکثر کنترل بر آنچه کدگذاری می‌شود، از quote استفاده کنید و مقداری برای safe مشخص کنید.

هنگامی که از یک دنباله از تاپل‌های دو عنصری به‌عنوان آرگومان query استفاده شود، اولین المان هر تاپل یک کلید و دومین المان یک مقدار است. خود المان مقدار می‌تواند یک دنباله باشد و در این صورت، اگر پارامتر اختیاری doseq به True ارزیابی شود، برای هر المان از دنباله‌ی مقدارِ آن کلید، جفت‌های key=value جداگانه‌ای تولید می‌شوند که با '&' از هم جدا شده‌اند. ترتیب پارامترها در رشته‌ی کدگذاری‌شده با ترتیب تاپل‌های پارامتر در دنباله مطابقت خواهد کرد.

پارامترهای safe، encoding و errors به quote_via منتقل می‌شوند (پارامترهای encoding و errors فقط زمانی منتقل می‌شوند که یک المان پرس‌وجو از نوع str باشد).

برای معکوس کردن این فرایند کدگذاری، parse_qs() و parse_qsl() در این ماژول ارائه شده‌اند تا رشته‌های پرس‌وجو را به ساختارهای داده پایتون تجزیه کنند.

برای اینکه ببینید چگونه می‌توان از متد urllib.parse.urlencode() برای تولید رشته‌ی پرس‌وجوی یک URL یا داده‌های یک درخواست POST استفاده کرد، به مثال‌های urllib مراجعه کنید.

تغییر یافته در نسخه‌ی 3.2: query از اشیای bytes و اشیای رشته‌ای پشتیبانی می‌کند.

تغییر یافته در نسخه‌ی 3.5: پارامتر quote_via افزوده شد.

منسوخ شده از نسخه‌ی 3.14: پذیرفتن اشیایی با مقادیر کاذب (مانند 0 و []) به‌جز رشته‌های خالی، اشیاء شبه‌بایت و None اکنون منسوخ شده است.

همچنین ببینید

WHATWG - استاندارد زنده‌ی URL

گروه کاری استاندارد URL که URLها، دامنه‌ها، آدرس‌های IP، قالب application/x-www-form-urlencoded و API آن‌ها را تعریف می‌کند.

RFC 3986 - شناسه‌های یکنواخت منبع

این استاندارد کنونی (STD66) است. هرگونه تغییری در ماژول urllib.parse باید با این استاندارد مطابقت داشته باشد. ممکن است برخی انحراف‌ها مشاهده شوند که عمدتاً برای اهداف سازگاری با نسخه‌های پیشین و برای برخی الزامات دوفاکتوی تجزیه هستند، همان‌گونه که معمولاً در مرورگرهای اصلی مشاهده می‌شود.

RFC 2732 - قالب آدرس‌های IPv6 به‌صورت متنی در URLها.

این الزامات تجزیه‌ی URLهای IPv6 را مشخص می‌کند.

RFC 2396 - شناسه‌های منبع یکنواخت (URI): سینتکس عام

سندی که الزامات نحوی عام برای هر دو نام منبع یکدست (URN) و مکان‌یاب منبع یکدست (URL) را توصیف می‌کند.

RFC 2368 - طرح‌واره URL mailto.

الزامات تجزیه برای طرح‌واره‌های URL mailto.

RFC 1808 - نشانی‌های نسبی منابع یکنواخت

این درخواست برای نظر (Request For Comments) شامل قواعد پیوند دادن یک URL مطلق و یک URL نسبی است، از جمله تعداد قابل‌توجهی «مثال‌های غیرعادی» که نحوه‌ی برخورد با موارد مرزی را تعیین می‌کنند.

RFC 1738 - مکان‌یاب‌های یکپارچه منابع (URL)

این، سینتکس و معناشناسی رسمی URLهای مطلق را مشخص می‌کند.