「Python3」Webスクレイピング(requests・beautifulsoup4)

Webスクレイピング Python
Webスクレイピング

Webスクレイピングは、Webサイトから情報を抽出し、その情報を分析可能な構造化データに変換する処理を指します。今回は、2つのライブラリ(requests・beautifulsoup4)を使用してWebスクレイピングを行おうと思います。

requests

インストール

requestsライブラリをインストールしましょう。

pip install requests

インストールが完了したら、requestsライブラリをインポートしましょう。

import requests

これで、requestsライブラリが使用可能になりました。

GETメソッド

GETメソッドは、URLにデータを付けて送ることができます。

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("URL", params=payload)

POSTメソッド

POSTメソッドは、HTTPリクエストのメッセージボディにパラメータ(情報)を付けて送ることができます。

payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))

レスポンスの内容

このサイトのトップページのURLを指定して、GETリクエストのレスポンスの中身を見ていきましょう。

import requests

#このサイトのトップページのURL
url = "https://python-eng.com/"

r = requests.get(url)

これで、”r”にレスポンスの情報が入っています。それでは、見ていきましょう。

url

urlを取得します。

<ソースコード>
print(r.url)
<出力結果>
https://python-eng.com/

status_code

ステータスコードを取得します。

<ソースコード>
print(r.url)
<出力結果>
https://python-eng.com/

encoding

エンコーディング情報を取得します。

<ソースコード>
print(r.status_code)
<出力結果>
200

headers

レスポンスヘッダを取得します。

<ソースコード>
print(r.headers)
<出力結果>
{'Server': 'nginx', 'Date': 'Mon, 23 Sep 2019 03:44:39 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'Link': '<https://python-eng.com/wp-json/>; rel="https://api.w.org/"', 'Content-Encoding': 'gzip'}

text

レスポンスボディをテキスト形式で取得します。

<ソースコード>
print(r.text)
<出力結果>
<!doctype html>
<html lang="ja">

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"/>
*省略

content

レスポンスボディをバイナリ形式で取得します。

<ソースコード>
print(r.content)
<出力結果>
b'<!doctype html>\n<html lang="ja">\n\n<head>\n<meta charset="utf-8">\n<meta http-equiv="X-UA-Compatible" content="IE=edge">\n<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"/>\n    <!-- Global site tag (gtag.js) - Google Analytics -->\n
*省略

beautifulsoup4

インストール

beautifulsoup4ライブラリをインストールしましょう。

pip install BeautifulSoup4

インストールが完了したら、beautifulsoup4ライブラリをインポートしましょう。

from bs4 import BeautifulSoup

これで、beautifulsoup4ライブラリが使用可能になりました。

使い方

BeautifulSoupのインスタンスを生成し、”prettify”メソッドを使用してhtmlを整形して表示します。

<ソースコード>
import requests
from bs4 import BeautifulSoup

#このサイトのトップページのURL
url = "https://python-eng.com/"

r = requests.get(url)

soup = BeautifulSoup(r.content, "html.parser")

print(soup.prettify())
<出力結果>
<!DOCTYPE doctype html>
<html lang="ja">
 <head>
  <meta charset="utf-8"/>
  <meta content="IE=edge" http-equiv="X-UA-Compatible"/>
  <meta content="width=device-width, initial-scale=1.0, viewport-fit=cover" name="viewport">
*省略

“html.parser”は、Pythonに標準搭載されている「htmlのタグ情報から情報を解釈するプログラム」です。他にも”lxml”や”html5lib”があります。

タグの取得

h2タグの取得 説明(取得できる数)
soup.h2 1つめのみ
soup.find(“h2”) 1つめのみ
soup.find_all(“h2”) すべてのh2タグのリスト
<ソースコード>
print(soup.h2)
print(soup.find("h2"))
print(soup.find_all("h2"))
<出力結果>
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」エラー処理(try・except)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」ジェネレータ・デコレータ</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」関数(引数・クロージャ・ラムダ)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」内包表記(リスト・辞書・集合 など)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」for文(break・continue・zip・range)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」while文(breakとcontinue)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」if文による比較</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」集合の操作(作成・追加・削除 など)</h2>]

属性を指定してタグを取得することができます。

<ソースコード>
a = soup.find_all("h2", class_="entry-card-title card-title e-card-title", itemprop="headline")
print(a)
a = soup.find_all("h2", attrs={"class": "entry-card-title card-title e-card-title", "itemprop": "headline"})
print(a)

# タグ指定なし
a = soup.find_all(class_="entry-card-title card-title e-card-title", itemprop="headline")
print(a)
a = soup.find_all(attrs={"class": "entry-card-title card-title e-card-title", "itemprop": "headline"})
print(a)
<出力結果>
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>,...省略
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>,...省略
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>,...省略
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>,...省略

selectメソッドを使用すれば、CSSセレクタのように指定して検索ができます。

divタグの中のh2タグの取得 説明(取得できる数)
soup.select_one(“div > h2”) 1つめのみ
soup.select(“div > h2”) すべてのh2タグのリスト
<ソースコード>
print(soup.select_one("div > h2"))
print(soup.select("div > h2"))
<出力結果>
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」エラー処理(try・except)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」ジェネレータ・デコレータ</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」関数(引数・クロージャ・ラムダ)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」内包表記(リスト・辞書・集合 など)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」for文(break・continue・zip・range)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」while文(breakとcontinue)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」if文による比較</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」集合の操作(作成・追加・削除 など)</h2>]

正規表現を利用してタグを取得することもできます。

<ソースコード>
import re

#"d"で始まるすべてのタグを取得
a = soup.find_all(re.compile("^d"))
print(a)

#"1"で終わるすべてのタグを取得
a = soup.find_all(re.compile("1$"))
print(a)

#href属性として"2019/09/19"という文字列を含むものすべて
a = soup.find_all(href=re.compile("2019/09/19"))
print(a)

#文字列に"クラス"を含むh2タグすべて
a = soup.find_all("h2", text=re.compile("クラス"))
print(a)
<出力結果>
[<div class="container cf" id="container">...省略
[<h1 class="logo logo-header logo-image">...省略
[<a class="entry-card-wrap a-wrap border-element cf" href="https://python-eng.com/2019/09/19/%e3%80%8cpython3%e3%80%8d%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%81%a8%e3%82%af%e3%83%a9%e3%82%b9/" title="「Python3」オブジェクトとクラス">...省略
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>]

属性の取得

aタグのhref属性を取得
soup.a.get(“href”)
soup.a[“href”]
<ソースコード>
print(1, soup.a.get("href"))
print(2, soup.a["href"])
print(3, soup.a["class"])

print(4, soup.find("h2")["class"])

print(5)
h2s = soup.find_all("h2")
for h2 in h2s:
    print(h2["class"], h2["itemprop"])
<出力結果>
1 https://python-eng.com
2 https://python-eng.com
3 ['site-name', 'site-name-text-link']
4 ['entry-card-title', 'card-title', 'e-card-title']
5
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline
['entry-card-title', 'card-title', 'e-card-title'] headline

テキストの取得

テキスト要素は、”.string”で取得することができます。

<ソースコード>
print(soup.find("h2").string)

h2s = soup.find_all("h2")
for h2 in h2s:
    print(h2.string)
<出力結果>
「Python3」オブジェクトとクラス
「Python3」オブジェクトとクラス
「Python3」モジュールのインストールとインポート
「Python3」エラー処理(try・except)
「Python3」ジェネレータ・デコレータ
「Python3」関数(引数・クロージャ・ラムダ)
「Python3」内包表記(リスト・辞書・集合 など)
「Python3」for文(break・continue・zip・range)
「Python3」while文(breakとcontinue)
「Python3」if文による比較
「Python3」集合の操作(作成・追加・削除 など)

その他のタグ取得方法

<ソースコード>
h1 = soup.h1
print("1\n", h1)

#指定したh1タグの1つ上の親タグを取得する
print("2\n", h1.find_parent("div"))
#指定したh1タグの親タグを全て取得する
print("3\n", h1.find_parents("div"))

#指定したh1タグ以降のh2タグを1つ取得する
print("4\n", h1.find_next("h2"))
#指定したh1タグ以降のh2タグを全て(リスト型)取得する
print("5\n", h1.find_all_next("h2"))

h2 = soup.find_all("h2")[3]
print("6\n", h2)

#指定したh2タグ以前のh2タグを1つ取得する
print("7\n", h2.find_previous("h2"))
#指定したh2タグ以前のh2タグを全て取得する
print("8\n", h2.find_all_previous("h2"))

#指定したh2タグ以降の同じ深さにあるdivタグを1つ取得する
print("9\n", h2.find_next_sibling("div"))
#指定したh2タグ以降の同じ深さにあるdivタグを全て取得する
print("10\n", h2.find_next_siblings("div"))

#指定したh2タグ以前の同じ深さにあるdivタグを1つ取得する
print("11\n", h2.find_previous_sibling("div"))
#指定したh2タグ以前の同じ深さにあるdivタグを全て取得する
print("12\n", h2.find_previous_siblings("div"))
<出力結果>
1
<h1 class="logo logo-header logo-image"><a class="site-name site-name-text-link" href="https://python-eng.com" itemprop="url"><span class="site-name-text" itemprop="name about"><img alt="パイソニスタの道" class="site-logo-image header-site-logo-image" src="http://python-eng.com/wp-content/uploads/2019/09/パイソニスタの道.png" width="600"/></span></a></h1>
2
<div class="header-in wrap cf" id="header-in" itemscope="" itemtype="https://schema.org/WebSite"><div class="tagline" itemprop="alternativeHeadline">Pythonをメインにプログラミング言語や必要な数学知識を発信していきます。</div><h1 class="logo logo-header logo-image"><a class="site-name site-name-text-link" href="https://python-eng.com" itemprop="url"><span class="site-name-text" itemprop="name about"><img alt="パイソニスタの道" class="site-logo-image header-site-logo-image" src="http://python-eng.com/wp-content/uploads/2019/09/パイソニスタの道.png" width="600"/></span></a></h1></div>
3
<div class="header-in wrap cf" id="header-in" itemscope="" itemtype="https://schema.org/WebSite"><div class="tagline" itemprop="alternativeHeadline">Pythonをメインにプログラミング言語や必要な数学知識を発信していきます。</div><h1 class="logo logo-header logo-image"><a class="site-name site-name-text-link" href="https://python-eng.com" itemprop="url"><span class="site-name-text" itemprop="name about"><img alt="パイソニスタの道" class="site-logo-image header-site-logo-image" src="http://python-eng.com/wp-content/uploads/2019/09/パイソニスタの道.png" width="600"/></span></a></h1></div>
4
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>
5
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」エラー処理(try・except)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」ジェネレータ・デコレータ</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」関数(引数・クロージャ・ラムダ)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」内包表記(リスト・辞書・集合 など)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」for文(break・continue・zip・range)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」while文(breakとcontinue)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」if文による比較</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」集合の操作(作成・追加・削除 など)</h2>]
6
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」ジェネレータ・デコレータ</h2>
7
<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」エラー処理(try・except)</h2>
8
[<h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」エラー処理(try・except)</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」モジュールのインストールとインポート</h2>, <h2 class="entry-card-title card-title e-card-title" itemprop="headline">「Python3」オブジェクトとクラス</h2>]
9
<div class="entry-card-snippet card-snippet e-card-snippet">ジェネレータは、Pythonのシーケンスを作成するオブジェクトです。
ジェネレータは、反復処理のたびに最後に呼び出されたの場所を管理し、次の値を返します。    
デコレータは、入力として関数を受け取り、別の関数を返す関数です。
実際に、ジェネレータとデコレータを使ってみましょう。</div>
10
[<div class="entry-card-snippet card-snippet e-card-snippet">ジェネレータは、Pythonのシーケンスを作成するオブジェクトです。
ジェネレータは、反復処理のたびに最後に呼び出されたの場所を管理し、次の値を返します。    
デコレータは、入力として関数を受け取り、別の関数を返す関数です。
実際に、ジェネレータとデコレータを使ってみましょう。</div>,<div class="entry-card-meta card-meta e-card-meta"><div class="entry-card-info e-card-info"><span class="post-date">2019.09.19</span></div><div class="entry-card-categorys"><span class="entry-category">Python</span></div></div>]
11
None
12
[]

適当に作ってみた

<ソースコード>
import requests
from bs4 import BeautifulSoup

url = "https://python-eng.com/"

r = requests.get(url)

soup = BeautifulSoup(r.content, "html.parser")
divs = soup.find_all("div", class_="entry-card-content card-content e-card-content")
c = 1
for div in divs:
    print("・"+str(c)+"個目")
    c += 1
    print("タイトル---------------------------------------")
    print(div.h2.string)
    print("説明文-----------------------------------------")
    s = div.find("div", class_="entry-card-snippet card-snippet e-card-snippet").string
    s = s.lstrip("\n        ")
    print(s)
    print("カテゴリー-------------------------------------")
    for cate in div.find("div", class_="entry-card-categorys"):
        print(cate.string)
    print("----------------------------------------------\n")
<出力結果>
・1個目
タイトル---------------------------------------
「Python3」Webスクレイピング(requests・beautifulsoup4)
説明文-----------------------------------------
Webスクレイピングは、Webサイトから情報を抽出し、その情報を分析可能な構造化データに変換する処理を指します。今回は、2つのライブラリ(requests・beautifulsoup4)を使用してWebスクレイピングを行おうと思います。
カテゴリー-------------------------------------
Python
----------------------------------------------

・2個目
タイトル---------------------------------------
「Python3」オブジェクトとクラス
説明文-----------------------------------------
Python公式サイトのドキュメントでは、オブジェクトとは「データを抽象的に表したもの」と表現されています。つまり、Pythonで書いたプログラムが操作したり、処理したりするデータのことを「オブジェクト」といいます。
またクラスとは、オブジェクトを生成するうえで使われる型のようなものになります。
カテゴリー-------------------------------------
Python
----------------------------------------------
*省略

コメント

タイトルとURLをコピーしました