[python][scraping]PythonによるWebスクレイピング

pexels-photo-6654031.jpeg python
Photo by cottonbro on Pexels.com

出典

Web Scraping with Python, 2nd Edition, Ryan Mitchell, O’Reilly, 978-491-98557-1

Web Scraping with Python, 2nd Edition
If programming is magic then web scraping is surely a form of wizardry. By writing a simple automated program, you can query web servers, request data, and pars...

GitHubリンクは以下。

GitHub - REMitchell/python-scraping: Code samples from the book Web Scraping with Python http://shop.oreilly.com/product/0636920034391.do
Code samples from the book Web Scraping with Python - REMitchell/python-scraping

第I部 スクレーパーを作る

第1章 最初のWebスクレーパー

1.2 初めてのBeautifulSoup

Beautiful Soup Documentation — Beautiful Soup 4.12.0 documentation

インストールについては割愛。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bs = BeautifulSoup(html.read(), "html.parser")
print(bs.h1)

#出力
<h1>An Interesting Title</h1>

これははじめに見つかったh1タグのみ返却する。

なお、BeautifulSoupでは.read()を付けなくてもオブジェクトを認識できる。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bs = BeautifulSoup(html, "html.parser")
print(bs.h1)

#出力
<h1>An Interesting Title</h1>

h1タグを直接呼び出すこともできる。

bs.html.body.h1
bs.body.h1
bs.html.h1

すべて同じ結果である。ここではparserとしてhtmlを指定したが、

bs = BeautifulSoup(html, "lxml")
bs = BeautifulSoup(html, "html5lib")

を指定することも可能である。特別な場合がなければhtml.parserを指定しておけば良い。

第2章 高度なHTMLパース

2.2 BeautifulSoupの使い方

https://pythonscraping.com/pages/warandpeace.html

のページを用いる。登場人物の語った行が赤で、登場人物の名前は緑で表示されている。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://pythonscraping.com/pages/warandpeace.html")
bs = BeautifulSoup(html, "html.parser")
namelist = bs.find_all("span", {"class":"green"})
for name in namelist:
    print(name.get_text())

#結果
Anna
Pavlovna Scherer
Empress Marya
Fedorovna
Prince Vasili Kuragin
Anna Pavlovna
St. Petersburg
the prince
Anna Pavlovna
Anna Pavlovna
the prince
the prince
the prince
Prince Vasili
Anna Pavlovna
Anna Pavlovna
the prince
Wintzingerode
King of Prussia
le Vicomte de Mortemart
Montmorencys
Rohans
Abbe Morio
the Emperor
the prince
Prince Vasili
Dowager Empress Marya Fedorovna
the baron
Anna Pavlovna
the Empress
the Empress
Anna Pavlovna's
Her Majesty
Baron
Funke
The prince
Anna
Pavlovna
the Empress
The prince
Anatole
the prince
The prince
Anna
Pavlovna
Anna Pavlovna

2.3 正規表現

よく用いられる正規表現の表。

記号意味合致する文字列の例
*先行する文字、部分式、角括弧文字の\(0\)個以上と一致a*b*aaaaaaaa, aaabbbbb, bbbbbb
+先行する文字、部分式、角括弧文字の\(1\)個以上と一致a+b+aaaaaaaab, aaabbbbb, abbbbbb
[]角括弧内の任意の文字[A-Z]*APPLE, CAPITALS, QWERTY
()まとめた部分式(a*b)*aaabaab, abaaab, ababaaaaab
{m, n}先行する文字、部分式、角括弧文字を\(m\)個から\(n\)個(両端含む)と合致a{2, 3}b{2, 3}aabbb, aaabbb, aabb
[^]角括弧にない文字と合致[^A-Z]*apple, lowercase, qwerty
||で区切られた文字や部分式のどちらかに合致b(a|i|e)dbad, bid, bed
.任意の\(1\)文字(記号、数字、空白を含む)と合致b.dbad, bzd, b$d, b d
^文字または部分式が文字列の先頭にあることを示す^aapple, asdf, a
\エスケープ文字\^\|\\^|\
$正規表現の末尾として用いる。[A-Z]*[a-z]*$ABCabc, zzzyx, Bob
?!「含まない」。^((?![A-Z].))*$no-caps-here, $ymbols a4e f!ne
python3の正規表現のまとめ。

第II部 高度なスクレイピング

ログインが必要なサイトでのスクレイピング

本題はここから。本書の内容からはだいぶ離れる。Seleniumによるスクレイピングを行わずに、requests libraryを用いる。インストールしていない場合はpipでインストールしておく。

pip install requests

必要なlibraryはここでimportしておく。

#import libraries
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from urllib.parse import urljoin
from bs4 import BeautifulSoup
import re
import requests
import time

最重要注意点

ログインが必要なサイトでスクレイピングをする場合、最も重要なのが、\((1)\)通常のwebブラウザで覗くログイン画面のurlと、\((2)\)actionをpostするurl、および\((3)\)ログイン後のurlの\(3\)つを特定することである。これがはじめはわからず、時間を取られた。このうち前\(2\)つの情報はwebサイトのソースを見れば分かる事が多い。ログイン後のurlは実際にwebブラウザを用いてログインすれば分かる。

login_url = "https://www.hogehoge.com/login"#(1)通常のwebブラウザで覗くログイン画面
url_login = "https://www.hogehoge.com//login/confirmation"#(2)actionをpostするurl
url_mp = "https://www.hogehoge.com/mp"#ログイン後のurl, my page

この\(3\)つが分かればログイン後のwebサイトでスクレイピングが可能である。

sessionの開始

以下の”login_id”でサイトのログインに必要なID(メールアドレスなど)、”my_password”でログインに必要なパスワードを指定する(ダブルでもシングルでも良いが、クオテーションで囲む)。responseで指定しているのは\((1)\)通常のwebブラウザで覗くログイン画面のurlである。

session = requests.session()
response = session.get(login_url)
bs = BeautifulSoup(response.text, "html.parser")

login_data = {
    "loginId":"loging_id",
    "loginPassword":"my_password"
}

tokenの取得

多くのwebサイトではログイン情報をtokenで管理している。

authenticity_token = bs.find(attrs = {"name":"_token"}).get("value")
login_data["_token"] = authenticity_token

これをloginのときに渡してやらないとうまくログインできない。tokenの名前はサイトによって異なるが、多くは”_token”で終わっているので、これを探す。名前を付けて”login_data”にわたすときは、各々のサイトで用いられている名前をつける。これもwebサイトのソースで確認することができる。

cookieの管理

これも必要に応じて追加する。

response_cookie = response.cookies

ログインアクションのpost

ここまでくれば必要な情報は揃っている。ここで指定している”url_login”は\((2)\)actionをpostするurlである。

login = session.post(url_login, data = login_data, cookies = response_cookie)
time.sleep(1)

ログインに成功したら

statusが200になる。下のreqで指定しているのは\((3)\)ログイン後のurlである。

req = session.get(url_mp)
#req.status_code
bs2 = BeautifulSoup(req.text, "lxml")
bs2

このbs2にログインした後の必要な情報が含まれる。後は通常のスクレイピングと同様に行えば良い。

全体のcode

#import libraries
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from urllib.parse import urljoin
from bs4 import BeautifulSoup
import re
import requests
import time

login_url = "https://www.hogehoge.com/login"#(1)通常のwebブラウザで覗くログイン画面
url_login = "https://www.hogehoge.com//login/confirmation"#(2)actionをpostするurl
url_mp = "https://www.hogehoge.com/mp"#ログイン後のurl, my page

#セッションの開始
session = requests.session()
response = session.get(login_url)#(1)のurl
bs = BeautifulSoup(response.text, "html.parser")

#ログイン情報の設定
login_data = {
    "loginId":"loging_id",
    "loginPassword":"my_password"
}

#tokenの取得
authenticity_token = bs.find(attrs = {"name":"_token"}).get("value")
login_data["_token"] = authenticity_token#渡す名前はサイトによって異なる

response_cookie = response.cookies
login = session.post(url_login, data = login_data, cookies = response_cookie)#(2)のurl
time.sleep(1)

req = session.get(url_mp)#(3)のurl
#req.status_code
bs2 = BeautifulSoup(req.text, "lxml")
bs2#ここにログイン後の情報がある

例えば、Webサイトにあるcsvファイルをダウンロードしたい場合、以下のようにすると良い。

f = open("/Users/Desktop/file.csv", "wb")
f = write(req.content)
f.close()

このようにする場合、あらかじめDesktopにfile.csvを用意しておく。

関連リンク

JSONファイルの読み込みについて

PythonでWeb上の画像などのファイルをダウンロード(個別・一括) | note.nkmk.me
Pythonで、Web上のファイル(画像やZIP、PDFなど)のURLを指定してダウンロード・保存する方法について説明する。 URLを指定してファイルをダウンロードurllib.request.urlretrieve()urllib.request.urlopen()とopen ...

コメント

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