Pythonウェブスクレイピング:主要ライブラリと実装ガイド

ウェブスクレイピングに役立つ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ライブラリを使った際にも、その内部動作を深く理解することができます。

タグ: Python ウェブスクレイピング urllib requests BeautifulSoup

7月6日 19:44 投稿