圏9研究所 工作室

圏9研究所の開発情報資料など

圏9微博Webスクレイピング~微博フォロアー数を解析する python版追加

フォロアー数を読み込んでcsvファイルに追記をpythonで作る

1.準備
1)selenium
Web ベースアプリケーションのテスト自動化の高速開発をサポートした堅牢なツール群
インストールします

2)ブラウザとドライバ
(1)Firefox
・geckodriverをダウンロード解凍して /usr/local/bin に保存する
・ブラウザのバージョンにマッチしたドライバを選ぶ
・ブラウザはアプリケーションフォルダーに置く
(2)Chrome
・ChromeDriverをダウンロード解凍して /usr/local/bin に保存する
・ブラウザのバージョンにマッチしたドライバを選ぶ
・ブラウザはアプリケーションフォルダーに置く
(3)Safari
・ドライバはインストールされている
・がしかし ブラウザもドライバもenableにしないと動かない
・ブラウザenable 開発メニュー:リモートオートメーションを許可を選んでチェックが入るようにする
・ドライバenable ターミナルでrootにして

$ su
Password:
# safaridriver --enable
# exit
exit

2.ページ読込完了条件を決める
Applescriptで使った「target_URLの文書と全ての副リソースの読み込みが完了したら」の方法が見つからなかったので
ターゲットの微博ページソースを見て読み込み完了ポイントを探す
・今回はいろいろあってフォロアー数の書いてある a タグにしてみた

<div class="obj_name">
	<h2 class="main_title W_fb W_f14">
		<a class="S_txt1"  href="/p/1004063279873201/follow?relate=fans" >
			她的粉丝(1160827)	    <— これ
		</a>

3.コード

#
#   Weibo fans取得
#
#       抽出するタグ
#           <h2 class=\"main_title W_fb W_f14\">
#               <a class=\"S_txt1\"  href=\"\/p\/1004063279873201\/follow?relate=fans\" >
#                   她的粉丝(1160827)
#               <\/a>

#   ブラウザ指定
browser = 'safari'
#browser = 'chrome'
#browser = 'firefox'

import sys
import re
import datetime
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

if browser == 'chrome':
    from selenium.webdriver.chrome.options import Options

# 定数定義
#   URL of Weibo
url_weibo = 'https://www.weibo.com/quan9quan9'
#   csv file
csv_file = '/Users/luke24e-hb/Documents/myfiles/BLOG/fuctry/W100_fanschart/fans_a.csv'
# xpath:fans element in a tag text
fans_xpath = "//a[contains(text(), '她的粉丝')]"

# ブラウザでURLを開く ブラウザ非表示 options.set_headless では動かない
if browser == 'safari':
    driver = webdriver.Safari()
elif browser == 'chrome':
    options = Options()
    driver = webdriver.Chrome(options=options)
elif browser == 'firefox':
    driver = webdriver.Firefox()
driver.get(url_weibo)

# 要素が表示されるまで待機 retry未実装
try:
    #   wait by XPATH
    element = WebDriverWait(driver, 120).until(EC.visibility_of_element_located((By.XPATH, fans_xpath)))

#   time over
except TimeoutException as ex:
    print(str(ex))
    print('time over')
    driver.quit()
    sys.exit(1)

# utf-8でページソースを読み込む
html_sorce = driver.page_source.encode('utf-8')
# lxmlでsoup
soup = BeautifulSoup(html_sorce, "lxml")
driver.quit()

# tag 抽出: <a> tag and text == "她的粉丝(fans)"
#   find_allを使うときは for a_tag in soup.find_all():
a_tag = soup.find('a', text = re.compile("她的粉丝\(\d+\)"))
a_text = a_tag.text
# ()内を抽出:(直前に'('がある) 任意の文字0回以上 (直後に')'がある)
fans = re.search('(?<=\().*?(?=\))', a_text).group()

# datetimeを取得追加
now = datetime.datetime.now()
datetime_str = now.strftime("%Y/%m/%d %H:%M:%S")
csv_str = datetime_str + ',' + fans + '\n'
print(csv_str)

# ファイルに追加書込
f = open(csv_file,'a')
f.write(csv_str)
f.close()

コードのポイント
・要素が表示されるまで待機
XPATHでフォロアー数の入った a タグを待つ
・フォロワー数の抽出
()内を抽出:(直前に'('がある) 任意の文字0回以上 (直後に')'がある)

【まとめ】
1.トラップメモ
結構歯応えありました
①問題
②調査結果
③対応

1)ブラウザとドライバ
①ブラウザが動かない(起動しない、起動してもURLを開かない
②ドライバのバージョンが不一致
③マッチするドライバを使う

②ブラウザの置き場所が違う
③アプリケーションフォルダに置く

safariはenableが必要
③ブラウザとドライバをenableする

2)javascriptが展開するサブコンテンツの表示待ち
①フォロアー数が含まれる div タグのIDで待つことでうまく動いていたが途中から動かなくなった
②ターゲットページのIDが変わった
③フォロアー数が含まれる a タグに変更
お陰様で XPATH の使い方を覚えた

3)()の中身を抽出する
①中身だけ抽出したいが()が付いてくる
正規表現が違う
正規表現の '(' 後読みと ')' 先読みの間の文字を抽出する
# ()の中身を抽出:(直前に'('がある) 任意の文字0回以上 (直後に')'がある)
fans = re.search('(?<=\().*?(?=\))', a_text).group()

2.課題
1)アプリ化
エラーメッセージとかポップアップさせたいけれど面倒くさそうなのでとりあえずこのまま

おしまい

Apple Script版】
luke24e-2h.hatenablog.com

【2020/2/22】
突然動かなくなったので追記
動かなくなった時に試すこと
①URLを変える 微博はよく不安定になる

url_weibo = 'https://www.weibo.com/quan9quan9'
↓
url_weibo = 'https://www.weibo.com/quan9quan9?from=feed&loc=at&nick=WineQ圈9&is_hot=1'

②webdriver ファイル名を明示する chromeのエラーメッセージによる

    driver = webdriver.Safari(executable_path='/usr/bin/safaridriver')
    driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver')
    driver = webdriver.Firefox(executable_path='/usr/local/bin/geckodriver')

③safaridriverを改めてenable safariのエラーメッセージによる

# safaridriver --enable