記事ディレクトリ
urllibライブラリを使用する
まず、Pythonに組み込まれているHTTPリクエストライブラリであるurllibライブラリについて学習します。これは、追加のインストールなしで使用できることを意味します。以下の4つのモジュールが含まれています。
request:これは、要求の送信をシミュレートするために使用できる最も基本的なHTTP要求モジュールです。ブラウザにURLを入力してEnterキーを押すのと同じように、このプロセスをシミュレートするには、URLと追加のパラメータをlibraryメソッドに渡すだけです。
エラー:例外処理モジュール。要求エラーが発生した場合、これらの例外をキャッチしてから、再試行またはその他の操作を実行して、プログラムが予期せず終了しないようにすることができます。
parse:分割、解析、マージなど、多くのURL処理方法を提供するツールモジュール。
robotparser:主にWebサイトのrobots.txtファイルを識別し、クロールできるWebサイトとクロールできないWebサイトを判別するために使用されます。あまり実用的ではありません。
1.urllib.request.urlopen()関数
urllib.requestモジュールは、HTTP要求を作成する最も基本的な方法を提供します。これは、ブラウザーの要求開始プロセスをシミュレートするために使用できます。
import urllib.request
response = urllib.request.urlopen("http://www.python.org")
#print(response.read().decode('utf-8'))
# print(type(response)) #class类型
# html = response.read() #读取该网页的html信息,爬取的内容是以 utf-8 编码的bytes对象
# print(html) #打印的时候字符串前面有个 b,表示这是一个bytes对象
#
# #要还原成带中文的html代码,需要对其进行解码,将它变成Unicode编码
# html = html.decode("utf-8")
# print(html)
# print("=======================")
次に、それが何を返すかを見てください。type()メソッドを使用して、応答タイプを出力します。
print(type(response))
<class 'http.client.HTTPResponse'>
HTTPResposneタイプのオブジェクトであることがわかります。これには主に、read()、readinto()、getheader(name)、getheaders()、fileno()などのメソッドと、msg、version、status、reason、debuglevel、closedなどの属性が含まれています。
read()メソッドを呼び出して、返されたWebページのコンテンツを取得し、status属性を呼び出して、返された結果のステータスコードを取得します。たとえば、200は要求が成功したことを表し、404はWebページが見つからないことを表します。
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
200
[('Connection', 'close'), ('Content-Length', '49243'), ('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur'), ('Via', '1.1 varnish'), ('Accept-Ranges', 'bytes'), ('Date', 'Wed, 23 Sep 2020 00:49:55 GMT'), ('Via', '1.1 varnish'), ('Age', '1774'), ('X-Served-By', 'cache-bwi5142-BWI, cache-hkg17933-HKG'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '1, 2695'), ('X-Timer', 'S1600822196.530321,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
nginx
最初の2つの出力はそれぞれ応答ステータスコードと応答ヘッダー情報を出力し、最後の出力はgetheader()メソッドを呼び出してパラメーターServerを渡すことにより、応答ヘッダーのサーバー値を取得します。結果はnginxです。これは、サーバーがNginxで構築されています。
urlopen()関数API:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
データパラメータ
このパラメーターが渡されると、その要求メソッドはGETではなくPOSTになります。
データパラメータはオプションです。このパラメータを追加する場合で、それがバイトストリームエンコーディング形式のコンテンツ、つまりバイトタイプである場合は、bytes()メソッドで変換する必要があります。
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())
ここでパラメータワードを渡します。値はhelloです。バイト(バイトストリーム)タイプにトランスコードする必要があります。バイトストリーム変換ではbytes()メソッドを使用します。このメソッドの最初のパラメーターはstr(string)型である必要があり、urllib.parseモジュールのurlencode()メソッドを使用してパラメーターディクショナリを文字列に変換する必要があります。 2つのパラメーターは、ここではutf8として指定されているエンコード形式を指定します。
ここでリクエストされたサイトはhttpbin.orgで、HTTPリクエストのテストを提供できます。今回リクエストしたURLはhttp://httpbin.org/postです。このリンクはPOSTリクエストのテストに使用でき、渡したデータパラメータを含むリクエストの情報を出力できます。
{
"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"
}
渡したパラメータがフォームフィールドに表示されます。これは、フォームの送信方法がシミュレートされ、データがPOSTで送信されることを示します。
タイムアウトパラメータ
タイムアウトパラメータは、タイムアウト期間を秒単位で設定するために使用されます。つまり、要求が設定時間を超えて応答が受信されない場合、例外がスローされます。このパラメーターが指定されていない場合、グローバルデフォルト時間が使用されます。HTTP、HTTPS、FTPリクエストをサポートします。
ここでは、タイムアウト期間を1秒に設定します。プログラムから1秒経ってもサーバーが応答しなかったため、URLError例外がスローされました。例外はurllib.errorモジュールに属し、エラーの原因はタイムアウトです。
したがって、このタイムアウトを設定して、Webページが長時間応答しないかどうかを制御できます。Webページはクロールをスキップします。これは、tryexceptステートメントを使用して実現できます。関連するコードは次のとおりです。
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
print(response.read())
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')
TIME OUT
2.urllib.request関数
工法は以下の通りです。
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
最初のパラメーターはurl
必須パラメーターであるURLを要求するために使用され、その他はオプションのパラメーターです。
2番目のパラメーターdata
を渡す場合は、バイトタイプ(バイトストリーム)である必要があります。辞書の場合は、最初にurllib.parseモジュールでurlencode()エンコーディングを使用できます。
3番目のパラメーター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
4番目のパラメーターorigin_req_host
は、リクエスターのホスト名またはIPアドレスを参照します。
5番目のパラメーターunverifiable
は、要求を検証できないかどうかを示します。デフォルトはFalseです。これは、ユーザーがこの要求を受信した結果を選択するための十分な権限を持っていないことを意味します。たとえば、HTMLドキュメントで画像をリクエストしましたが、画像を自動的に取得する権限がない場合、検証できない値はTrueになります。
6番目のパラメーター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であり、User-AgentとHostはヘッダーで指定され、パラメーターデータは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"
}
さらに、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)')
検証
一部のWebサイトは、開くとプロンプトボックスが表示され、ユーザー名とパスワードの入力を直接求められます。図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()を使用してユーザー名とパスワードを追加し、認証を処理するためのハンドラーを確立します。
次に、このハンドラーを使用し、build_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()メソッドを使用してオープナーを作成し、リクエストを送信します。
クッキー
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を使用してハンドラーを構築し、最後に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の名前と値がここに出力されます。
クッキーを保存する
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に置き換える必要があります。MozillaCookieJarはファイルの生成時に使用されます。これはCookieJarのサブクラスであり、Cookieや、Cookieの読み取りや保存などのファイル関連のイベントの処理に使用でき、CookieはMozillaブラウジングとして保存できます。デバイスのCookie形式。
クッキーを読む
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()メソッドを呼び出してローカルのCookieファイルを読み取り、Cookieのコンテンツを取得します。ただし、最初にLWPCookieJar形式でCookieを生成してファイルとして保存し、Cookieを読み取って操作を完了した後、同じ方法を使用してハンドラーとオープナーを作成することが前提です。