SNSに画像を自動投稿できるようにしたい
この記事で、できるようになること。
複数のSNSを使っていると、同じ内容を全てのSNSに投稿したいことってありますよね。
一つ一つ手でやるのは、面倒臭いので、pythonで複数のSNSに自動投稿できるようにします。
Twitterだけ自動投稿したいとか、TwitterとFacebookだけでいいという場合にも使える方法になっています。
方法としては、seleniumでブラウザを自動操作して投稿します。
seleniumを使ってブラウザを自動操作する方法は、こちらにまとめてあります。
seleniumをインストールしていないという人は上の記事から読んでもらった方がいいと思います。
今回は、seleniumを使ってSNSにログイン、投稿する部分の解説を行います。
動作環境
動作環境はこちら。
- windows 10
- python 2.7
- selenium 3.141.0
対象のSNSはこちら。
- Line(タイムライン)
※追記
Facebookは画像なしで文章だけ自動投稿するように変更したプログラムになっています。
自動投稿プログラムの全体
まずは、自動投稿プログラムの完成品を載せておきます。(ちょっと長いです。)
後半に各処理の解説を書きます。
設定ファイル(settings.ini)を作成して投稿する画像パス、テキストと各SNSのログインIDとパスワードを書いておきます。
# 以下の各SNSのIDはログインに使用するIDを入力してください。
# ログインでメールアドレスや電話番号を使用している人は、それがIDになります。
[Common]
# 投稿する画像のパスとファイル名を指定する
# (例) D:\image\image001.jpgを投稿する場合、以下のようになる
# image_path = D:\image
# image_file = image001.jpg
image_path = D:\image
image_file = image001.jpg
# 投稿する文章
text = "ここに投稿したい文章を入力"
[Twitter]
# Twitterに投稿するかどうか、0:投稿する, 1投稿しない
disable = 0
# TwitterのIDとパスワード
id = ツイッターのID
password = ツイッターのパスワード
[Facebook]
# Facebookに投稿するかどうか、0:投稿する, 1投稿しな
disable = 0
# facebookのID(ログインに電話番号を使っているなら電話番号)とパスワード
id = facebookのID
password = facebookのパスワード
# 投稿したいページのURL (例) https://www.facebook.com/test
page = 投稿したいページのURL
[Line]
# Lineはビジネスアカウントのみ対応
# Lineに投稿するかどうか、0:投稿する, 1投稿しない
disable = 0
# LineのID(メールアドレス)とパスワード
id = LineのID
password = Lineのパスワード
# Lineビジネスアカウント(@を付けて入力) (例) @test123456789
business_id = Lineビジネスアカウント
[Instagram]
# Instagramに投稿するかどうか、0:投稿する, 1投稿しない
disable = 0
# Instagramログイン用ID(メールアドレス)とパスワード
id = インスタのID
password = インスタのパスワード
そして投稿プログラム本体(auto_post_sns.py)
glob, pywinautoを使っているので、インストールしていなければ、pipで入れてください。
#! /usr/bin/env python
# -*- coding: shift_jis -*-
import time
import os
import ConfigParser
import glob
import pywinauto
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
inifile = ConfigParser.SafeConfigParser()
inifile.read('./settings.ini')
image_path = inifile.get('Common','image_path')
image_file = inifile.get('Common','image_file')
Twitter_ID = inifile.get('Twitter','id')
Twitter_PASS = inifile.get('Twitter','password')
Twitter_URL = "https://twitter.com/login?username_or_email=" + Twitter_ID
Facebook_ID = inifile.get('Facebook','id')
Facebook_PASS = inifile.get('Facebook','password')
Facebook_URL = "https://ja-jp.facebook.com/"
Line_ID = inifile.get('Line','id')
Line_PASS = inifile.get('Line','password')
Line_URL = "https://manager.line.biz/account/"+inifile.get('Line','business_id')+"/timeline/create"
Insta_ID = inifile.get('Instagram','id')
Insta_PASS = inifile.get('Instagram','password')
Insta_URL = "https://www.instagram.com/accounts/login/"
def main():
if inifile.get('Twitter','disable') == '0':
post_twitter()
if inifile.get('Facebook','disable') == '0':
post_facebook()
if inifile.get('Line','disable') == '0':
post_line()
if inifile.get('Instagram','disable') == '0':
post_insta()
# Twitterに投稿
def post_twitter():
try:
# Twitterログイン画面を開く
driver = webdriver.Chrome(executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Twitter_URL)
# ログイン
driver.find_element_by_name('session[password]').send_keys(Twitter_PASS)
driver.find_element_by_xpath('//*[@data-testid="LoginForm_Login_Button"]').click()
# 画像アップロード
image = glob.glob(image_path +'¥¥' + image_file)
driver.find_element_by_xpath('//input[@type="file"]').send_keys(image)
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Twitter ----------"
print text.decode('utf-8')
# 入力
element_text = driver.find_element_by_class_name('notranslate')
element_text.click()
element_text.send_keys(text.decode('utf-8'))
time.sleep(1)
# 投稿
tweet_button = driver.find_element_by_xpath('//*[@data-testid="tweetButtonInline"]')
tweet_button.click()
time.sleep(5)
print "---------- Twitter完了 ----------"
except Exception as e:
print "[ERROR] Twitterの投稿に失敗"
# Facebookに投稿
def post_facebook():
try:
# 通知許可するかどうかのポップアップを消すための設定
option = webdriver.ChromeOptions()
prefs = {"profile.default_content_setting_values.notifications" : 2}
option.add_experimental_option("prefs",prefs)
# Facebookログイン画面を開く
driver = webdriver.Chrome(chrome_options=option, executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Facebook_URL)
# ログイン
driver.find_element_by_id('email').send_keys(Facebook_ID)
driver.find_element_by_id('pass').send_keys(Facebook_PASS)
driver.find_element_by_xpath('//*[@data-testid="royal_login_button"]').click()
time.sleep(1)
# 投稿画面
driver.get(inifile.get('Facebook','page'))
time.sleep(1)
post_button = driver.find_element_by_xpath('//*[@aria-label="'+ u'投稿の作成' +'"]')
post_button.click()
time.sleep(1)
# 投稿
actions= ActionChains(driver) ##Action Chains
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Facebook ----------"
print text.decode('utf-8')
actions.send_keys(text.decode('utf-8'))
actions.pause(3) # 入力終わるまで待つ
actions.send_keys(Keys.TAB * 10) # TABを10回押して、投稿ボタンにフォーカス
actions.pause(1) # 入力終わるまで待つ
actions.send_keys(Keys.ENTER) #投稿ボタン押す
actions.perform() #actions実行
time.sleep(10) # 投稿終わるまで待つ
print "---------- Facebook完了 ----------"
except Exception as e:
print "[ERROR] Facebookの投稿に失敗"
# Lineに投稿
def post_line():
try:
# Lineログイン画面を開く
driver = webdriver.Chrome(executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Line_URL)
# ログイン
driver.find_element_by_class_name('btn-dark').click()
driver.find_element_by_name('email').send_keys(Line_ID)
driver.find_element_by_name('password').send_keys(Line_PASS)
time.sleep(1)
driver.find_element_by_class_name('btn-dark').click()
# 画像アップロード
driver.find_element_by_css_selector('.las.la-photo-video.fa-3x').click()
## YouTubeの最後のタグがフォルダ番号
image = glob.glob(image_path +'¥¥' + image_file)
driver.find_element_by_xpath('//input[@type="file"]').send_keys(image)
time.sleep(5) # 画像アップロードを待つ
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Line ----------"
print text.decode('utf-8')
# 入力
element_text = driver.find_element_by_css_selector('.form-control.editor')
element_text.send_keys(text.decode('utf-8'))
time.sleep(1)
# 投稿
post_button = driver.find_element_by_css_selector('.btn.btn-lg.btn-primary.px-5.mx-1')
post_button.click()
confirm_button = driver.find_element_by_css_selector('.btn.btn-lg.rounded-0.flex-1.btn-primary')
confirm_button.click()
time.sleep(5)
print "---------- Line完了 ----------"
except Exception as e:
print "[ERROR] Lineの投稿に失敗"
# Instaに投稿
def post_insta():
try:
# スマホモードにする
mobile_emulation = { "deviceName": "iPhone X" }
option = webdriver.ChromeOptions()
option.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome(chrome_options=option, executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Insta_URL)
# ログイン
driver.find_element_by_name('username').send_keys(Insta_ID)
driver.find_element_by_name('password').send_keys(Insta_PASS)
driver.find_elements_by_css_selector('.sqdOP.L3NKy.y3zKF')[1].click() # ログインボタン押す
# トップページに遷移
driver.get("https://www.instagram.com/")
driver.find_element_by_css_selector('.aOOlW.HoLwm').click() # ホーム追加キャンセル押す
post_button = driver.find_element_by_xpath('//div[@data-testid="new-post-button"]').click()
# 画像アップロード(pywinautoによるOSウィンドウ制御)
time.sleep(1)
findWindow = lambda: pywinauto.findwindows.find_windows(title=u'開く')[0]
dialog = pywinauto.timings.wait_until_passes(5, 1, findWindow)
pwa_app = pywinauto.Application()
pwa_app.connect(handle=dialog)
window = pwa_app[u'開く']
window.wait(u'ready')
edit = window.Edit4
# 画像パス入力
edit.set_focus()
image = glob.glob(image_path +'¥¥' + image_file)
edit.set_text(image[0])
# ダイアログの「開く」ボタンをクリック
button = window[u'開く(&O):']
button.click()
time.sleep(3) # アップロード完了まで待つ
driver.find_element_by_class_name('pHnkA').click() # 画像縮小ボタン押す
time.sleep(1)
driver.find_element_by_class_name('UP43G').click() # 次へボタン押す
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Insta ----------"
print text.decode('utf-8')
# 文章入力
time.sleep(3)
driver.find_element_by_tag_name('textarea').send_keys(text.decode('utf-8'))
time.sleep(3)
# 投稿
driver.find_element_by_class_name('UP43G').click() # 投稿ボタン押す
time.sleep(5) # 投稿完了まで待つ
print "---------- Insta完了 ----------"
except Exception as e:
print "[ERROR] Instaの投稿に失敗"
if __name__ == '__main__':
main()
Twitterに自動投稿
Twitterに自動投稿する箇所の処理を解説していきます。
seleniumを使ってブラウザでTwitterのログイン画面を開きます。
ページ読み込みが完了するまで最大10秒待ちます。
# Twitterログイン画面を開く
driver = webdriver.Chrome(executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Twitter_URL)
IDとパスワードを入力して、ログインボタンをクリックします。
# ログイン
driver.find_element_by_name('session[password]').send_keys(Twitter_PASS)
driver.find_element_by_xpath('//*[@data-testid="LoginForm_Login_Button"]').click()
image_pathとimage_fileから画像を読み込みアップロードします。
# 画像アップロード
image = glob.glob(image_path + '¥¥' + image_file)
driver.find_element_by_xpath('//input[@type="file"]').send_keys(image)
設定ファイルに投稿する文章を書いておき、ブラウザ上に入力します。
text = inifile.get('Common','text')
print "---------- Twitter ----------"
print text.decode('utf-8')
# 入力
element_text = driver.find_element_by_class_name('notranslate')
element_text.click()
element_text.send_keys(text.decode('utf-8'))
time.sleep(1)
投稿ボタンを押す処理です。投稿完了するまで5秒ほどsleepを入れています。
# 投稿
tweet_button = driver.find_element_by_xpath('//*[@data-testid="tweetButtonInline"]')
tweet_button.click()
time.sleep(5)
print "---------- Twitter完了 ----------"
Facebookに自動投稿
Facebookに自動投稿する処理について解説していきます。
seleniumでブラウザを起動するとシークレットブラウザと同様の挙動をするので、毎回通知を許可するかのポップアップが表示されます。
それを非表示にする設定をします。
# 通知許可するかどうかのポップアップを消すための設定
option = webdriver.ChromeOptions()
prefs = {"profile.default_content_setting_values.notifications" : 2}
option.add_experimental_option("prefs",prefs)
ログイン画面を開きます。
facebookは一つのIDで複数ページ作成することができるので投稿したいページを指定して遷移できるようにします。
# Facebookログイン画面を開く
driver = webdriver.Chrome(chrome_options=option, executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Facebook_URL)
IDとパスワードを入力してログインします。
# ログイン
driver.find_element_by_id('email').send_keys(Facebook_ID)
driver.find_element_by_id('pass').send_keys(Facebook_PASS)
driver.find_element_by_xpath('//*[@data-testid="royal_login_button"]').click()
time.sleep(1)
ログインが完了したら、投稿画面を開きます。
# 投稿画面
driver.get(inifile.get('Facebook','page'))
time.sleep(1)
post_button = driver.find_element_by_xpath('//*[@aria-label="'+ u'投稿の作成' +'"]')
post_button.click()
time.sleep(1)
投稿する内容を入力していきますが、どの要素をクリックするのかをhtmlの要素ではなく、TabキーやEnterキーの入力で選択します。
投稿ボタンにフォーカスが当たるようにTabキーを10回押して、Enterで投稿。
このキーボード操作をseleniumではActionChainsを使って実現できます。
# 投稿
actions= ActionChains(driver) ##Action Chains
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Facebook ----------"
print text.decode('utf-8')
actions.send_keys(text.decode('utf-8'))
actions.pause(3) # 入力終わるまで待つ
actions.send_keys(Keys.TAB * 10) # TABを10回押して、投稿ボタンにフォーカス
actions.pause(1) # 入力終わるまで待つ
actions.send_keys(Keys.ENTER) #投稿ボタン押す
actions.perform() #actions実行
time.sleep(10) # 投稿終わるまで待つ
print "---------- Facebook完了 ----------"
Line (タイムライン) に自動投稿
次にLineのタイムラインに自動投稿できるようにします。
今回はLineのビジネスアカウント(Line@)で投稿します。
通常のLineアカウントではこのコードでは動きませんので、ご注意ください。
まずは、他と同様にログイン画面を開きます。
# Lineログイン画面を開く
driver = webdriver.Chrome(executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Line_URL)
IDとパスワードを入力してログインボタンを押します。
# ログイン
driver.find_element_by_class_name('btn-dark').click()
driver.find_element_by_name('email').send_keys(Line_ID)
driver.find_element_by_name('password').send_keys(Line_PASS)
time.sleep(1)
driver.find_element_by_class_name('btn-dark').click()
画像をアップロードします。
# 画像アップロード
driver.find_element_by_css_selector('.las.la-photo-video.fa-3x').click()
image = glob.glob(image_path + '¥¥' + image_file)
driver.find_element_by_xpath('//input[@type="file"]').send_keys(image)
time.sleep(5) # 画像アップロードを待つ
テキストを入力します。
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Line ----------"
print text.decode('utf-8')
# 入力
element_text = driver.find_element_by_css_selector('.form-control.editor')
element_text.send_keys(text.decode('utf-8'))
time.sleep(1)
投稿ボタンを押してsleepして完了です。
# 投稿
post_button = driver.find_element_by_css_selector('.btn.btn-lg.btn-primary.px-5.mx-1')
post_button.click()
confirm_button = driver.find_element_by_css_selector('.btn.btn-lg.rounded-0.flex-1.btn-primary')
confirm_button.click()
time.sleep(5)
print "---------- Line完了 ----------"
Instagramに自動投稿
最後はインスタグラムです。
インスタグラムはPCから投稿できないため、ブラウザをスマホモードに変更して投稿します。
# スマホモードにする
mobile_emulation = { "deviceName": "iPhone X" }
option = webdriver.ChromeOptions()
option.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome(chrome_options=option, executable_path='C:¥¥Python27¥¥Lib¥¥site-packages¥¥chromedriver_binary¥¥chromedriver.exe')
driver.implicitly_wait(10) # ページ読み込み最大待ち時間
driver.get(Insta_URL)
IDとパスワードを入力してログインします。
# ログイン
driver.find_element_by_name('username').send_keys(Insta_ID)
driver.find_element_by_name('password').send_keys(Insta_PASS)
driver.find_elements_by_css_selector('.sqdOP.L3NKy.y3zKF')[1].click()
ログイン後トップページに遷移します。
トップに遷移すると、ホームに追加のポップアップが出るのでキャンセルを押します。
# トップページに遷移
driver.get("https://www.instagram.com/")
driver.find_element_by_css_selector('.aOOlW.HoLwm').click() # ホーム追加キャンセル押す
post_button = driver.find_element_by_xpath('//div[@data-testid="new-post-button"]').click()
インスタグラムはhtmlのinputタグに直接画像を指定してアップロードできないため、pywinautoを使ってOSウィンドウを制御し、画像のアップロードを自動化します。
実行してみると、自動でPCのファイル選択画面が表示され、画像が選択されるのが分かるかと思います。
# 画像アップロード(pywinautoによるOSウィンドウ制御)
time.sleep(1)
findWindow = lambda: pywinauto.findwindows.find_windows(title=u'開く')[0]
dialog = pywinauto.timings.wait_until_passes(5, 1, findWindow)
pwa_app = pywinauto.Application()
pwa_app.connect(handle=dialog)
window = pwa_app[u'開く']
window.wait(u'ready')
edit = window.Edit4
# 画像パス入力
edit.set_focus()
image = glob.glob(image_path +'¥¥' + image_file)
edit.set_text(image[0])
# ダイアログの「開く」ボタンをクリック
button = window[u'開く(&O):']
button.click()
time.sleep(3) # アップロード完了まで待つ
画像をアップロードできたら、インスタグラムの画像縮小ボタンを押して画面内に画像が収まるようにして次へ進みます。(画像が画面内に収まる必要がなければこの処理は不要です。)
driver.find_element_by_class_name('pHnkA').click() # 画像縮小ボタン押す
time.sleep(1)
driver.find_element_by_class_name('UP43G').click() # 次へボタン押す
文章を入力して、投稿ボタンを押して完了です。
# 投稿する文章取得
text = inifile.get('Common','text')
print "---------- Insta ----------"
print text.decode('utf-8')
# 文章入力
time.sleep(3)
driver.find_element_by_tag_name('textarea').send_keys(text.decode('utf-8'))
time.sleep(3)
# 投稿
driver.find_element_by_class_name('UP43G').click() # 投稿ボタン押す
time.sleep(5) # 投稿完了まで待つ
print "---------- Insta完了 ----------"
まとめ
pythonでseleniumを使ってTwitter, Facebook, Line, Instagramに画像を自動投稿する方法を書きました。
今回の方法はあくまで、技術理解が目的であり、SNSの自動操作は利用規約で禁止しているものもあります。
利用規約違反でアカウント停止になる可能性もありますので、全て自己責任でお願いします。
本記事の内容が原因で発生した損失や損害について、筆者は一切責任を負いかねます。
プログラミングを効率的に学ぶには、Udemyがオススメです。
Udemyは、世界最大の教育プラットフォームで、動画でスキルを学ぶことができます。
Webサービス・スマホアプリ・ゲーム開発に役立つプログラミングスキルはもちろん、ブログやYouTubeで稼ぐために必要な集客・ブランディングなどを学ぶことができます。
セール期間中は、95%OFFになったり、30日間の全額返金保証もついているので、お得に安心して利用できます。
コメント