作成の経緯
離任一週間前に急にクローリングしてウェブページからデータ取得したいとか言われたので、
とりあえず出来るだけの事を行った。
※自社内のWebページ用に作成したので、ソースコードとかは一切残ってないです。
あとコーディングしてから時間合いてるので間違ってるところとかも多いと思います。
必要であれば修正します。
使った物
・Python3.65
・BeautifulSoup4
・Selenium
準備
各インストール等は省きます。(調べたら死ぬほど出てくるからね)
「BeautifulSoup4」は「BeautifulSoup」で
インストールしようとすると前バージョンがインストールされるのでそこだけ注意しましょう。
各使い方等
僕が使った情報しか書いてないので、全部の機能を使いたいって人は各自ググってね。
BeautifulSoup4:URL
selenium:URL
BeautifulSoup4
from bs4 import BeautifulSoup
soup = BeautifulSoup("ファイルパス", "html.parser")
とりあえずこれでローカルに置いてあるhtmlは読み込める。
import urllib2
from bs4 import BeautifulSoup
html = urllib2.urlopen("ページURL")
soup = BeautifulSoup(html, "html.parser")
URLは直接入力してはダメみたいなので、urllib2を使おうね。
parserってものをよく理解せずに使ってましたが、
とりあえずこれで進めていきました。
ここから重要
htmlファイル内のタグで囲われてる部分のデータ取得方法とか
この辺が結構辛かった。
soup.find_all("dev")
これで、対象ページのdevタグに書いてある内容全部list形式で取ってきてくれる。
(最近のページdevいっぱい使ってるからdevを探す時は気をつけようね)
soup.find_all("dev", class_="class_name")
こんな感じで書けば複数の条件で絞れる、
しかし、同じタグ内に書かれた属性しか取れないので、
絞り込むならもうちょっと頑張ろう。
あと、「class」はPythonの予約で使われてるので「class_」で書きます。
複数指定しててもJSってのは同じタグを沢山散りばめているので、
不要な箇所が取れることがある。
そんな時は親要素で絞り込むと良かった。
for children in soup.find_all("dev", class_="class_name")
if children.parent.find("目的のタグ名") == "タグ名":
target = children
ifの条件式は手元で試してないので怪しいしforも要らなかった気がするが、
children.parent.find()で子要素から上のタグを順番に見ていき
最初に見つかったタグを返してくれる。(うまく取れなかったら調整してね)
これで90%位目的の物が取得出来るのと思う・・・
出力とか
今回は現場でCSVずっと使ってたのでCSVで出力しました。
(JSONとかわからんちん)
with open("failname.csv", "w") as f:
for tmp in target #targetはfindとかで取れたlist
f.write(tmp + "\n")
こんな感じで書き込みは問題ないと思う。
必要に応じてlistが増えるならzipでまとめて好きな雛形にしようね。
今更だがpandasとか触ればよかったなと思った。
とりあえずこれで取りたいhtmlファイルをスクレイピングしよう。
適当にURLとか引数にして関数とかにしてもいいかもね。(僕はそうしました)
selenium
今回使ったブラウザはクロームです。
それしかブラウザが対応してないって言われた。
(そんなWebページ作るのは辞めようね)
from selenium import webdriver
driver = webdriver.Chrome(executable_path="chromedriverのファイルパス")
webdriverのパスが通って入れば引数は要らないらしいですが、
僕はパスを通したくなかったので、適当なディレクトリに置いて実行しました。
driver.get("クローリングしたいURL")
これで対象のページが開きます
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
name_w = driver.find_element_by_name("UserID")
pass_w = driver.find_element_by_class_name("password")
name_w.send_keys("UseID")
pass_w.send_keys("password").send_keys(Keys.RETURN)
#driver.find_element_by_class_name("SignInButton").click() #本来はこれでボタンをクリックできる。
time.sleep(10)
ログインが必要だったため、ログインページに移動した後、上記を実行しました。
実際こんな書き方してる所無いと思うけど、こんな感じでWebElementってのを取得できて、
そのWebElementに文字を入力したり、EnterKeyを押したり出来る。
もちろんTextも取得することが出来る。(他にも沢山出来ることがあるから調べようね)
ちなみにコメント部分のように記載しクリックすることも出来るが、
今回はなぜか反応しないのでパスワードを入力した時点でエンターキー押して
無理やり画面遷移しています。
※sleepを挟まないと画面ロード中に次の動作しちゃうので、画面遷移する時はつけようね。
でもselenium自体に待機させる、関数あるみたいなので、そっち使ったほうがいいかも
やっぱりSeleniumでも親要素とか取りたくなるときがあると思います。
その時はxpathってのを使いましょう。(僕はよくわからない。)
Seleniumの使い方はページ移動してURLとかページソース読み取るくらいなので、
大抵は上記のような感じで必要なWebElementをかき集める方向だと思う。
実際僕はURLを取得して、それをBeautifulSoupに渡してるぐらいの利用方法だった。
実際にやってみて
実際にやってみて、思ってたよりかはハードルが低そうな技術かなぁと感じた。
もちろんやり込めば沢山出来ることがあるので、習得するのが簡単というわけでは無いです。
もっとシンプルなWebページをクローリングしてスクレイピングしてとなると、
ストレスフリーで快適な解析が行えると思うので、
次回行うことがあるのであれば、JSとか作り込みが少なくシンプルなサイトで行いたいと思う。
あとこの記事を書くにあたってコーディングした時期がちょっと空いてしまったので
だいぶ記憶から抜け落ちてるところがあったなと・・・
次何かの記事書く際には早めもしくは同時に書いてかないときつい。
以上になります。