ウェブスクレイピング

下位ページ

Content

Pythonでウェブスクレイピング


ライブラリの使用

BeautifulSoup


urllib3

リクエストの方法

  • 基本?PoolManagerインスタンスを使って、操作を行う
  • PoolManager で request を実行する
    • Httpレスポンスオブジェクトを返す
      • status
      • header
      • data
      • などなど

>>>import urllib3
>>>http = urllib3.PoolManager()
>>>r = http.request('GET', 'http://httpbin.org/robots.txt')
>>>r.status
200
>>>r.data
'User-agent: *\nDisallow: /deny\n'

デコード
r.data.decode('utf-8')

Httpレスポンスコンテナ

selenium

JavaScriptも動かしてページを表示させているページだったので、ブラウザも一旦起動する方法をとった。その際に使った。


  1. browser を動かせる状態にする
  2. ブラウザ上の要素を取得する
  3. 走査を加える
  4. 2,3を繰り返す

webdriver

ブラウザを開く(操作する?)ためのドライバーも準備(selenuimのぺーじからダウンロードした)
自動でパスが通る場所においていなかったので、バスを通す
from selenium import webdriver


# version 2.0 は webdriver付属、みたいに書いてあったのだが・・・
driver = webdriver.Firefox(executable_path="C:/Users/.../geckodriver.exe")
driver.get(url)
print(driver.find_element_by_id("zansu6").text)
driver.close()

ページを取得する(開く)

driver.get(url)

要素の取得



idで
classで
cheeses = driver.find_elements_by_class_name("cheese")

テキストを取得する

element.text
textプロパティで取得できる。このとき、タグは含んでいない。
Getting text values - Selenium

ヘッドレス化

データを取得するだけなら、ウィンドウを開く必要はない。「ヘッドレスブラウザ」は画面を表示しないブラウザ。
Chrome や Firefox はヘッドレスブラウザとして動かすことができる。

Firefoxの場合
from selenium.webdriver.firefox.options import Options
 
# selenium と geckodriver を つかって、firefox を開く(ヘッドレス)
options = Options()
options.add_argument("--headless")
driver = webdriver.Firefox(executable_path="/PathOfFirefox/geckodriver.exe", \
                           firefox_options=options)
 

2段階認証が必要な必要なサイトを何とかする

  • やりたかったこと
    • 自分があるサイトに構築している、複数ページに渡るリストを取得すること
  • 現状
    • リスト取得に対してはAPIが公開されていない。
    • リストは単純な追加作業ばかりでなく、途中で部分的に削除することもある
    • しかしながら、そのサイトは「独自のアカウント」がない
      • googleだったりYahooだったりDocomoだったりのアカウントを使っての登録が必須
    • 自分が使っているgoogleのアカウントで入ろうとすると、スマホ端末での認証が必要となり、ウェブの範囲を超えている。

思いつく、「ステップ」としては次くらいか?
  1. とりあえず認証を手作業でやる
  2. 一度認証できたら、cookieなどで記憶させて次回以降のログインを飛ばす
  3. (最初から自動ログインにする←2ができていたら、多分、この作業はあまり意味がない)

とりあえず認証作業は手作業で行って、途中から自動にする

作業の途中からseleniumに任せる方法がわからなかったので、最初はログインの認証画面に遷移されたタイミングで
import time
time.sleep(60)
 
sleepメソッドで止めようとしたが、「確立された接続が。。。。」というエラーメッセージで止まってしまう。さらに言えば、selenium IDEで作業を追ってみても、「次へ」ボタンがうまく特定できない。この辺は実力の無さか?

WebDriverWait

WebDriverWaitで作業を止めて、作業ができる状態になったら、再スタートするようにした。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
wait = WebDriverWait(driver,120)
wait.until(EC.title_contains("リスト"))
 

流れは
  • ログインができるページに飛ぶ(自動)
  • google認証のページに飛ぶ(手動)
  • googleのアカウント名を入力→確認ボタン(手動)
  • googleのアカウントのパスワードを入力→確認ボタン(手動)
  • スマホで2段階認証(当然手動)
  • リダイレクト
  • トップページ→目的のページへのリンククリック(手動)
  • 目的にページが開かれたら、発火(ここから自動化)
  • 認証を済ませる。そのあと、リストのあるページに行く。
まだまだ自動化できる部分もあるが、エラーもぼちぼち出て、面倒になって、この方法に。

wait.until(value)
value が真になったら発火させる

何で発火させるかは、expected_conditions を使って指定している。
本来の使い方は、動的に表示データを生成するようなページに向けての模様。

使い方の分類としては明示的な待機になるのか?「何を待つか」に関して、準備されているものもあれば、独自に作ることもできるらしい。



expected_conditions 要素が表示されたら発火

要素の表示で使い場合は、
EC.presence_of_element_located


ログイン情報に cookie を使用する

普段はログイン作業を通らずにリストが表示される、ということは、クッキーにセッション情報か何かが残っているわけで、一度ログインをすればクッキーが使えるはず。

※最初からログインした状態のブラウザから読み出した cookie 情報でログインすればよかったのだが、後述のミスで、cookie 情報の読み込みができなかった。。。

cookie 情報を書き出す

driver.get_cookies()
複数クッキーがあるかもしれないので、読み出した後 for か何かで回したものを print すればOK
.get_cookies() - selenium

driver.get_cookie(name)
もあるが、nameがわからないと呼び出せないので、上が良い?

cookie 情報を読み込む

driver.add_cookie(cookie)

cookie の情報としては、dict 型で記述した cookie を準備しておいて、読み込ませる。
読み込ませる(書き込む)タイミングは、関連付けるドメインで get した後。まだ開いていない状態で add_cookie をすると
Document is cookie-abverse
とエラーが出て止まってしまう。

最終更新:2019年01月04日 09:14