[python] BeautifulSoupとExcelの入出力を組み合わせてハンドル名(@123456のようなもの)からtwitterのアカウント名を集める話


pythonでTwitterのアカウント名をスクレイピングしたい!!

上記のようなことを思ったために、少しだけそういうコードを作成してみたので共有しようと思います。
(今回はハンドル名がわかっている前提)

スクレイピングにおける注意点

スクレイピングに関しては基本的に色々と規約を守らないといけないので
こちらをお読みください

相手のサーバー負荷に繋がることもあるので実行の際はくれぐれも慎重にお願いいたします。

情報取得の流れ

エクセルの一列目にハンドル名を並べる

エクセルから情報を取得する

googleで検索する

そこから情報(アカウント名)を抜き取る

エクセルの三列目にアカウント名を並べる

このような流れでやっていこうと思います。

必要なモジュールをインストールする

使っていくモジュールは4つ
1. Urlを取得するrequests
2. エクセルファイルの操作のopenpyxl
3. サイトのhtmlから抽出するbs4
4. サーバー負荷にならないようにsleep関数導入のためのtime

自分はローカル環境のDocumentsにscraypeディレクトリ作成の元行いました。

  • scraype
    • handle_name_search.py
    • handle.xlsx

早速上記pipを用いて4つをinstallしましょう。

pip3 install requests
pip3 install openpyxl
pip3 install BeautifulSoup4
pip3 install time

そして先ほど作ったファイルにimport

handle_name-search.py
import requests
import openpyxl
from bs4 import BeautfulSoup as bs
import time

ハンドル名をエクセルの一列目に並べる

上記のようにセッティングをしてhandle.xlsxとして保存しscraypeフォルダに保存しましょう。

エクセルからA1列目の情報を取得する

openpyxlモジュールを使ってローカル環境のファイルをloadし、Sheet1を操作する

handle_name_search.py
wb = openpyxl.laod_workbook('/Users/{自分のローカル}/Documents/scraype/handle.xlsx')
sheet1=wb['Sheet1']

これでSheet1の設定は完了なのでA1列目を全て取って行きましょう

handle_name_search.py
for i in range(0,sheet1.max_row):
    print(sheet1.cell(row=i+1,column=1).value

これを実行すればエクセルからA1列目の情報が全て出力されます!
あとはこれを探す!

摘出したものをgoogleで検索する

handle_name_search.py
req = requests.get("https//www.google.com/search?q=" + sheet1.cell(row = i+1, column=1).value)

BeatifulSoupを用いてアカウント名が書かれているタグを検索

handle_name_search.py
req = req.text
soup = bs(req,"html.parser")
tags = soup.find_all("div",class_="ZINbbc xpd O9g5cc uUPGi")
if(tags[0].find("div",class_="BNeawe vvjwJb AP7Wnd") != None):
    title = tags[0].find("div",class_="BNeawe vvjwJb AP7Wnd").string

ここで苦戦した内容がchromeの検証でみられるクラス名とbs4で取得するクラスが違うということで、soup.prettify()でBNeawe vvjwJb AP7Wndのクラスの中にgoogleの検索タイトルが入っているのを確認。

検索結果の中から邪魔なものを取り除く

handle_name_search.py
if "(@" in title:
    title = title.split('(@')[0]
else:
    if "- Twitter" in title:
        title = title.split('-')[0]
    if "✓" in title:
        title = title.split('✓')[0]

最後にエクセルに出力し保存

handle_name_searchpy
sheet1.cell(row=i+1,column=3).value = title
wb.save('/Users/{自分のローカル名}/Documents/scraype/handle.xlsx')

全容以下に載せます

handle_name_search.py
import requests
import openpyxl
from bs4 import BeautifulSoup as bs
import time


##ローカルにあるhandle.xlsxにアクセスする(一列目にハンドル名入力)
wb = openpyxl.load_workbook('/Users/{自分のローカル名}/Documents/scraype/handle.xlsx')
sheet1=wb['Sheet1']

##excelの一列目のハンドルを取得し、三列目に出力する
for i in range(0,sheet1.max_row):
    time.sleep(1)
    print(sheet1.cell(row=i+1,column=1).value)    
    req = requests.get("https://www.google.com/search?q=" + sheet1.cell(row=i+1,column=1).value)
    req = req.text
    soup = bs(req,"html.parser")
    tags = soup.find_all("div", class_="ZINbbc xpd O9g5cc uUPGi")
    if(tags[0].find("div",class_="BNeawe vvjwJb AP7Wnd") != None):
        title = tags[0].find("div", class_="BNeawe vvjwJb AP7Wnd").string 
        if "(@" in title:
            title = title.split('(@')[0]
        else:
            if "- Twitter" in title:
                title = title.split('-')[0]
            if "✓" in title:
                title = title.split('✓')[0]
        print(title)
        sheet1.cell(row=i+1,column=3).value= title
        wb.save('/Users/{自分のローカル名}/Documents/scraype/handle.xlsx')
wb.save('/Users/{自分のローカル名}/Documents/scraype/handle.xlsx')    

あとはコンパイルしてみて確認してみてください。
三列目にアカウント名が出力されましたでしょうか!?

サーバー攻撃にならないように途中にsleep関数を導入していますが、スクレイピングを実行する際はくれぐれも規約に沿った行動をしてください。

以上スクレイピングでした。