連載
» 2019年10月15日 05時00分 公開

Python入門:[Python入門]urllib.requestモジュールによるWebページの取得 (1/2)

urllib.requestモジュールを使って、指定したURLをオープンし、その内容をファイルと同様な手法で取り出す方法の基本を紹介する。

[かわさきしんじ,Deep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「Python入門」のインデックス

連載目次

 前回は、shelveモジュールを使用して辞書のような使い勝手でオブジェクトを外部ファイルに保存する方法を見た。今回は、ファイルと同様な手法でネットワークからファイルを取得する方法について見てみよう。

urllibモジュール

 PythonにはURLを扱うためのモジュールとして、urllibモジュールが標準で付属している。実際には、これは幾つかのモジュールをまとめたパッケージである。本稿ではそのうちのurllib.requestモジュールを紹介する。

 urllib.requestモジュールを使って、特定のURLをオープンするにはurllib.request.urlopen関数を使用する。その基本構文を以下に示す。

urllib.request.urlopen関数(その1)

urlopen(url)


 urlをオープンする。

パラメーター 説明
url オープンしたいURL
urllib.request.urlopen関数のパラメーター(一部)


 urllib.request.urlopen関数はより多くのパラメーターを持つが、これらについてはPythonのドキュメントを参照されたい。

urlopen関数の基本的な使い方

 この関数を使用して、指定したURLをオープンすると、http.clientモジュールで定義されているHTTPResponseクラスのオブジェクトが返送される。このクラスには、readメソッド、readlineメソッド、readlinesメソッドなど、取得したHTTPレスポンスから、そのボディー(内容)を読み出すためのメソッドがある。これらを使うことで、取得したレスポンスページの内容を、ファイルを操作するのと同様な手法で読み込めるようになっている。

 この他にも取得したリソースの実際のURLを返送するgeturlメソッド、ページに関する情報を取得するinfoメソッド、urllib.request.urlopen関数によるURLのオープンが成功したかを示すHTTPステータスコードを取得するgetcodeメソッドもある。

 以下に簡単な例を示す。

import urllib

response = urllib.request.urlopen('https://www.example.com/')
print('url:', response.geturl())
print('code:', response.getcode())
print('Content-Type:', response.info()['Content-Type'])
content = response.read()
print(content)
response.close()

urllib.request.urlopen関数を使ってhttp://www.example.comの内容を取得する

 ここではhttps://www.example.comをオープンして、上で述べた3つのメソッドを使い、実際のURL、HTTPレスポンスコード、infoメソッドで得た情報のうちContent-Typeヘッダの内容を表示している。その後、readメソッドを使ってWebページの内容を読み込んで、それを画面に出力している。ここではreadメソッドを使っているが、readlineメソッドで1行ずつ内容を読み出すことも可能だ。

 実行結果を以下に示す。

実行結果 実行結果

 実行結果を見ると分かるように、取得したページ内容はバイト列(bytesオブジェクト)になっている。よって、実際にこれを利用するにはdecodeメソッドで文字列にデコードする必要がある。

html = content.decode()
print(html)

取得したバイト列を文字列にデコードする

 このコードを実行すると、次のように文字列としてWebページのソースが表示される。

実行結果 実行結果

 このときに注意したいのは、decodeメソッドではエンコーディング方式をデフォルトで'utf-8'としている点だ。例えば、@ITのWebページはシフトJISをそのエンコーディングに使用している。そのため、urllib.request.urlopen関数でそのページの内容を取得しても、デコード時にエンコーディングに'shift_jis'などを指定しないと、適切な結果が得られない。

response = urllib.request.urlopen('https://www.atmarkit.co.jp/ait/subtop/di')
content = response.read()
response.close()
html = content.decode()  # UTF-8でデコード

シフトJISでエンコードされたページをUTF-8でデコードしてみる

 そのため、上のコードを実行すると、次のような結果になる。

実行結果 実行結果

 このように、UnicodeDecodeError例外が発生する。これを修正するには、次のようにdecodeメソッドにエンコーディングを指定する。

html = content.decode('shift_jis')
print(html)

エンコーディングに「shift_jis」を指定してデコードする

 実行結果を以下に示す。

実行結果 実行結果

 このとき、エンコーディングを調べるには、上述のinfoメソッドやこの例ならresponse.headersとして取り出せるhttp.client.HTTPMessageオブジェクトに対して、get_content_charsetメソッドを呼び出すとよい(ただし、常にエンコーディングを取得できるとは限らない)。

 以下に例を示す(実行結果は省略する)。

response = urllib.request.urlopen('https://www.google.co.jp')
print(response.info().get_content_charset())

エンコーディングの取得

 なお、上のコードではurllibモジュールのインポートに次の行を実行している。

import urllib

urllibモジュールのインポート

 これにより「urllib.request.urlopen(……)」や「urllib.parse.urlencode(……)」のように、urllibモジュールに含まれているサブモジュールの関数やクラスにアクセスできるようになるが、記述が煩わしいと感じる方もいるかもしれない。以下のように、必要なものだけをインポートしても構わない。

from urllib import request, parse
from urllib.request import urlopen
from urllib.parse import urlencode

urllibモジュールから必要なものだけをインポート

 1行目のようなインポートをすれば、その後は「request.urlopen(……)」のようにurllib.requestモジュールで定義されている関数やクラスにアクセスできるようになる。2行目と3行目のように使用することが分かっている関数だけをインポートしてもよい。以下では、「import urllib」でこのモジュールをインポートしたものとして話を進める。

       1|2 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。