QiitaからTwitterIDをスクレイピングして、Seleniumで一括フォローしてみた

# 背景
この度、無事に転職先が決定しました！
転職先がフルリモートなので、少しコミュニケーションに不安があります。
そこで入社前に転職先で社員様のTwitterアカウントをフォローしようと思い立ちました。
PythonのSeleniumを利用して自動フォローする仕組みを考えましたので、まとめます。

:::note alert
API以外の方法でTwitterのウェブサイトを操作は規約違反です。
最悪アカウント凍結される可能性があるます
自動フォローは有料のTwitterAPIを使用しましょう。
https://help.twitter.com/ja/rules-and-policies/twitter-automation
:::

やり方を考えただけで、私はやっていないです・・・:smiley:

# 一括フォローの概要

1. Qiitaから特定のTwitterカウントをスクレイピングしてファイル出力
2. アカウントリストをもとに、PythonのSeleniumを使って、ブラウザ自動化でフォロー


# 一括フォローの詳細
## 1.TwitterアカウントIDをスクレイピング
QiitaにはOrganizationという機能があります。
これを利用すると、組織をタグづけて投稿することで、一括で記事や投稿者を確認できます
私の転職先がOrganizationを登録していたため、ここからアカウントを取得することにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3514527/326b1caa-22c6-73b8-f65b-a6625f4dff9c.png)

### ロジック

1. `https://qiita.com/organizations/組織名/members?page=n`にアクセス、
メンバー一覧を取得する。
2. ユーザページのリンクをスクレイピングして配列に格納する。
3. `https://qiita.com/ユーザID` にアクセスし、Twitterアカウントを取得する。
4. Twitterアカウントが登録されていれば取得する。
5. 3~4を繰り返し、アカウントリストをtxtファイルで出力する。

### ソース
- 使用したプログラミング言語はPythonで、以下が実際のソースコードです。
  私は業務で全く使ったことがないですが、スクレイピングといえばのイメージがあったので。
```python:getTwitterIDs
import requests
import re
from urllib import request
from bs4 import BeautifulSoup as bs4

# QiitaユーザIDを取得する
userIds = []
for num in range(1,11):
    response = requests.get('https://qiita.com/organizations/組織名/members?page='+ str(num))
    soup = bs4(response.text,'html.parser')
    for userid in soup.find_all(class_='style-uwhyem'):
        userIds.append(userid['href'])

# Qiita各ページに遷移して、Twitterアカウントを取得する
twitterIds = []
for num in range(0,len(userIds)):
    response = requests.get('https://qiita.com'+ str(userIds[num]))
    soup = bs4(response.text,'html.parser')
    twitterid = soup.find('a', attrs={"aria-label": "Twitter"})
    if twitterid:
        twitterIds.append(twitterid.get('href'))

# 取得した配列をテキストファイルに出力
with open("TwitterIds.txt", "w") as file:
    # 配列の要素を1行ずつファイルに書き込む
    for twitterid in twitterIds:
        file.write(twitterid + "\n")  # 改行文字 "\n" を追加して各要素を別々の行に書き込む

```

## 2.PythonのSeleniumでフォロー自動化
TwitterAPIを使用せずに、PythonのSeleniumで自動フォローを行う方法を説明します。
前述しましたが、Twitterの規約に反するので、使用は自己責任でお願いします。

以下ベーシックプランの料金表を参考程度に。高い:astonished:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3514527/a6d7ab36-e56b-3e1d-6e10-3348130dbbf9.png)

### ロジック
Seleniumでブラウザを自動操作
1. Twitterアカウントにログインする。
2. 先ほど取得したアカウントリストからユーザページにアクセスする。
3. フォローボタンを押下する。
4. 2~3を繰り返す。

### ソース
以下が実際のソースコードです。
- 要素の取得はXpath使って無理やり。
- 画面描写に時間がかかり要素が取得できないので、各処理事に2秒のインターバルを設定。

```python:getTwitterIDs
import requests
import re
from urllib import request
from bs4 import BeautifulSoup as bs4

# QiitaユーザIDを取得する
userIds = []
for num in range(1,11):
    response = requests.get('https://qiita.com/organizations/組織名/members?page='+ str(num))
    soup = bs4(response.text,'html.parser')
    for userid in soup.find_all(class_='style-uwhyem'):
        userIds.append(userid['href'])

# Qiita各ページに遷移して、Twitterアカウントを取得する
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException

import chromedriver_binary


TWITTER_BASE = "https://twitter.com/"
LOGIN_ID = "ログインID"
LOGIN_USER_NAME = "ユーザ名称"
PASSWORD = "パスワード"
ACCOUNTLISTFILE = "アカウントリストのファイル場所"

if __name__ == "__main__":
    # Driver
    driver = get_driver()
    # ログイン
    login_flg = do_login(driver)
    # フォロー
    login_flg = do_follow(driver)

    driver.quit()
    
def get_driver():
    #　ヘッドレスモードでブラウザを起動
    options = Options()
    driver = webdriver.Chrome()
    return driver

# twitterログイン
def do_login(driver):
    # ログインURL
    login_url = TWITTER_BASE + "login"
    driver.get(login_url)
    time.sleep(2)

    # アカウントIDを入力
    element_account = driver.find_element(By.NAME,"text")
    element_account.send_keys(LOGIN_ID)
    time.sleep(2)

    # 次へボタンクリック
    element_login = driver.find_element(by=By.XPATH,value= '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div/div[6]/div')
    element_login.click()
    time.sleep(2)

    # パスワード入力
    print(driver.current_url)
    element_pass = driver.find_element(By.NAME,"password")
    element_pass.send_keys(PASSWORD)
    time.sleep(2)

    # ログインボタンクリック
    element_login = driver.find_element(by=By.XPATH, value='//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[2]/div/div[1]/div/div/div/div')
    element_login.click()
    time.sleep(2)

def do_follow(driver):
    # ファイルを開いて行ごとに読み込み、配列に格納
    lines = []
    with open(ACCOUNTLISTFILE, 'r', encoding='utf-8') as file:
        for line in file:
            lines.append(line.strip())  # 行末の改行文字を取り除いて格納

    # フォローボタンを自動押下
    for line in lines:
        driver.get(str(line))
        time.sleep(2)
        # フォローボタンクリック
        element_follow = driver.find_elements(By.CSS_SELECTOR, '.css-901oao.r-1awozwy.r-jwli3a.r-6koalj.r-18u37iz.r-16y2uox.r-37j5jr.r-a023e6.r-b88u0q.r-1777fci.r-rjixqe.r-bcqeeo.r-q4m81j.r-qvutc0 > .css-901oao.css-16my406.css-1hf3ou5.r-poiln3.r-a023e6.r-rjixqe.r-bcqeeo.r-qvutc0 > .css-901oao.css-16my406.r-poiln3.r-bcqeeo.r-qvutc0')
        element_follow[0].click()
```

# 最後に
多くの方が、TwitterAPIは有料でありコストが高いため、自動フォローを行うことを検討しているかと思います。しかし、何度も言いますが、これは規約違反ですので、自己責任で行ってください。この記事のタイトルには「やってみた」というキャッチーなフレーズが含まれていますが、実際には私は自動フォローを行っていません。:cry::cry:

# 参考
Seleniumの理解に。

https://qiita.com/Chanmoro/items/9a3c86bb465c1cce738a

find_element_by_idの書き方は非推奨で、ind_element(By.ID,”id”)が推奨されている。

https://mwkexcelfriend.com/python-selenium/

すでに自動ログインが実装されている方のコードを参考。
ただし、HTMLの構造が変更されているため、要素を取得する際に都度修正が必要。

https://zenn.dev/ingress/articles/520ff00c8f6399