こんにちは。
私もクロールを初めて勉強しながら、いろいろなことをしてみています。
今回は最近人気のSNSの一つであるインスタグラムに適用してみましょう。
興味を与えるために人の心理を少し利用して、次のような作業をしてみようと思います。
どうですか?やりたくないですか。 🙂
たまにフォローを中断する人がいました。 TT
それではじっくりしてみましょう。
必要なモジュールのインポート
import time
import sys
from selenium import webdriver
from bs4 import BeautifulSoup
seleniumパッケージのwebdriverモジュールはWebブラウザを実行し、スクリプトコマンドに従ってアクションを実行し、bs4パッケージ内のBeautifulSoupモジュールはHTML DOM形式のデータから目的のコンテンツを簡単に抽出する機能を備えています。
seleniumパッケージとbs4パッケージがない場合は、コマンドウィンドウに次のようにそれぞれ入力してインストールしてください。
pip install bs4
pip install selenium
そして、Chrome webdriverは以下のリンクからダウンロードできます。
https://sites.google.com/a/chromium.org/chromedriver/downloads
その他の残りは基本モジュールなのですぐにインポートしてお使いいただけます。
Instagramのログイン
これで、Chromeブラウザを起動してInstagramのアドレスにアクセスしてログインしようとします。
コマンドウィンドウから直接入力してみましょう。
たとえば、コマンドウィンドウに次のように入力をするとします。
python crawling_instagram.py sangminem 123456
ここで、sys.argv[0] は crawling_instagram.py 、sys.argv[1] は sangminem、sys.argv[2] は 123456 になります。
これを活用して、以下のようにインスタにログインするコードを書いてみましょう。
browser = webdriver.Chrome('./chromedriver')
browser.get('https://www.instagram.com/'+sys.argv[1])
browser.execute_script("document.querySelectorAll('.-nal3')[1].click();")
time.sleep(2)
browser.find_element_by_name('username').send_keys(sys.argv[1])
browser.find_element_by_name('password').send_keys(sys.argv[2])
browser.find_element_by_xpath('//*[@id="loginForm"]/div[1]/div[3]/button').submit()
time.sleep(5)
browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/div/div/button').click()
chromedriverを使ってChrome Webブラウザを表示し、Instagramアドレスとユーザー名を組み合わせて接続しました。
browser.execute_scriptを使用してフォロワーボタンをクリックしてログインウィンドウを表示しました。
(ログインしていないときにクリックするとログインウィンドウが表示されるようになっています。)
その後、ロードが長くなるのに備えて2秒待機しました。
次に input タイプが username と password 部分を見つけ、 send_keys メソッドでユーザー名とパスワードを入力するようにしました。
そして、xpathでform内のログインボタンを見つけてsubmitメソッドを呼び出しました。
xpathは、ChromeでF12キーを押すと、出てくる開発者の[Elements]タブで参照したい要素を右クリックし、Copy> Copy xpathを選択すると取得できます。
次回ログインするまで5秒待ちます。
再びxpathを利用して後で下記ボタンをクリックするように作成したコードです。
この部分は単にスキップするための部分なので、詳細な説明は省略します。
フォロワーリストを取得する
これでログインが完了したので、フォロワー数を求めるロジックを実装しましょう。
time.sleep(2)
browser.execute_script("document.querySelectorAll('.-nal3')[1].click();")
time.sleep(1)
oldHeight = -1
newHeight = -2
while oldHeight != newHeight:
oldHeight = newHeight
newHeight = browser.execute_script("return document.querySelectorAll('._aano')[0].scrollHeight")
browser.execute_script("document.querySelectorAll('.isgrP')[0].scrollTo(0,document.querySelectorAll('._aano')[0].scrollHeight)")
time.sleep(0.5)
soup = BeautifulSoup(browser.page_source, 'html.parser')
followers = soup.findAll('a',['FPmhX','notranslate','_0imsa'])
followers_text = []
for follower in followers:
followers_text.append(follower.get_text())
print("Number of followers: " + str(len(followers_text)))
誤動作を防ぐために2秒待ってから、もう一度フォロワーボタンをクリックしました。
そして1秒待って本格的にフォロワーユーザー名を求める部分です。
まず、すべてのフォロワーを呼び出す必要があるので、すべての人をロードするためにスクロールを繰り返し下げるロジックをwhile文で実装しました。
前のスクロールの高さと新しいスクロールの高さが異なる場合は、追加のロードが残っているという意味なので、前のスクロールの高さと新しいスクロールの高さが等しくなるまで繰り返し続ける構文です。
querySelectorAll メソッド 引数の値である class 名は、[Developer Mode Elements] タブで直接表示して取得した値です。
ロードが完了したら、htmlデータをBeautifulSoupモジュールを介して取得し、ユーザー名のタグとクラスを確認し、すべて抽出して配列に入れます。
printメソッドで配列の長さを求めてフォロワー数を画面に出力しました。
フォローイングリストのインポート
次にフォロー数を求めてみましょう。
browser.find_element_by_xpath('/html/body/div[4]/div/div/div[1]/div/div[2]/button').click()
time.sleep(0.5)
browser.execute_script("document.querySelectorAll('.-nal3')[2].click();")
time.sleep(1)
oldHeight = -1
newHeight = -2
while oldHeight != newHeight:
oldHeight = newHeight
newHeight = browser.execute_script("return document.querySelectorAll('._aano')[0].scrollHeight")
browser.execute_script("document.querySelectorAll('.isgrP')[0].scrollTo(0,document.querySelectorAll('._aano')[0].scrollHeight)")
time.sleep(0.5)
soup = BeautifulSoup(browser.page_source, 'html.parser')
followings = soup.findAll('a',['FPmhX','notranslate','_0imsa'])
followings_text = []
for following in followings:
followings_text.append(following.get_text())
print("Number of followings: " + str(len(followings_text)))
フォロワーウィンドウを閉じるには、xpathを使って閉じるボタンをクリックしました。
その後、0.5秒待ち、フォローボタンをクリックしました。
そしてまた1秒待ってフォローしているユーザー名を求めました。
フォロワーのユーザー名を求めるパターンとほとんど似ているので、この部分はもう一度説明しません。
自分だけをフォローした対象を引き出す
最後に、フォロワーユーザー名リストとフォローイングユーザー名リストを比較して、一致しない対象を見つけてみましょう。
result = []
for following in followings_text:
cnt = 0
for follower in followers_text:
if following == follower:
cnt += 1
break
if cnt == 0:
result.append(following)
print('List of people who did not F4F: '+str(result))
フォローイングユーザー名を基準に1人ずつすべてのフォロワーユーザー名リストと対照をしていると、カウントをして抜け出すロジックを繰り返し実行しました。
もしカウントが0ならば私はフォローするがフォロワーリストにはないのでF4Fしていないターゲットという意味で結果配列に追加をします。
最終的に結果の配列を出力すると、目的の目的が達成されます。
そうです。
私はフォローしましたが、あなたはしませんでしたか? ㅠ
ちなみに、私は知人だけをフォローしてもらう人が多いわけではありません。
簡単に目的を達成しました。
完全なソース共有
ご希望の方がいらっしゃって共有します。
import time
import sys
from selenium import webdriver
from bs4 import BeautifulSoup
username = sys.argv[1]
browser = webdriver.Chrome('./chromedriver')
browser.get('https://www.instagram.com/'+username)
browser.execute_script("document.querySelectorAll('.-nal3')[1].click();")
time.sleep(2)
browser.find_element_by_name('username').send_keys(sys.argv[1])
browser.find_element_by_name('password').send_keys(sys.argv[2])
browser.find_element_by_xpath('//*[@id="loginForm"]/div[1]/div[3]/button').submit()
time.sleep(5)
browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/div/div/button').click()
time.sleep(5)
if len(sys.argv) > 3:
username = sys.argv[3]
print('Account: ' + username)
browser.get('https://www.instagram.com/'+username)
time.sleep(2)
browser.execute_script("document.querySelectorAll('.-nal3')[1].click();")
time.sleep(1)
oldHeight = -1
newHeight = -2
while oldHeight != newHeight:
oldHeight = newHeight
newHeight = browser.execute_script("return document.querySelectorAll('.jSC57')[0].scrollHeight")
browser.execute_script("document.querySelectorAll('.isgrP')[0].scrollTo(0,document.querySelectorAll('.jSC57')[0].scrollHeight)")
time.sleep(0.5)
soup = BeautifulSoup(browser.page_source, 'html.parser')
followers = soup.findAll('a',['FPmhX','notranslate','_0imsa'])
followers_text = []
for follower in followers:
followers_text.append(follower.get_text())
print("Number of followers: " + str(len(followers_text)))
browser.find_element_by_xpath('/html/body/div[4]/div/div/div[1]/div/div[2]/button').click()
time.sleep(0.5)
browser.execute_script("document.querySelectorAll('.-nal3')[2].click();")
time.sleep(1)
oldHeight = -1
newHeight = -2
while oldHeight != newHeight:
oldHeight = newHeight
newHeight = browser.execute_script("return document.querySelectorAll('._aano')[0].scrollHeight")
browser.execute_script("document.querySelectorAll('.isgrP')[0].scrollTo(0,document.querySelectorAll('._aano')[0].scrollHeight)")
time.sleep(0.5)
soup = BeautifulSoup(browser.page_source, 'html.parser')
followings = soup.findAll('a',['FPmhX','notranslate','_0imsa'])
followings_text = []
for following in followings:
followings_text.append(following.get_text())
print("Number of followings: " + str(len(followings_text)))
result = []
for following in followings_text:
cnt = 0
for follower in followers_text:
if following == follower:
cnt += 1
break
if cnt == 0:
result.append(following)
print('List of people who did not F4F: '+str(result))
次回は別のテーマで探してお会いしましょう。 🙂
(注意)クラス名は随時変更される可能性があるため、プログラムが動作しない場合は、修正のためにInstagramタグ構造を直接把握する必要があります。