先週 Let’s start Python #2 に参加してきました!今回の講座内容はスクレイピングなのでとても楽しみでした。
スクレイピングは興味ある人多いと思うんですけど、勉強する機会ってなかなかないんですよねー。ProgateにもPaizaラーニングにも見当たらないし、業務で使う訳でなく趣味で使ってみたいだけなので、書籍購入してまでの学習コストは掛けたくないし。。
クローリング、スクレイピング基礎
クローリングとは、リンクを辿ってWebページを収集すること
スクレイピングとは、収集したWebページ(HTML)から必要な情報を抜き出すこと
クローリングとスクレイピング実施時の注意事項
これが知りたかったです!勝手にスクレイピング(クローリング)しちゃダメなんだろうなーとは思いつつ、どういうルールで許可/拒否されているんだろうと疑問に思ってました。
- Webサイトによっては、クローリングが禁止されている
- robots.txtやrobots metaタグで拒否されているページをクロールしないこと
- Webサーバへの負担をかけないよう配慮して作成する(最低1秒は間隔をあける)
Googleを例にした場合、下記のようにrobots.txtにアクセスすると、どのページが許可されていて、どのページが拒否されているのかを確認できます。
https://www.google.co.jp/robots.txt
# robots.txt User-agent: * Disallow: /search # /search以下は基本的にクロール禁止 Allow: /search/about # /search/aboutのみクロール許可 Allow: /search/static # /search/staticのみクロール許可
詳細は、 robots.txt の概要に記載されています。
仮想環境構築
今回ライブラリのインストール等を行うので、今回の作業用の仮想環境を構築します。Windows用とMac用の説明がありました。WSLでUbuntu(Linux)使っている人は少ないんですね(使用コマンドは適宜置き換えました)。Macはいいとして、WindowsでコマンドプロンプトからPython使うとか、お疲れ様です!としか言えない(20年以上前のターミナルをまだ使うってことは、メインフレームをまだ使っているに等しい)。。
$ mkdir elv_python # 作業ディレクトリ作成 $ cd elv_python $ python3 -m venv myvenv # 仮想環境をvenvライブラリで作成 $ source myvenv/bin/activate # 環境設定ファイルを読み込む $ pip install requests # ライブラリのインストール $ pip freeze # 確認 certifi==2019.6.16 chardet==3.0.4 idna==2.8 pkg-resources==0.0.0 requests==2.22.0 # インストールされている urllib3==1.25.3
Webページの情報をクローリング
$ vi sc_1.py import requests url = "http://sandream.main.jp/elv_python/first" # サンプルURL response = requests.get(url) # HTMLを取得 response.encoding = response.apparent_encoding # エンコーディング print(response.text) $ python3 sc_1.py # クローリング実行 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>初めてのスクレイピング</title> </head> <body> <h1>初めてのスクレイピング</h1> <p>スクレイピングテスト</p> </body> </html>
Web情報を解析する(スクレイピング)
$ pip install beautifulsoup4 # ライブラリのインストール $ pip freeze # 確認 $ vi sc_4.py # スクレイピングのソースファイル作成 import requests from bs4 import BeautifulSoup # スクレイピングに特化したモジュール url = "http://sandream.main.jp/elv_python/second" # サンプルURL response = requests.get(url) # HTML取得 response.encoding = response.apparent_encoding # エンコーディング # BeautifulSoupにファイルとhtml parserを渡してインスタンスを作成 # html.parser:htmlのタグ情報から情報を解析するプログラム bs = BeautifulSoup(response.text, 'html.parser') ul_tag = bs.find('ul') # ulタグで囲まれた部分を抽出 for a_tag in ul_tag.find_all('a'): # ulタグの中のaタグを抽出 text = a_tag.text # aタグのテキストを取得 link_url = a_tag['href'] # aタグのhref属性を取得 print('%s: %s'%(text, link_url)) $ python3 sc_4.py # 実行結果 どこにも行かない1: http://sandream.main.jp/elv_python/1 どこにも行かない2: http://sandream.main.jp/elv_python/2 どこにも行かない3: http://sandream.main.jp/elv_python/3 どこにも行かない4: http://sandream.main.jp/elv_python/4 どこにも行かない5: http://sandream.main.jp/elv_python/5
練習問題
■問題
http://sandream.main.jp/elv_python/exercises
の中のリンク先に記載されているpタグ内のテキストだけを表示しましょう
■私の回答
全てのhref属性を取得して、その後でpタグを取得したので、for文を2回も回してしまいました。
$ vi sc_5.py import requests import time from bs4 import BeautifulSoup url = "http://sandream.main.jp/elv_python/exercises" response = requests.get(url) # HTMLを取得 response.encoding = response.apparent_encoding # エンコーディング # BeautifulSoupにファイルとhtml parserを渡してインスタンスを作成 bs = BeautifulSoup(response.text, 'html.parser') link_url = [] ul_tag = bs.find('ul') # ulタグで囲まれた部分を抽出 for a_tag in ul_tag.find_all('a'): # ulタグの中のaタグを抽出 link_url.append(a_tag['href']) # aタグのhref属性を取得 for url in link_url: response = requests.get(url) response.encoding = response.apparent_encoding bs = BeautifulSoup(response.text, 'html.parser') p_tag = bs.find('p') # pタグを取得 print(p_tag.text) time.sleep(1) # 1秒間隔をおく $ python3 sc_5.py # 実行結果 すばらしい仕事をするには、自分のやっていることを好きにならなくてはいけない。 まだそれを見つけていないのなら、探すのをやめてはいけない。 安住してはいけない。 心の問題のすべてがそうであるように、 答えを見つけたときには、自然とわかるはずだ。
※ 「by スティーブジョブス」だそうです。いい言葉ですね!
私はインフラエンジニアに安住せず探して、Webエンジニアという答えを見つけました~!
■模範解答
href属性を取得してそのままpタグも取得すれば、for文は1度で済みますね汗
動くコードは書けるけど、よいコード(技術的負債のない)を書くにはまだ精進が必要のようです!
$ vi sc_5.py import requests import time from bs4 import BeautifulSoup url = "http://sandream.main.jp/elv_python/exercises" response = requests.get(url) # HTMLを取得 response.encoding = response.apparent_encoding # エンコーディング # BeautifulSoupにファイルとhtml parserを渡してインスタンスを作成 bs = BeautifulSoup(response.text, 'html.parser') ul_tag = bs.find('ul') # ulタグで囲まれた部分を抽出 for a_tag in ul_tag.find_all('a'): # ulタグの中のaタグを抽出 link_url = a_tag['href'] # aタグのhref属性を取得 detail_response = requests.get(link_url) detail_response.encoding = detail_response.apparent_encoding detail_bs = BeautifulSoup(detail_response.text, 'html.parser') detail_p_tag = detail_bs.find('p') # pタグを取得 print(detail_p_tag.text) time.sleep(1) # 1秒間隔をおく
主催者の方の資料:python_elv_2
※ 上下左右ボタンでページが切り替わります。
Kindleのデータを収集したい
・Prime Reading
Amazonプライム会員になっていると、Prime Readingという読み放題サービス(949冊)があるので、ここから自分が興味ありそうな本を抽出したい。
・Kindleオーナーライブラリー
Amazonプライム会員でかつKindle Fireを持っていると、Kindleオーナーライブラリという月1冊が無料で読めるサービス(641冊)があるので、ここから自分が興味ありそうな本を抽出したい。
robots.txtの内容を確認してみたところ、自分のwishlistだけスクレイピングが許可されてました笑 まあ当然というか、スクレイピングはダメということですね。
AmazonならAPIが用意されていると思ったので、下記の記事に目を通す。Product Advertising APIを使用するには、Amazonアソシエイトへの登録が必要とのこと。Amazonアソシエイトは、登録後に1年間放置してたら(売り上げないから)アカウント閉鎖されてしまってました。。おとなしく、ブラウザの画面から地道に探すことにします。。