используя urllibrequest
модуль, мы можем легко реализовать отправку запроса и получить ответ, В этом разделе мы рассмотрим его конкретное использование.
1. urlopen()
urllib.request
Модуль предоставляет самый базовый метод построения HTTP-запросов, который можно использовать для имитации процесса инициации запроса браузера, а также обрабатывает проверку авторизации (аутентификацию), перенаправление (перенаправление), файлы cookie браузера и другой контент.
Давайте посмотрим на его сильные стороны. Возьмем в качестве примера официальный сайт Python, давайте возьмем эту страницу:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))
Результат работы показан на рис. 3-1.
Рисунок 3-1 Результат работы
Здесь мы используем только две строки кода для завершения сканирования официального сайта Python и вывода исходного кода веб-страницы. После получения исходного кода? Можем ли мы извлечь все нужные ссылки, адреса изображений и текстовую информацию?
Далее посмотрите, что именно он возвращает. использоватьtype()
Метод выводит тип ответа:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))
Результат выглядит следующим образом:
<class 'http.client.HTTPResponse'>
Можно обнаружить, что этоHTTPResposne
тип объекта. В основном содержитread()
,readinto()
,getheader(name)
,getheaders()
,fileno()
и другие методы, а такжеmsg
,version
,status
,reason
,debuglevel
,closed
и другие свойства.
Получив этот объект, мы назначаем его какresponse
переменные, а затем вы можете вызвать эти методы и свойства, чтобы получить ряд сведений о возвращаемом результате.
Например, вызовread()
Метод может получить возвращенное содержимое веб-страницы, вызватьstatus
Атрибут может получить код состояния возвращаемого результата, например, 200 для успешного запроса, 404 для веб-страницы, не найденной и т. д.
Давайте посмотрим на другой пример:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
Результаты приведены ниже:
200
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Content-Length', '47397'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 01 Aug 2016 09:57:31 GMT'), ('Via', '1.1 varnish'), ('Age', '2473'), ('Connection', 'close'), ('X-Served-By', 'cache-lcy1125-LCY'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '23'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
nginx
Видно, что первые два вывода выводят код состояния ответа и информацию заголовка ответа соответственно, а последний вывод вызывается вызовомgetheader()
метод и передать параметрServer
получить заголовок ответаServer
значение, результатnginx
, что означает, что сервер построен на Nginx.
Используйте самые основныеurlopen()
метод, который может выполнить самый простой и простой обход веб-страницы по запросу GET.
Если вы хотите передать в ссылку какие-то параметры, как это сделать? Первый взглядurlopen()
API функции:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
Можно обнаружить, что в дополнение к первому параметру мы можем передать URL-адрес, мы также можем передать другой контент, напримерdata
(Дополнительная информация),timeout
(таймаут) и т.д.
Ниже мы подробно опишем использование этих параметров.
параметр данных
data
Параметры являются необязательными. Если вы хотите добавить этот параметр, и если он содержится в формате кодированного потока байтов, т.е.bytes
тип, вам нужно пройтиbytes()
преобразование метода. Кроме того, если этот параметр передается, его метод запроса больше не является методом GET, а методом POST.
Давайте рассмотрим пример:
import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
Здесь мы передаем параметрword
, значениеhello
. его нужно перекодировать вbytes
(поток байтов) тип. Среди них поток байтов принимаетbytes()
метод, первый параметр метода должен бытьstr
(строка), вам нужно использоватьurllib.parse
в модулеurlencode()
метод для преобразования словаря параметров в строку; второй параметр указывает формат кодировки, который указан здесь какutf8
.
Запрошенный здесь сайтhttpbin.org, который может обеспечить тестирование HTTP-запросов. URL-адрес, который мы запрашиваем на этот раз,httpbin.org/post, эту ссылку можно использовать для проверки POST-запроса, она может выводить некоторую информацию о запросе, который содержит переданную нами информациюdata
параметр.
Результаты приведены ниже:
{
"args": {},
"data": "",
"files": {},
"form": {
"word": "hello"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "10",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.5"
},
"json": null,
"origin": "123.124.23.253",
"url": "http://httpbin.org/post"
}
Переданные нами параметры появляются вform
В поле это указывает, что он имитирует метод отправки формы и передает данные в режиме POST.
параметр тайм-аута
timeout
Параметр используется для установки времени ожидания в секундах, что означает, что если запрос превышает установленное время и не получил ответа, будет выдано исключение. Если этот параметр не указан, будет использоваться глобальное время по умолчанию. Он поддерживает HTTP, HTTPS, FTP-запросы.
Давайте рассмотрим пример:
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())
Результаты приведены ниже:
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "/var/py/python/urllibtest.py", line 4, in <module> response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
...
urllib.error.URLError: <urlopen error timed out>
Здесь мы устанавливаем тайм-аут на 1 секунду. Через 1 секунду программы сервер так и не ответил, поэтому кинулURLError
аномальный. Исключение принадлежитurllib.error
модуль, причина ошибки - тайм-аут.
Поэтому, установив этот тайм-аут, вы можете управлять веб-страницей, чтобы пропустить ее сканирование, если она не отвечает в течение длительного времени. Это можно использоватьtry except
заявление для достижения, соответствующий код выглядит следующим образом:
import socket
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
Здесь мы спрашиваемhttpbin.org/getПротестируйте ссылку, установите тайм-аут на 0,1 секунды, затем захватитеURLError
Исключение, тогда судите об исключенииsocket.timeout
Введите (имеется в виду исключение тайм-аута), чтобы это действительно была ошибка из-за тайм-аута, а распечаткаTIME OUT
.
Результаты приведены ниже:
TIME OUT
Согласно здравому смыслу получить ответ сервера в течение 0,1 секунды в принципе невозможно, поэтому выводTIME OUT
намекать.
установивtimeout
Этот параметр используется для реализации обработки времени ожидания, что иногда полезно.
Другие параметры
Кромеdata
параметры иtimeout
Кроме параметров естьcontext
параметр, он должен бытьssl.SSLContext
Введите, чтобы указать настройки SSL.
также,cafile
а такжеcapath
Эти два параметра определяют сертификат ЦС и его путь соответственно, что полезно при запросе ссылок HTTPS.
cadefault
Параметр устарел, и его значение по умолчанию равноFalse
.
объяснил ранееurlopen()
Использование метода, с помощью этого самого основного метода мы можем выполнять простые запросы и веб-скраппинг. Более подробную информацию можно найти в официальной документации:docs.Python.org/3/library/U….
2. Request
мы знаем, используяurlopen()
Метод может инициировать самый простой запрос, но этих простых параметров недостаточно для построения полного запроса. Если вам нужно добавить в запрос заголовки и другую информацию, вы можете использовать более мощныйRequest
класс для сборки.
Во-первых, давайте почувствуем это на примереRequest
Применение:
import urllib.request
request = urllib.request.Request('https://python.org')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
Можно обнаружить, что мы все еще используемurlopen()
метод для отправки этого запроса, но на этот раз параметром метода является уже не URL, аRequest
тип объекта. Построив эту структуру данных, мы, с одной стороны, можем отделить запрос в объект, а с другой стороны, можем более обильно и гибко настраивать параметры.
Давайте взглянемRequest
Какие параметры можно использовать для построения, метод его построения выглядит следующим образом:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- первый параметр
url
Используется для запроса URL, это обязательный параметр, остальные параметры необязательны. - второй параметр
data
Если вы хотите пройти его, вы должны пройти егоbytes
(поток байтов) тип. Если это словарь, вы можете сначала использоватьurllib.parse
в модулеurlencode()
кодирование. - третий параметр
headers
это словарь, это заголовок запроса, мы можем передать его при построении запросаheaders
Параметры создаются напрямую или путем вызова экземпляра запроса.add_header()
добавлен метод. Чаще всего для добавления заголовков запросов используется изменениеUser-Agent
чтобы скрыть браузер, по умолчаниюUser-Agent
является Python-urllib, мы можем замаскировать браузер, изменив его. Например, чтобы замаскировать Firefox, вы можете установить его на:
Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11
- четвертый параметр
origin_req_host
Относится к имени хоста или IP-адресу запрашивающей стороны. - пятый параметр
unverifiable
Указывает, является ли запрос непроверяемым, по умолчаниюFalse
, что означает, что у пользователя недостаточно прав для выбора получения результатов этого запроса. Например, мы запрашиваем изображение в HTML-документе, но у нас нет разрешения на автоматическое получение изображения, которое затем невозможно проверить.的值就是
Правда`. - шестой параметр
method
Строка, указывающая метод, используемый запросом, например GET, POST и PUT.
Давайте посмотрим на запрос построения, передав несколько параметров:
from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
'Host': 'httpbin.org'
}
dict = {
'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
Здесь мы создаем запрос с 4 параметрами, гдеurl
то есть URL-адрес запроса,headers
указано вUser-Agent
а такжеHost
,параметрdata
использоватьurlencode()
а такжеbytes()
метод преобразования в поток байтов. Кроме того, метод запроса указан как POST.
Результаты приведены ниже:
{
"args": {},
"data": "",
"files": {},
"form": {
"name": "Germey"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "11",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
},
"json": null,
"origin": "219.224.169.11",
"url": "http://httpbin.org/post"
}
По результатам наблюдения можно обнаружить, что мы успешно установилиdata
,headers
а такжеmethod
.
Кроме того,headers
также можно использоватьadd_header()
метод добавления:
req = request.Request(url=url, data=data, method='POST')
req.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
Таким образом, мы можем более удобно построить запрос и реализовать отправку запроса.
3. Расширенное использование
В приведенном выше процессе, хотя мы можем создать запрос, что мы должны сделать для некоторых более сложных операций (таких как обработка файлов cookie, настройка прокси-сервера и т. д.)?
Затем необходим более мощный инструмент Handler. Короче говоря, мы можем понимать это как различные процессоры, некоторые из которых специализируются на проверке входа в систему, некоторые имеют дело с файлами cookie, а некоторые — с настройками прокси. Используя их, мы можем делать почти все в HTTP-запросе.
Во-первых, позвольте мне представитьurllib.request
в модулеBaseHandler
класс, это все другоеHandler
, который предоставляет самые основные методы, такие какdefault_open()
,protocol_request()
Ждать.
Далее идут различныеHandler
подклассы наследуют этоBaseHandler
класс например.
-
HTTPDefaultErrorHandler
: используется для обработки ошибок ответа HTTP, будут выдаваться ошибкиHTTPError
тип исключения. -
HTTPRedirectHandler
: Используется для обработки перенаправлений. -
HTTPCookieProcessor
: используется для обработки файлов cookie. -
ProxyHandler
: Используется для установки прокси, прокси по умолчанию пуст. -
HTTPPasswordMgr
: используется для управления паролями, поддерживает таблицу имен пользователей и паролей. -
HTTPBasicAuthHandler
: используется для управления аутентификацией и может использоваться для решения проблем с аутентификацией, если аутентификация требуется при открытии ссылки.
Кроме того, существуют другиеHandler
Классы здесь не указаны, подробности можно найти в официальной документации:docs.Python.org/3/library/U….
О том, как их использовать, не беспокойтесь сейчас, примеры будут позже.
Другим важным классом являетсяOpenerDirector
, мы можем назвать этоOpener
. мы использовали его раньшеurlopen()
Этот метод, на самом деле, предоставлен нам urllib.Opener
.
Так зачем вводитьOpener
Шерстяная ткань? Потому что нужно реализовать более продвинутые функции. бывшего употребленияRequest
а такжеurlopen()
Это эквивалентно библиотеке классов, которая инкапсулирует наиболее часто используемые для вас методы запросов, и вы можете использовать их для выполнения базовых запросов, но теперь это другое, нам нужно реализовать более продвинутые функции, поэтому нам нужно углубиться в конфигурации и использовать экземпляры более низкого уровня для завершения операции, поэтому он используется здесьOpener
.
Opener
можно использоватьopen()
метод, тип возвращаемого значения иurlopen()
такой же. Тогда это иHandler
Что это значит? Короче говоря, используяHandler
строитьOpener
.
Вот несколько примеров, чтобы увидеть, как они используются.
проверять
При открытии некоторых веб-сайтов появляется всплывающее окно с запросом на ввод имени пользователя и пароля, и страницу можно просмотреть только после успешной проверки, как показано на рис. 3-2.
Рисунок 3-2 Страница проверки
Итак, что, если вы хотите запросить такую страницу? с помощьюHTTPBasicAuthHandler
Его можно завершить, соответствующий код выглядит следующим образом:
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = 'username'
password = 'password'
url = 'http://localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler)
try:
result = opener.open(url)
html = result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)
Первый экземпляр здесьHTTPBasicAuthHandler
объект, аргумент которогоHTTPPasswordMgrWithDefaultRealm
объект, который используетadd_password()
Добавьте имя пользователя и пароль, которые создают процесс аутентификации.Handler
.
Далее используйте этоHandler
и использоватьbuild_opener()
способ построитьOpener
,этоOpener
Отправка запроса означает, что проверка прошла успешно.
Далее используйтеOpener
изopen()
Метод открывает ссылку, и проверка может быть завершена. Полученный здесь результат является проверенным исходным контентом страницы.
играет роль
При выполнении краулера использование прокси неизбежно, если вы хотите добавить прокси, вы можете сделать это:
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
'http': 'http://127.0.0.1:9743',
'https': 'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
Здесь мы настраиваем прокси локально, который работает на порту 9743.
используется здесьProxyHandler
, параметр которого — словарь, имя ключа — тип протокола (например, HTTP или HTTPS и т. д.), значение ключа — ссылка на прокси, и можно добавить несколько прокси.
Затем используйте этот обработчик иbuild_opener()
метод построенияOpener
, а затем отправить запрос.
Cookies
Обработка файлов cookie требует соответствующихHandler
.
Давайте используем пример, чтобы увидеть, как получить файлы cookie веб-сайта. Соответствующий код выглядит следующим образом:
import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:
print(item.name+"="+item.value)
Во-первых, мы должны объявитьCookieJar
объект. Далее необходимо использоватьHTTPCookieProcessor
построитьHandler
, и, наконец, используйтеbuild_opener()
метод строитOpener
,воплощать в жизньopen()
функция.
Результаты приведены ниже:
BAIDUID=2E65A683F8A8BA3DF521469DF8EFF1E1:FG=1
BIDUPSID=2E65A683F8A8BA3DF521469DF8EFF1E1
H_PS_PSSID=20987_1421_18282_17949_21122_17001_21227_21189_21161_20927
PSTM=1474900615
BDSVRTM=0
BD_HOME=0
Как видите, здесь выводятся имя и значение каждого файла cookie.
Но поскольку его можно вывести, можно ли его вывести в формате файла? Мы знаем, что файлы cookie на самом деле хранятся в текстовом виде.
Ответ, конечно, да, вот посмотрите на следующие примеры:
filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
В настоящее времяCookieJar
необходимо заменить наMozillaCookieJar
, который используется при создании файла,CookieJar
Подкласс , который можно использовать для обработки файлов cookie и событий, связанных с файлами, таких как чтение и сохранение файлов cookie, а также сохранение файлов cookie в формате файлов cookie браузера типа Mozilla.
После запуска вы можете обнаружить, что создается файл cookies.txt со следующим содержимым:
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file! Do not edit.
.baidu.com TRUE / FALSE 3622386254 BAIDUID 05AE39B5F56C1DEC474325CDA522D44F:FG=1
.baidu.com TRUE / FALSE 3622386254 BIDUPSID 05AE39B5F56C1DEC474325CDA522D44F
.baidu.com TRUE / FALSE H_PS_PSSID 19638_1453_17710_18240_21091_18560_17001_21191_21161
.baidu.com TRUE / FALSE 3622386254 PSTM 1474902606
www.baidu.com FALSE / FALSE BDSVRTM 0
www.baidu.com FALSE / FALSE BD_HOME 0
Кроме того,LWPCookieJar
Файлы cookie также можно читать и сохранять, но в том же формате, что иMozillaCookieJar
Не то же самое, он будет сохранен как файл cookie в формате libwww-perl (LWP).
Чтобы сохранить файл cookie в формате LWP, вы можете изменить его на:
cookie = http.cookiejar.LWPCookieJar(filename)
Контент, сгенерированный в это время, выглядит следующим образом:
#LWP-Cookies-2.0
Set-Cookie3: BAIDUID="0CE9C56F598E69DB375B7C294AE5C591:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: BIDUPSID=0CE9C56F598E69DB375B7C294AE5C591; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: H_PS_PSSID=20048_1448_18240_17944_21089_21192_21161_20929; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: PSTM=1474902671; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
С этой точки зрения сгенерированный формат все же сильно отличается.
Затем, после создания файла Cookies, как читать и использовать его из файла?
Ниже мы используемLWPCookieJar
Взгляните на формат в качестве примера:
cookie = http.cookiejar.LWPCookieJar()
cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))
Как видите, звонок здесьload()
метод для чтения локального файла Cookies и получения содержимого Cookies. Но предпосылка заключается в том, что мы сначала создаем файлы cookie в формате LWPCookieJar, сохраняем их как файлы, а затем читаем файлы cookie и используем тот же метод для создания обработчика и открывателя для завершения операции.
Если текущий результат нормальный, будет выведен исходный код веб-страницы Baidu.
С помощью вышеуказанного метода мы можем реализовать настройки большинства функций запроса.
Это библиотека urllibrequest
Основное использование модуля, если вы хотите получить больше функций, вы можете обратиться к официальной документации:docs.Python.org/3/library/U….
Этот ресурс был впервые опубликован в личном блоге Цуй Цинцай Цзин Ми:Практическое руководство по разработке веб-краулера на Python3 | Цзин Ми
Если вы хотите узнать больше информации о поисковых роботах, обратите внимание на мой личный публичный аккаунт WeChat: Coder of Attack.
WeChat.QQ.com/Day/5 Это радость VE Z…(автоматическое распознавание QR-кода)