PythonとSeleniumで自分のツイートを抽出する

本日2件目。PythonSeleniumを使って自分のツイートを抽出します。 API叩けばすぐ済むことを敢えてスクレイピングでやる。熱い。

やりたいこと

  • https://twitter.com/にアクセス
  • ログインボタンを押し、出てきたinputタグにユーザー名とパスワードを記入、ログイン
  • 最初のページから、マイページへ移動
  • 何もせずに出ている20ツイートくらいをテキストで抽出
  • 抽出したツイートをターミナルで表示+csv出力

Seleniumの準備などにはdockerを使っています。 その辺りの環境構築は今回は省略。

今回試した方法

  1. PhantomJSという仮想ブラウザを取得
  2. Twitterにアクセス
  3. Seleniumでログイン
  4. マイページに移動
  5. ツイートを取得してターミナルに出力
  6. csvにも出力

元ネタとして参考にしたのは、こちら。

実はNewsPicksで似たようなことをしていたんだけど、後々アウトなことを知ったのであげられず。 なので今回はTwitterで簡単なバージョンを作ってみました。

コードはこちgetTweet · GitHub

それでは順に見ていきます。

1. PhantomJSのブラウザを取得

# PhantomJSのドライバを得る
browser = webdriver.PhantomJS()
browser.implicitly_wait(3) #念のため3秒待機

スクレイピングをやるときはマナーとして定期的に休みをとる。とらないとサーバにめちゃくちゃ負担かかるらしいので。

2. Twitterにアクセス

browser.get()で指定のURLにアクセス。 browser.save_screenshot()でスクリーンショットをとる。 今回はブログ用に写真をとってます。

# Twitterにアクセス
url = "https://twitter.com/"
browser.get(url)
browser.save_screenshot("toppage.png") #証拠写真撮影

証拠写真こちf:id:cyclemem:20170701165822p:plain

3. ログインする

まずは右上にあるログインボタンをクリック Seleniumだと、find_element_by_css_selectorでCSSセレクタを指定した要素が取得できる そこをe.click()でクリックしているだけ。

#ログインボタンをクリック
e = browser.find_element_by_css_selector(".StreamsLogin")
e.click()
browser.implicitly_wait(10) #反映に時間がかかるので待つ
browser.save_screenshot("login.png") #証拠写真撮影

そうすると、さっきの画面がこうなる。 f:id:cyclemem:20170701170054p:plain

次に指定したユーザIDとパスワードを入力する。 ここでUSER、PASSとなってるのは、あとで全文載せるけど、最初のほうで指定している さっきと同じ要領で、ユーザIDの入力欄を取得し、念のためclearで初期化。send_keysで指定文字列を入力する。

# ユーザIDとパスワードを入力
e = browser.find_element_by_css_selector(".email-input")
e.clear()
e.send_keys(USER) #ここでユーザIDを入力

e = browser.find_element_by_css_selector("input[type=password]")
e.clear()
e.send_keys(PASS) #ここでパスワードを入力

browser.implicitly_wait(5) #念のため5分待って
browser.save_screenshot("login_with_info.png") #証拠写真撮影

結果がこちら、 f:id:cyclemem:20170701170424p:plain

最後に、ログインボタンを取得してクリックするとログイン完了。

#送信ボタンをクリック
e = browser.find_element_by_css_selector(".submit")
e.click()
browser.implicitly_wait(5) #念のため5分待って
browser.save_screenshot("success.png") #証拠写真撮影

やったぜ f:id:cyclemem:20170701170525p:plain

4. マイページに移動

これは簡単で、上のページのアカウント情報にあるヘッダー画像をクリックすればいい。

#マイページに移動
e = browser.find_element_by_css_selector(".DashboardProfileCard-bg")
e.click()

browser.implicitly_wait(3) #念のため3秒待って
browser.save_screenshot("mypage.png") #証拠写真撮影

結果はこちら。自分のページに移動しています。 f:id:cyclemem:20170701171004p:plain

5. ツイートを抽出して、ターミナルに出力

さっきと同様にツイートを取得。今回は複数あるので、find_elements_by_css_selectorを使う。 element→elementsにするだけで複数形になる親切設計。

またこのあとcsvに書き込むときにツイートがリストになってると便利なので、事前に用意しておく。

ここまで出来たらツイートを出力したいのだけど、抽出したtweetsにはいろんな情報が入っているので、textだけを出力する。

# ツイートを抽出
tweets = browser.find_elements_by_css_selector(".tweet-text")

#csvに読み込む用のリストを生成
tweet_list = []

# ツイートの出力
for tweet in tweets:
    t = tweet.text #ツイートのテキストを出力
    tweet_list.append(t) #リストに追加
    print(t) #ターミナルに出力

結果がこちら。黒い画面かっこいい! f:id:cyclemem:20170701171319p:plain

6. csvに出力

さっきのだけだと面白くないので、せっかくだから外部ファイルに出力する。

# csvに入れまくる
with codecs.open("tweets.csv", "w", "utf-8") as fp:
    writer = csv.writer(fp, delimiter=",", quotechar='"')
    writer.writerow(["tweet"])
    for tweet in tweet_list:
        writer.writerow([tweet])

結果は、こんな感じ。内容は変わらないけど。 f:id:cyclemem:20170701171437p:plain

以上!

まとめ

こんな感じでSeleniumを使ってログインからスクレイピングまでは上手くいきました。 ただ業務で使うのはJavaなので、この後そっちでも試してみます。 またあげるかも。では。