ウェブスクレイピングに役立つPythonライブラリ
代表的なライブラリ
- requests: HTTPリクエストを送信するためのライブラリ
- selenium: ブラウザを自動化するためのツール
- lxml: 高速なXML/HTMLパーサー
- BeautifulSoup: HTML/XML解析ライブラリ
- pyquery: jQueryライクな文法でHTMLを操作できるライブラリ
- pymysql: MySQLデータベース接続用ライブラリ
- pymongo: MongoDB操作用ライブラリ
- redis: 高速なキー値ストアデータベース
- jupyter: 対話型プログラミング環境
Urllibについて
Python標準のHTTPリクエストライブラリです。
主要モジュール
urllib.request: リクエスト処理モジュールurllib.error: エラーハンドリングモジュールurllib.parse: URL解析モジュールurllib.robotparser: robots.txt解析モジュール
Python 2と3の違い
Python 2:
import urllib2
response = urllib2.urlopen('http://www.example.com')
Python 3:
import urllib.request
response = urllib.request.urlopen('http://www.example.com')
基本的な使い方
urlopen()はサーバーにリクエストを送信します。
urllib.request.urlopen(url, data=None, timeout=None, ...)
例1: GETリクエスト
import urllib.request
response = urllib.request.urlopen('http://www.example.com')
print(response.read().decode('utf-8'))
例2: POSTリクエスト
import urllib.request
import urllib.parse
data = bytes(urllib.parse.urlencode({'query': '検索キーワード'}), encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
例3: タイムアウト設定
import urllib.request
try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())
except Exception as e:
print(f'エラー: {e}')
レスポンス情報の取得
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
# ステータスコード
print(f'ステータスコード: {response.status}')
# レスポンスヘッダー
print('レスポンスヘッダー:')
for header, value in response.getheaders():
print(f'{header}: {value}')
# 特定ヘッダー
print(f'Server: {response.getheader("Server")}')
Requestオブジェクトの使用
ヘッダー情報を追加するにはRequestオブジェクトを使用します。
import urllib.request
from urllib import parse
url = 'http://httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Host': 'httpbin.org'
}
form_data = {'username': 'testuser', 'password': 'testpass'}
data = bytes(parse.urlencode(form_data), encoding='utf8')
req = urllib.request.Request(url=url, data=data, headers=headers, method='POST')
response = urllib.request.urlopen(req)
print(response.read().decode('utf-8'))
プロキシ設定
import urllib.request
proxy_handler = urllib.request.ProxyHandler({
'http': 'http://proxy.example.com:8080',
'https': 'https://proxy.example.com:8080',
})
opener = urllib.request.build_opener(proxy_handler)
response = opener.open('http://httpbin.org/get')
print(response.read())
Cookieの取り扱い
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.example.com')
for item in cookie:
print(f'{item.name}={item.value}')
Cookieの保存
Mozilla形式で保存:
import http.cookiejar, urllib.request
filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.example.com')
cookie.save(ignore_discard=True, ignore_expires=True)
LWP形式で保存:
import http.cookiejar, urllib.request
filename = 'cookies.txt'
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.example.com')
cookie.save(ignore_discard=True, ignore_expires=True)
Cookieの読み込み
import http.cookiejar, urllib.request
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.example.com')
print(response.read().decode('utf-8'))
エラーハンドリング
from urllib import request, error
# 基本的なエラーハンドリング
try:
response = request.urlopen('http://example.com/notfound')
except error.URLError as e:
print(f'URLエラー: {e.reason}')
# HTTPエラーとURLエラーを分けて処理
try:
response = request.urlopen('http://example.com/notfound')
except error.HTTPError as e:
print(f'HTTPエラー: {e.reason}')
print(f'ステータスコード: {e.code}')
print(f'ヘッダー: {e.headers}')
except error.URLError as e:
print(f'URLエラー: {e.reason}')
else:
print('リクエストが成功しました')
# タイムアウトエラーの処理
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('タイムアウトが発生しました')
URL解析
URLの分解 (urlparse)
from urllib.parse import urlparse
result = urlparse('http://www.example.com/path/to/page?query=value#section')
print(f'スキーマ: {result.scheme}')
print(f'ネットロケーション: {result.netloc}')
print(f'パス: {result.path}')
print(f'パラメータ: {result.params}')
print(f'クエリ: {result.query}')
print(f'フラグメント: {result.fragment}')
# スキームが指定されていない場合
result = urlparse('www.example.com/path', scheme='https')
print(f'スキーム: {result.scheme}')
# フラグメントを無視する場合
result = urlparse('http://www.example.com/path#section', allow_fragments=False)
print(f'フラグメント: {result.fragment}')
URLの結合 (urlunparse)
from urllib.parse import urlunparse
url_parts = ['https', 'www.example.com', '/search', '', 'q=python', '']
full_url = urlunparse(url_parts)
print(full_url)
URLの結合 (urljoin)
from urllib.parse import urljoin
base_url = 'http://www.example.com/'
relative_url = 'about.html'
full_url = urljoin(base_url, relative_url)
print(full_url)
# 後のURLが前のURLを上書き
print(urljoin('http://www.example.com/path/', 'otherpage.html'))
print(urljoin('http://www.example.com/path/', 'http://anothersite.com/'))
クエリ文字列の作成 (urlencode)
from urllib.parse import urlencode
params = {
'keyword': 'Pythonスクレイピング',
'category': 'web',
'page': 1
}
base_url = 'http://www.example.com/search?'
url = base_url + urlencode(params)
print(url)
robots.txtの解析
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url('http://www.example.com/robots.txt')
rp.read()
print(f'許可されているか: {rp.can_fetch("*", "http://www.example.com/")}')
print(f'許可されているか: {rp.can_fetch("*", "http://www.example.com/private/")}')
print(f'クロール遅延: {rp.crawl_delay("*")}')
Pythonの標準ライブラリであるurllibは、ウェブスクレイピングに必要な基本的な機能をすべて提供しています。このライブラリを理解することで、後により便利なrequestsライブラリを使った際にも、その内部動作を深く理解することができます。