見出し画像

エロタレブログをPythonでする体験をしてみないか②

下の記事の続きです。無料で読めてしまいます。

まずはこちらをご覧ください。
↓↓↓

https://twitter.com/kikamasu/status/1786507694649872886

今回の記事を読んでいただければ、上の動画のような記事投稿がみなさんもできるようになります。
クリック一つで記事が勝手に自分のサイトに投稿されます。


  • エロタレストを自動化してもっと楽したい!

  • 自動化がどんなものか試してみたい!

  • Pythonを使ってプログラマーっぽいことにチャレンジしてみたい!

  • プログラミングなんてやったことなくても自動化ってできるの…?

こんなこと思っていませんか?

  • 毎日記事を書くのに疲れた…

  • せっかく記事を書いたのにエロタレに掲載されない…

  • プログラミングについて調べてみたけど自分のサイトに調整するやり方がわからない…

この記事では上のような悩みが解決します。


毎日記事を書くのに疲れた…
自動化すればクリック一つ!

せっかく記事を書いたのにエロタレに掲載されない…
エロタレストが提供している「エロタレブログ」を利用すれば掲載されないことはほぼない!

プログラミングについて調べてみたけど自分のサイトに調整するやり方がわからない…
コードの詳しい説明があるので、メールアドレスとパスワードを入れ替えるだけ。もっと応用することも可能!


私もエロタレストでエログ運営している時には、ワードプレスを立ち上げて毎日毎日記事を投稿していました。

仕事もあるので、朝4時に起きて記事を作成しても、エロタレストの収集タイミングに合わなかったり、重複チェックに引っかかったりと無駄にした記事は数え切れません。

そんなとき、「Python 自動化」について調べ、学習していくうちにブログを自動化する方法を少しずつ身に付けることができました。

さらに、エロタレストが公式に提供している「エロタレブログ」の存在を知りました。この「エロタレブログ」は固定費がかからないのにいつでも動画投稿ができ必ずエロタレに反映されます。

この「エロタレブログ」と「Python 自動化」を組み合わせることで、クリック一つで自分のエロタレブログに記事を反映させることができるようになりました。


この記事では、大手エロタレストが提供している「エロタレブログ」でエログ運営をしている方向けに自動化をするためのPythonコードの例を紹介します。

参考にしたのは、下のように「エロタレスト 自動化」でGoogle検索したときの一番上のサイトにあるものです。

値段が数万円。高い!
このサイトが提供しているプラグインにあるようなたくさんの機能はいらないと考え、最低限の機能だけですが、コード全体を公開し自分専用にカスタマイズできるようになっています。

なぜなら、ツールとして販売してしまうと、状況が変わりツールが使えなくなった時に対応できないからです。

申し遅れました。私はkika_masuといいます。
エログ運営のツールを販売したり、アダアフィで報酬を得たりしています。

自動化に成功してから、毎日朝ごはん食べる前にコードをポチッと実行、朝ごはん食べてる間に記事が投稿されています。
(実行される速さはネット環境によります。)

※今回の記事の値段について

先ほどのサイトではプラグインが、安いもので数万円で販売されていました。
今回の記事にあるコードを利用すれば、似た結果が得られると自負しております。
しかし、せっかく「エロタレストブログ」を利用して固定費を0にしたのに、ツールに数万円を払うのは正直きついですよね。
そう思って私も自分で作成したのですから。
同じような思いを抱えている人のために、
先ほどのプラグインの値段より半額以下で提供します

無料公開してしまいます。ただし、実行にあたってのトラブルや責任は一切負いませんので自己責任で行ってください。


この記事をおすすめする人

  • プログラミング初心者でも自動化に挑戦してみたい人

  • エロタレストの記事作成に疲弊している人

  • 高確率でエロタレストに記事を反映させたい人

  • Google検索ができる人

この記事をおすすめしない人

  • パソコンを持っていない人

  • 思考停止で自動化できると思っている人

  • 自分のしたことに責任が持てる人

コードを完成させるために、Youtubeで勉強し、スクールに通う時間はなかったので、Udemyでお金を払って講座を購入して勉強してきました。
それでもエラーに散々苦しめられ、3時間格闘してようやく一つのエラーを解消したこともあります。
お金と時間をかけて完成させましたが、それもこれも「アダアフィには夢がある」と信じてきたからです。
精神論ではなく、「アダアフィ」が一番0→1を突破するのに簡単です。
実際、アダルトではない雑記ブログを3年やってきましたが、収益は毎月数百円。しかし、アダアフィは初めてすぐに収益が上がり雑記ブログの3年間をあっという間に追い越しました。

「アダアフィには夢がある」これは間違いないです。
ぜひ一緒に自動化して楽で稼げる体験をしてください!


今回は、エロタレブログでのブログ投稿を自動化するためのコードをわかりやすく解説し、実行するための手順を説明します。
パソコンはWindowsでもMacでもどちらでも大丈夫ですが、ブラウザはGoogle Chromeがおすすめです。

1.これだけでOK!自動化に必須な準備

まずは今回の自動化をするにあたり、以下の3つを準備します。

  • エロタレブログ

  • Python

  • テキストエディタ

1.1.エロタレブログ

エロタレブログを持っていない人は以下のリンクからブログを開設(無料)してください。開設に10分もかかりません。

サイト名、ドメイン、メールアドレス、パスワードの4つを入力して「確認」をクリックします。

エロタレストが公開している「掲載の条件」を読みブログを登録させてください。

1.2. Pythonのインストール

ここでは、初めての方もいると思うので、Pythonのダウンロードも含めてすべてコマンドプロンプトやターミナルから行います。

コマンドプロンプト?ターミナル?
という人にも丁寧に解説していきますので安心してついてきてください。

1.2.1. Windowsの場合

  1. コマンドプロンプトを開きます。

    • キーボードの「Windowsキー」を押しながら「Rキー」を押します。

    • 「ファイル名を指定して実行」ウィンドウが表示されるので、「cmd」と入力して「OK」をクリックします。

  2. 以下のコマンドを入力してPythonのインストーラーをダウンロードします。

curl -o python-installer.exe https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe

3.次に、以下のコマンドを入力してインストーラーを実行します。

start python-installer.exe

4.インストーラーが起動したら、「Add Python to PATH」にチェックを入れてから、「Install Now」をクリックします。

1.2.2. Macの場合

  1. ターミナルを開きます。

    • 「Commandキー」を押しながら「Spaceキー」を押します。

    • 検索バーが表示されるので、「Terminal」と入力して「Enterキー」を押します。

  2. 以下のコマンドを入力してHomebrewをインストールします(Homebrewが既にインストールされている場合はこの手順をスキップしてください)。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

3.次に、以下のコマンドを入力してPythonをインストールします。

brew install python

2. 必要なライブラリのインストール

次に、必要なライブラリをインストールします。

ライブラリとは、たくさんの便利なプログラムや機能が集まったもののことです。
たとえば、ゲームを作るときに「キャラクターを動かす」や「音を鳴らす」などのプログラムが必要ですよね。
ライブラリを使うと、これらのプログラムを一から自分で作らなくても、すでに作られているものを使うことができます。

簡単に言うと、家の修理をするときの「道具箱」です。
道具箱にはハンマーやドライバーなどの工具が入っています。道具箱を持っていれば、必要な工具を一から作る必要はありません。
同じように、ライブラリを使えば、自分でゼロからプログラムを作る手間が省けます。

今回使用するライブラリは、以下になります。

  • requests

  • beautifulsoup4

  • pandas

  • selenium

  • webdriver-manager

それぞれのライブラリについて、簡単に説明します。

1. requests

requestsは、インターネット上のウェブサイトから情報を簡単に取り出すためのライブラリです。例えば、天気予報のデータやニュースの記事を取得することができます。

2. beautifulsoup4

beautifulsoup4は、ウェブサイトから取ってきた情報をわかりやすく整理するためのライブラリです。requestsと一緒に使って、欲しいデータだけを見つけ出すのに便利です。

3. pandas

pandasは、大量のデータを整理したり、分析したりするためのライブラリです。例えば、表(スプレッドシート)のデータを読み込んで、いろいろな計算や操作ができます。

4. selenium

seleniumは、ウェブブラウザを自動で操作するためのライブラリです。人間がブラウザを使ってクリックしたり入力したりする作業を、プログラムで自動化できます。

5. webdriver-autoinstaller

webdriver-autoinstallerは、seleniumが使うためのブラウザのドライバを自動でインストールしてくれるライブラリです。これを使うと、seleniumの設定が簡単になります。

これらをインストールするためには、以下のコマンドをコピーして、コマンドプロンプトまたはターミナルに貼り付け、「Enterキー」を押して実行します。
「pip install」というのは、指定したパッケージをインストールすることができます。

pip install requests beautifulsoup4 pandas selenium webdriver-autoinstaller

3. コードの解説

まずは、今回紹介するコードの全体を示します。
例なので皆さんが独自でカスタマイズしてください。
全体を見てみると完成系がイメージできると思います。

import requests
from bs4 import BeautifulSoup
import os
import re
import datetime
from datetime import timedelta
import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
from selenium.webdriver.common.action_chains import ActionChains
import urllib.parse
import chromedriver_autoinstaller

# Chromedriverをインストールまたは確認
chromedriver_autoinstaller.install()

session = requests.Session()

def clean_filename(text):
    return re.sub(r'[\/:*?"<>|]', '', text)

def fetch_content_by_tag(tag, page=1):
    base_url = "https://対象URL/" # スクレイピングしたいサイトURL
    encoded_tag = urllib.parse.quote(tag)
    url = f"{base_url}search.php?keyword={encoded_tag}&page={page}"
    response = session.get(url)
    content = response.text
    return extract_content(content, base_url)

def extract_content(html, base_url):
    soup = BeautifulSoup(html, 'html.parser')
    entries = soup.find_all('article')
    results = []

  # 変換ルールを辞書として定義
    conversion_rules = {
        "〇〇": "△△",
        "□□": "××"
    }
    for entry in entries:
        thumb_div = entry.find('div', class_='thumb')
        article_div = entry.find('div', class_='article_content')

        # タイトルの抽出
        title_tag = article_div.find('h3').find('a')
        title = title_tag.get_text(strip=True) if title_tag else "No title found"
        page_url = title_tag['href'] if title_tag else None

     # タイトルを変換ルールに基づいて変換
        transformed_title = title
        for key, value in conversion_rules.items():
            transformed_title = transformed_title.replace(key, value)

        # 動画時間の抽出とチェック
        duration_tag = thumb_div.find('span', class_='duration')
        duration = duration_tag.get_text(strip=True) if duration_tag else None
        print(f"Duration: {duration}")  

        # タグの抽出
        tags = [tag.get_text(strip=True) for tag in article_div.find('ul').find_all('a')]

        # サムネイルURLの抽出
        thumbnail_tag = thumb_div.find('img')
        thumbnail_url = 'https:' + thumbnail_tag['src'] if thumbnail_tag else None
        
        # フルビデオURLの取得
        video_url = fetch_video_url_with_selenium(base_url + page_url) if page_url else None

        if duration:
            try:
                hours, minutes = map(int, duration.split(':'))
                total_minutes = hours * 60 + minutes
            except ValueError:
                print(f"Skipping invalid duration format: {duration}")
                continue

            results.append({
                'title': transformed_title,
                'tags': tags,
                'thumbnail_url': thumbnail_url,
                'page_url': base_url + page_url if page_url else None,
                'video_url': video_url
            })
            print(f"Added: {transformed_title}")  # 追加された動画のタイトルを出力
        else:
            print(f"Skipped: {title}")  # スキップされた動画のタイトルを出力

    return results

def fetch_video_url_with_selenium(full_page_url):
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    
    try:
        driver = webdriver.Chrome(options=options)
        driver.get(full_page_url)
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))

        iframe = driver.find_element(By.TAG_NAME, 'iframe')
        video_url = iframe.get_attribute('src')
        print("Found video URL:", video_url)
    except Exception as e:
        print("Error in fetch_video_url_with_selenium:", str(e))
        video_url = None
    finally:
        if 'driver' in locals():
            driver.quit()
    
    return video_url

def save_images_to_drive(data, download_folder):
    if not os.path.exists(download_folder):
        os.makedirs(download_folder)
    for entry in data:
        image_url = entry['thumbnail_url']
        image_name = clean_filename(entry['title']) + '.jpg'
        if os.path.exists(os.path.join(download_folder, image_name)):
            print(f"{image_name} already exists.")
            continue
        try:
            image_response = session.get(image_url, stream=True)
            if image_response.status_code == 200:
                with open(os.path.join(download_folder, image_name), 'wb') as f:
                    for chunk in image_response.iter_content(1024):
                        f.write(chunk)
                print(f"Downloaded {image_name}")
            else:
                print(f"Failed to download {image_name} with status code {image_response.status_code}")
        except Exception as e:
            print(f"Error downloading {image_name}: {e}")

def click_erotere_button(driver, title):
    # 記事リストページに移動
    driver.get('https://自分のエロタレブログのURL/kanri/page/index/')
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'itemHead')))

    # ページ上の全記事を取得
    articles = driver.find_elements(By.CLASS_NAME, 'item')
    for article in articles:
        # 各記事内でタイトルスパンを探す
        article_title = article.find_element(By.CLASS_NAME, 'itemHead').text
        if title in article_title:
            # 「エロタレ反映」ボタンを見つけてクリック
            reflect_button = article.find_element(By.CSS_SELECTOR, 'a.btn-info.showDetail')
            reflect_button.click()
            print(f"反映ボタンをクリックしました: {title}")
            break
    else:
        print("記事が見つかりませんでした。")

def main():
    tag = input("Enter the tag you want to scrape: ")
    page = int(input("Enter the page number to start scraping from: "))
    data = fetch_content_by_tag(tag, page)
    download_folder = './downloaded_images'
    save_images_to_drive(data, download_folder)
    df = pd.DataFrame(data)
    print(df)

    options = webdriver.ChromeOptions()
    #options.add_argument('--headless')  # ヘッドレスモードを使用
    driver = webdriver.Chrome(options=options)
    driver.get('https:/自分のエロタレブログのURL/login')
    WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.ID, 'mail')))
    WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.ID, 'pass')))
    driver.find_element(By.ID, 'mail').send_keys('メールアドレスをここに入力')
    driver.find_element(By.ID, 'pass').send_keys('パスワードをここに入力')
    driver.find_element(By.CSS_SELECTOR, 'input[type="submit"]').click()
    WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.ID, 'globalnav')))
    articles_link = driver.find_element(By.LINK_TEXT, "記事")
    articles_link.click()
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))).click()
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'pagetitle')))
    start_time = datetime.datetime.now().replace(hour=17, minute=0, second=0, microsecond=0)

    for entry in data:

        driver.find_element(By.ID, 'pagetitle').send_keys(entry['title'])
        driver.find_element(By.ID, 'tags').send_keys(' '.join(entry['tags']))
        driver.find_element(By.ID, 'movieurl').send_keys(entry['video_url'])
        driver.find_element(By.NAME, 'img_link').send_keys(entry['video_url'])

        driver.find_element(By.ID, 'titleCheckBtn').click()
        time.sleep(3)

        try:
            alert = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '.alert.alert-danger'))
            )
            print("Alert found:", alert.text)

            # Clear fields only if there is an alert
            driver.find_element(By.ID, 'pagetitle').clear()
            driver.find_element(By.ID, 'tags').clear()
            driver.find_element(By.ID, 'movieurl').clear()
            driver.find_element(By.NAME, 'img_link').clear()

        except TimeoutException:
            print("No alerts, proceeding with image upload.")
            # 投稿時間を設定
            post_date = driver.find_element(By.ID, 'post_date')
            post_date.clear()
            post_date.send_keys(start_time.strftime('%Y-%m-%d'))
            
            post_hour = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'post_date_hour')))
            post_minute = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'post_date_minute')))
            
            post_hour.send_keys(start_time.strftime('%H'))
            post_minute.send_keys(start_time.strftime('%M'))

            start_time += timedelta(minutes=30)  # 次の投稿時間を30分後に設定

            driver.find_element(By.ID, 'titleCheckBtn').click()
            time.sleep(3)  # サーバー応答待ち

            # Proceed with image upload
            image_path = os.path.abspath(os.path.join(download_folder, clean_filename(entry['title']) + '.jpg'))
            driver.find_element(By.ID, 'page_image').send_keys(image_path)

            # Before clicking the submit button, change the form's action URL
            driver.execute_script("document.getElementById('pageEditForm').setAttribute('action', 'https://eromaji.blogterest.net/kanri/page/edit/0/')")
            send_button = driver.find_element(By.NAME, "send")
            driver.execute_script("arguments[0].click();", send_button)

            print("Article posted.")
            # Wait 3 seconds before clicking the 'Erotare Reflect' button
            time.sleep(3)

            # 'エロタレスト反映'ボタンをクリックした後のコード
            click_erotere_button(driver, entry['title'])
            print("Clicked 'Erotare Reflect' button: ", entry['title'])

           # 'エロタレスト反映'ボタンをクリック後、ポップアップが表示されるのを待つ
            try:
                # ポップアップが表示されるのを待つ
                WebDriverWait(driver, 10).until(
                    EC.visibility_of_element_located((By.ID, 'detail'))
                )
                print("ポップアップが表示されました。")

                # ポップアップ以外の場所をクリックして閉じる
                body_element = driver.find_element(By.TAG_NAME, 'body')
                ActionChains(driver).move_to_element_with_offset(body_element, 10, 10).click().perform()
                print("ポップアップを閉じました。")

                # ポップアップが閉じたことを確認
                WebDriverWait(driver, 10).until(
                    EC.invisibility_of_element_located((By.ID, 'detail'))
                )
                print("ポップアップが正常に閉じました。")

                # 「新規作成」リンクがクリック可能になるのを待つ
                WebDriverWait(driver, 10).until(
                    EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))
                ).click()
                print("新規作成ページにアクセスしました。")

            except TimeoutException as e:
                print(f"処理中にタイムアウトが発生しました: {str(e)}")

            # Navigate back to the new article creation page to reset the form
            articles_link = driver.find_element(By.LINK_TEXT, "記事")
            articles_link.click()
            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))).click()

            # Wait until the 'pagetitle' element is visible and ready for new input
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'pagetitle')))

    input("Press Enter to close the browser...")
    driver.quit()

if __name__ == "__main__":
    main()


次に、今回のコードが何をしているのかを説明します。
説明を理解すれば応用することができます。

3.0.そんなことはいいから早く試したい人向け

以下にコードの詳細を解説しましたが、早く試したい方向けに最低限ここだけ変えればできるよ、というのを記します。

上の完成例コードをコピーして、テキストエディタ(メモ帳やVSCodeなど)に貼り付けます。

メモ帳で保存するには以下の順です。Macの場合は、【テキストエディット】です。
※そのままだと実行できないので、「フォーマット」→「標準テキストにする」にクリックしてください。

以下のコードを探し、それぞれ修正する。

base_url = "https://対象URL/" # スクレイピングしたいサイトURL

driver.get('https://自分のエロタレプログのURL/kanri/page/index/')

driver.get('https:/自分のエロタレブログのURL/login')
driver.find_element(By.ID, 'mail').send_keys('メールアドレスをここに入力')
driver.find_element(By.ID, 'pass').send_keys('パスワードをここに入力')

今回例としてスクレイピングするサイトは、
以下の検索画面の一番上のサイト→「基本プラグイン」で紹介されてるサイトの2番目(○○○ラ)です。URLを入力します。自分で調べてください。

「自分のエロタレブログURL」「メールアドレス」「パスワード」は自分のものを貼り付けてください。 そして、ファイル名を「auto_post.py」として保存します。

コマンドプロンプトまたはターミナルでディレクトリを移動する

次に、コマンドプロンプトまたはターミナルを開き、先ほど保存した「auto_post.py」のあるフォルダに移動します。例えば、ファイルがデスクトップにある場合は、以下のコマンドを実行します。

Windowsの場合

cd Desktop

Macの場合

cd ~/Desktop

4.3. コードを実行する

最後に、以下のコマンドを実行してコードを実行します。

python auto_post.py

これで、プログラムが実行されるはずです。
検索したいキーワードとページ番号を入力するプロンプトが表示されます。入力が完了すると、指定したタグに基づいてデータを取得し、記事が自動的に投稿されるはずです。


3.1. 必要なライブラリのインポート

これらのライブラリは、ウェブページからデータを取得したり、ブラウザを自動操作したりするために必要です。
先ほど、ライブラリのインストールは行いましたが、コードの中に入れないと使うことができません。
道具は買っても使わないと意味がありませんよね。先にこのライブラリを使うよって宣言します。

import requests
from bs4 import BeautifulSoup
import os
import re
import datetime
from datetime import timedelta
import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
from selenium.webdriver.common.action_chains import ActionChains
import urllib.parse
import chromedriver_autoinstaller

3.2. セッションの作成

ウェブサイトにアクセスするためのセッションを作成します。

chromedriver_autoinstaller.install()
session = requests.Session()
  • ChromeDriverは、ウェブブラウザのChromeを自動操作するためのプログラムです。

  • chromedriver_autoinstaller.install() は、このプログラムをインストールしたり、すでにインストールされているかを確認するための命令です。

  • requests.Session() は、ウェブサイトにアクセスするときに使う特別な方法を作ります。

  • このセッションを使うと、同じウェブサイトに何度もアクセスするときに便利で、効率的にデータをやり取りできます。

3.3. ファイル名を安全にする関数

ファイル名に使えない文字を取り除く関数です。

def clean_filename(text):
    return re.sub(r'[\/:*?"<>|]', '', text)

3.4. タグで検索して内容を取得する関数

ここから本題です。
スクレイピング(動画を検索したいサイト)先のURLを入力し、指定したタグ(キーワード)でウェブサイトを検索し、その結果のHTMLを取得します。

def fetch_content_by_tag(tag, page=1):
    base_url = "https://対象URL/" # スクレイピングしたいサイトURL
    encoded_tag = urllib.parse.quote(tag)
    url = f"{base_url}search.php?keyword={encoded_tag}&page={page}"
    response = session.get(url)
    content = response.text
    return extract_content(content, base_url)

【カスタマイズできるとこ】
・「base_url」にスクレイピングしたいサイトのURLを入れます。

3.5. HTMLから必要な情報を抽出する関数

取得したHTMLから記事のタイトル、タグ、サムネイル画像のURL、動画のURLなどを抽出します。

def extract_content(html, base_url):
    soup = BeautifulSoup(html, 'html.parser')
    entries = soup.find_all('article')
    results = []
    # 変換ルールを辞書として定義
    conversion_rules = {
        "〇〇": "△△",
        "□□": "××"
    }

    for entry in entries:
        thumb_div = entry.find('div', class_='thumb')
        article_div = entry.find('div', class_='article_content')

        # タイトルの抽出
        title_tag = article_div.find('h3').find('a')
        title = title_tag.get_text(strip=True) if title_tag else "No title found"
        page_url = title_tag['href'] if title_tag else None

        # タイトルを変換ルールに基づいて変換
        transformed_title = title
        for key, value in conversion_rules.items():
            transformed_title = transformed_title.replace(key, value)

        # 動画時間の抽出とチェック
        duration_tag = thumb_div.find('span', class_='duration')
        duration = duration_tag.get_text(strip=True) if duration_tag else None
        print(f"Duration: {duration}")  

        # タグの抽出
        tags = [tag.get_text(strip=True) for tag in article_div.find('ul').find_all('a')]

        # サムネイルURLの抽出
        thumbnail_tag = thumb_div.find('img')
        thumbnail_url = 'https:' + thumbnail_tag['src'] if thumbnail_tag else None
        
        # フルビデオURLの取得
        video_url = fetch_video_url_with_selenium(base_url + page_url) if page_url else None

        if duration:
            try:
                hours, minutes = map(int, duration.split(':'))
                total_minutes = hours * 60 + minutes
            except ValueError:
                print(f"Skipping invalid duration format: {duration}")
                continue

            results.append({
                'title': transformed_titl,
                'tags': tags,
                'thumbnail_url': thumbnail_url,
                'page_url': base_url + page_url if page_url else None,
                'video_url': video_url
            })
            print(f"Added: {transformed_titl}")  # 追加された動画のタイトルを出力
        else:
            print(f"Skipped: {title}")  # スキップされた動画のタイトルを出力

    return results

【カスタマイズできること】

entries = soup.find_all('article')

・'article' の部分を、そのサイトの個々の記事を囲むタグやクラス名に変更します。

thumb_div = entry.find('div', class_='thumb')
article_div = entry.find('div', class_='article_content')

・'div', class_='thumb' や 'div', class_='article_content' の部分を、そのサイトでサムネイルや記事内容を囲む要素に変更します。

title_tag = article_div.find('h3').find('a')

・'h3' や 'a' の部分を、そのサイトでタイトルが含まれるタグに変更します。

duration_tag = thumb_div.find('span', class_='duration')

・'span', class_='duration' の部分を、そのサイトで動画時間が表示されるタグやクラス名に変更します。

tags = [tag.get_text(strip=True) for tag in article_div.find('ul').find_all('a')]

・'ul' や 'a' の部分を、そのサイトでタグがリストされる要素に変更します。

thumbnail_tag = thumb_div.find('img')

・'img' の部分を、そのサイトでサムネイル画像が含まれるタグに変更します。

conversion_rules = {
        "〇〇": "△△",
        "□□": "××"
    }

タイトルに「〇〇」という単語が含まれている場合、それを「△△」に変換します。同様に、「□□」を「××」に変換します。他の変換ルールも同様に追加できます。これにより、タイトルをオリジナルのものにすることができます。

Google Chromeのデベロッパーツールを使って「要素」を調べる方法

上の説明で「div」や「article」を変更して、と言われても何に変更すればいいかわかりませんよね。以下に簡単に説明します。

ステップ 1: Google Chromeを開く

まず、Google Chromeを開きます。普段インターネットを見るときに使っているブラウザです。

ステップ 2: 調べたいウェブページを開く

次に、調べたいウェブページを開きます。

ステップ 3: デベロッパーツールを開く

デベロッパーツールを開くには、次の方法があります。

  1. 右クリックする方法

    • 調べたい部分(例えば、写真や文字)の上で右クリックします。

    • 出てきたメニューの中から「検証」を選びます。

  2. キーボードを使う方法

    • キーボードの「F12」キーを押します。

    • または、「Ctrl + Shift + I」(Macの場合は「Command + Option + I」)を押します。

ステップ 4: デベロッパーツールの「要素(Elements)」タブを見る

デベロッパーツールが開いたら、画面の右側や下側に新しいウィンドウが表示されます。その中の一番左側にある「要素(Elements)」タブをクリックします。

ステップ 5: 調べたい要素を見つける

「要素(Elements)」タブの一番左にあるマウスをクリックし、ウェブページの調べたい箇所をクリックすると、対応したコードが表示されます。ここで調べたい要素を調べることができます。

以下のサイトがわかりやすかったので参考にしてください。

https://willcloud.jp/knowhow/dev-tools-01/

実はこれはHTMLという言語の要素

今回の例にあるサイトで確認してみましょう。

entries = soup.find_all('article')

・'article' の部分を、そのサイトの個々の記事を囲むタグやクラス名に変更します。

thumb_div = entry.find('div', class_='thumb')
article_div = entry.find('div', class_='article_content')

・'div', class_='thumb' や 'div', class_='article_content' の部分を、そのサイトでサムネイルや記事内容を囲む要素に変更します。

title_tag = article_div.find('h3').find('a')

・'h3' や 'a' の部分を、そのサイトでタイトルが含まれるタグに変更します。

duration_tag = thumb_div.find('span', class_='duration')

・'span', class_='duration' の部分を、そのサイトで動画時間が表示されるタグやクラス名に変更します。

tags = [tag.get_text(strip=True) for tag in article_div.find('ul').find_all('a')]

・'ul' や 'a' の部分を、そのサイトでタグがリストされる要素に変更します。

thumbnail_tag = thumb_div.find('img')

・'img' の部分を、そのサイトでサムネイル画像が含まれるタグに変更します。

Google Chromeのデベロッパーツールを使ってコードを確認する方法がわかりましたか?これからも【カスタマイズできること】セクションで出てきますので、都度、スクレイピングしたいサイトで確認してください。

3.6. Seleniumを使って動画URLを取得する関数

Seleniumを使ってブラウザを自動操作し、動画のURLを取得します。

def fetch_video_url_with_selenium(full_page_url):
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    
    try:
        driver = webdriver.Chrome(options=options)
        driver.get(full_page_url)
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))

        iframe = driver.find_element(By.TAG_NAME, 'iframe')
        video_url = iframe.get_attribute('src')
        print("Found video URL:", video_url)
    except Exception as e:
        print("Error in fetch_video_url_with_selenium:", str(e))
        video_url = None
    finally:
        if 'driver' in locals():
            driver.quit()
    
    return video_url

【カスタマイズできること】

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))

・'iframe' の部分を、そのサイトでビデオが埋め込まれている要素のタグやクラス名に変更します。例えば、ビデオが div 要素内にある場合は、(By.TAG_NAME, "iframe") を (By.TAG_NAME, "div") に変更します。

iframe = driver.find_element(By.TAG_NAME, 'iframe')

・'iframe' の部分を、ビデオURLを持つ要素のタグやクラス名に変更します。例えば、ビデオが div 要素内にある場合は、find_element(By.TAG_NAME, 'iframe') を find_element(By.TAG_NAME, 'div') に変更します。

video_url = iframe.get_attribute('src')

・iframe.get_attribute('src') の部分を、ビデオURLを取得するための適切な属性に変更します。例えば、ビデオURLが data-video-url 属性に含まれている場合は、iframe.get_attribute('src') を iframe.get_attribute('data-video-url') に変更します。

3.7. 取得したデータを使って画像を保存する関数

取得したデータを使って、サムネイル画像を指定のフォルダに保存します。

def save_images_to_drive(data, download_folder):
    if not os.path.exists(download_folder):
        os.makedirs(download_folder)
    for entry in data:
        image_url = entry['thumbnail_url']
        image_name = clean_filename(entry['title']) + '.jpg'
        if os.path.exists(os.path.join(download_folder, image_name)):
            print(f"{image_name} already exists.")
            continue
        try:
            image_response = session.get(image_url, stream=True)
            if image_response.status_code == 200:
                with open(os.path.join(download_folder, image_name), 'wb') as f:
                    for chunk in image_response.iter_content(1024):
                        f.write(chunk)
                print(f"Downloaded {image_name}")
            else:
                print(f"Failed to download {image_name} with status code {image_response.status_code}")
        except Exception as e:
            print(f"Error downloading {image_name}: {e}")

【カスタマイズできること】

image_url = entry['thumbnail_url']

・entry['thumbnail_url'] の部分を、そのサイトで画像URLが格納されているキーに変更します。たとえば、画像URLが entry['image_url'] に格納されている場合は、entry['image_url'] に変更します。

ここでの'thumbnail_url'は【3.5. HTMLから必要な情報を抽出する関数】の真ん中下にある以下の部分で作成されたURLになります。

# サムネイルURLの抽出
        thumbnail_tag = thumb_div.find('img')
        thumbnail_url = 'https:' + thumbnail_tag['src'] if thumbnail_tag else None

サムネイル画像が<img>に入っていることは説明したとおりですが、この画像のURLは<img src="//img.poyopara.com/files/102568.jpg">のようになっておりこのままだと画像のダウンロードができません。そこで、'https:' を追加してフルURLを作成しています。これにより、thumbnail_url には https://img.poyopara.com/files/102568.jpg というフルURLが格納されます。


3.8. メイン処理

ユーザーにタグとページ番号を入力させ、指定したタグに基づいてウェブサイトからデータを取得し、そのデータを使って記事を作成し、画像を保存し、特定のウェブサイトに自動で投稿します。

def main():
    tag = input("Enter the tag you want to scrape: ")
    page = int(input("Enter the page number to start scraping from: "))
    data = fetch_content_by_tag(tag, page)
    download_folder = './downloaded_images'
    save_images_to_drive(data, download_folder)
    df = pd.DataFrame(data)
    print(df)

    options = webdriver.ChromeOptions()
    #options.add_argument('--headless')  # ヘッドレスモードを使用
    driver = webdriver.Chrome(options=options)
    driver.get('https:/自分のブロタレスとのURL/login')
    WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.ID, 'mail')))
    WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.ID, 'pass')))
    driver.find_element(By.ID, 'mail').send_keys('メールアドレスをここに入力')
    driver.find_element(By.ID, 'pass').send_keys('パスワードをここに入力')
    driver.find_element(By.CSS_SELECTOR, 'input[type="submit"]').click()
    WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.ID, 'globalnav')))
    articles_link = driver.find_element(By.LINK_TEXT, "記事")
    articles_link.click()
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))).click()
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'pagetitle')))
    start_time = datetime.datetime.now().replace(hour=17, minute=0, second=0, microsecond=0)

    for entry in data:

        driver.find_element(By.ID, 'pagetitle').send_keys(entry['title'])
        driver.find_element(By.ID, 'tags').send_keys(' '.join(entry['tags']))
        driver.find_element(By.ID, 'movieurl').send_keys(entry['video_url'])
        driver.find_element(By.NAME, 'img_link').send_keys(entry['video_url'])

        driver.find_element(By.ID, 'titleCheckBtn').click()
        time.sleep(3)

        try:
            alert = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '.alert.alert-danger'))
            )
            print("Alert found:", alert.text)

            # Clear fields only if there is an alert
            driver.find_element(By.ID, 'pagetitle').clear()
            driver.find_element(By.ID, 'tags').clear()
            driver.find_element(By.ID, 'movieurl').clear()
            driver.find_element(By.NAME, 'img_link').clear()

        except TimeoutException:
            print("No alerts, proceeding with image upload.")
            # 投稿時間を設定
            post_date = driver.find_element(By.ID, 'post_date')
            post_date.clear()
            post_date.send_keys(start_time.strftime('%Y-%m-%d'))
            
            post_hour = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'post_date_hour')))
            post_minute = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'post_date_minute')))
            
            post_hour.send_keys(start_time.strftime('%H'))
            post_minute.send_keys(start_time.strftime('%M'))

            start_time += timedelta(minutes=30)  # 次の投稿時間を30分後に設定

            driver.find_element(By.ID, 'titleCheckBtn').click()
            time.sleep(3)  # サーバー応答待ち

            # Proceed with image upload
            image_path = os.path.abspath(os.path.join(download_folder, clean_filename(entry['title']) + '.jpg'))
            driver.find_element(By.ID, 'page_image').send_keys(image_path)

            # Before clicking the submit button, change the form's action URL
            driver.execute_script("document.getElementById('pageEditForm').setAttribute('action', 'https://eromaji.blogterest.net/kanri/page/edit/0/')")
            send_button = driver.find_element(By.NAME, "send")
            driver.execute_script("arguments[0].click();", send_button)

            print("Article posted.")
            # Wait 3 seconds before clicking the 'Erotare Reflect' button
            time.sleep(3)

            # 'エロタレスト反映'ボタンをクリックした後のコード
            click_erotere_button(driver, entry['title'])
            print("Clicked 'Erotare Reflect' button: ", entry['title'])

           # 'エロタレスト反映'ボタンをクリック後、ポップアップが表示されるのを待つ
            try:
                # ポップアップが表示されるのを待つ
                WebDriverWait(driver, 10).until(
                    EC.visibility_of_element_located((By.ID, 'detail'))
                )
                print("ポップアップが表示されました。")

                # ポップアップ以外の場所をクリックして閉じる
                body_element = driver.find_element(By.TAG_NAME, 'body')
                ActionChains(driver).move_to_element_with_offset(body_element, 10, 10).click().perform()
                print("ポップアップを閉じました。")

                # ポップアップが閉じたことを確認
                WebDriverWait(driver, 10).until(
                    EC.invisibility_of_element_located((By.ID, 'detail'))
                )
                print("ポップアップが正常に閉じました。")

                # 「新規作成」リンクがクリック可能になるのを待つ
                WebDriverWait(driver, 10).until(
                    EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))
                ).click()
                print("新規作成ページにアクセスしました。")

            except TimeoutException as e:
                print(f"処理中にタイムアウトが発生しました: {str(e)}")

            # Navigate back to the new article creation page to reset the form
            articles_link = driver.find_element(By.LINK_TEXT, "記事")
            articles_link.click()
            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "新規作成"))).click()

            # Wait until the 'pagetitle' element is visible and ready for new input
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'pagetitle')))

    input("Press Enter to close the browser...")
    driver.quit()

if __name__ == "__main__":
    main()

【カスタマイズできること】

driver.get('https:/自分のブロタレスとのURL/login')

・ログインページのURLを自分のサイト(エロタレストブログ)のログインURLに変更します。

driver.find_element(By.ID, 'mail').send_keys('メールアドレスをここに入力')
driver.find_element(By.ID, 'pass').send_keys('パスワードをここに入力')

・エロタレストブログならメールアドレスとパスワードを自分のものに変更します。

start_time = datetime.datetime.now().replace(hour=17, minute=0, second=0, microsecond=0)

・ここで start_time という変数に、現在の日時をベースにして時間を17:00:00に設定した日時オブジェクトを代入しています。この時間は、最初の投稿時間として使用されています。

start_time = datetime.datetime.now()

これだけにすれば、現在の時間になります。

start_time += timedelta(minutes=30)

各記事の投稿時間を30分ずつずらしています。これにより、次の記事の投稿時間が現在の投稿時間から30分後に設定されます。

start_time += timedelta(hours=1)

とすれば、1時間後に設定されます。

4. コードの実行方法

ここからは、コードを実行するための具体的な手順を説明します。

4.1. コードをファイルに保存する

まず、上記のコードをコピーして、テキストエディタ(メモ帳やVSCodeなど)に貼り付けます。そして、ファイル名を「auto_post.py」として保存します。

メモ帳で保存するには以下の順です。

  1. メモ帳開く。

  2. コードをコピーして貼り付ける

  3. ファイルを「auto_post.py」としてデスクトップに保存する。(別の名称でも大丈夫です)

Macの場合は、【テキストエディット】です。
※そのままだと実行できないので、「フォーマット」→「標準テキストにする」にクリックしてください。


4.2. コマンドプロンプトまたはターミナルでディレクトリを移動する

次に、コマンドプロンプトまたはターミナルを開き、先ほど保存した「auto_post.py」のあるフォルダに移動します。例えば、ファイルがデスクトップにある場合は、以下のコマンドを実行します。

Windowsの場合

cd Desktop

Macの場合

cd ~/Desktop

4.3. コードを実行する

最後に、以下のコマンドを実行してコードを実行します。

python auto_post.py

これで、プログラムが実行されるはずです。
検索したいキーワードとページ番号を入力するプロンプトが表示されます。入力が完了すると、指定したタグに基づいてデータを取得し、記事が自動的に投稿されます。

まとめ

このノートでは、エロタレストブログでのブログ投稿を自動化するコードの仕組みを解説し、実行するための手順を説明しました。
これを使えば、記事の投稿作業が効率化され、もっとコンテンツ作成に集中できます。
もし気に入っていただけたら嬉しいです。

応援していただける方は以下お願いします。3万文字(コードの文字含むからそうでもないか…)の苦労が報われます。

ここから先は

0字

¥ 500

この記事が気に入ったらチップで応援してみませんか?