SE吾郎の備忘録

24歳SEの勉強用の備忘録です.皆様の役にも立てれば幸いです.

【備忘録】AI画像生成で発生したエラーと対処方法まとめ

Google Colab上で動かしていたAIを使用した画像生成コードでエラーが発生するようになってしまいました.AI画像生成の作成方法については別記事を作成予定なので,少々お待ちください.
StableDiffuisonを使用した画像生成コードを作成していたのですが,モデル設定部分でエラーが発生するようになってしまいました.

・StableDiffuionモデル設定エラー

発生エラー


---------------------------------------------------------------------------
ValueError  Traceback (most recent call last)

---->  pipe = StableDiffusionPipeline.from_ckpt("https://huggingface.co/BanKaiPls/AsianModel/blob/main/BRAV5finalfp16.safetensors").to("cuda")

/usr/local/lib/python3.10/dist-packages/diffusers/utils/deprecation_utils.py in deprecate(take_from, standard_warn, stacklevel, *args)
       for attribute, version_name, message in args:
         if version.parse(version.parse(__version__).base_version) >= version.parse(version_name):
--->     raise ValueError(
            f"The deprecation tuple {(attribute, version_name, message)} should be removed since diffusers'"
            f" version {__version__} is >= {version_name}"

ValueError: The deprecation tuple ('from_ckpt', '0.21.0', 'The function `from_ckpt` is deprecated in favor of `from_single_file` and will be removed in diffusers v.0.21. Please make sure to use `StableDiffusionPipeline.from_single_file(...)` instead.') should be removed since diffusers' version 0.21.2 is >= 0.21.0


「diffusersのバージョン0.21.0以降ではStableDiffusionPipeline.from_ckptの関数が廃止されています.
from_ckptの代わりにfrom_single_fileを使ってください.」
という内容のエラーみたいです.
知らないうちに現在のバージョンでは動かないコードになっていたみたいですね. ウェブ上でコードを動かす場合,今まで動いていたコードが動かなくなるのは嫌ですね.

・対応方法

関数を最新版のものに変更すれば,引数などの変更も必要なくそのまま実行す流ことができました.

修正後コード


pipe = StableDiffusionPipeline.from_single_file("https://huggingface.co/BanKaiPls/AsianModel/blob/main/BRAV5finalfp16.safetensors").to("cuda")

修正前コード


pipe = StableDiffusionPipeline.from_ckpt("https://huggingface.co/BanKaiPls/AsianModel/blob/main/BRAV5finalfp16.safetensors").to("cuda")

これで修正完了です.ウェブ上には対応方法の情報があまり載っていなかったので,まとめてみました.エラーコードを丁寧に読めば対応できる内容でしたが,プログラムに詳しくない人でもAI画像生成に挑戦している人は多いと思うので,参考になっていれば嬉しいです.最後に修正後に生成した画像がこちらになります.

AI生成した画像


最新のAIは凄いですね!

 

【備忘録】Jenkins新スレーブPC追加で発生したエラーと対処方法まとめ

こちらの記事を参考にJenkinsのスレーブPC(ノードPC)を追加したのですが,いくつか苦戦したポイントがあったので,エラーとその対処方法をまとめます.
【CI奮闘記】第6章:エージェントを作ってみよう!
エラー発生箇所としては「Lauch agent by connecting it to the master」を設定で選択し,新ノードPC側でJava Web Start (JNLP)を実行するタイミングでエラーが発生しました.

JNLP不正エラー

発生エラー


    INFO: Locating server among [http:://255.255.255.255:8080/jenkins/]
    ** **, 20** **:**:** ** org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve
    INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping]
    ** **, 20** **:**:** ** org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver isPortVisible
    WARNING: connect timed out
    ** **, 20** **:**:** ** hudson.remoting.jnlp.Main$CuiListener error
    SEVERE: http:://255.255.255.255:8080/jenkins/ provided port:49600 is not reachable
    java.io.IOException: http:://255.255.255.255:8080/jenkins/provided port:49600 is not reachable
        at org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.resolve(JnlpAgentEndpointResolver.java:311)
        at hudson.remoting.Engine.innerRun(Engine.java:724)
        at hudson.remoting.Engine.run(Engine.java:540)

※(エラーログのurlと時間は変更しています)


まず,新ノードPCからアクセスするJenkinsのマスターのURLをIPアドレスからリネームしている方もIPアドレスからアクセスしてください.
次に,本エラーの対処方法ですが,私の場合は既に別のノードPCが接続された状態で,さらに新規のノードPCの追加中にこのエラーが発生しました.Jenkinsの設定,JenkinsのバージョンもJavaのバージョン,ファイルパスも合わせたのにエラーが発生してしまいました.


そこで,jenkins-agent.jnlpの中身を比較し,修正したところ接続することができました.
jenkins-agent.jnlpをエディタで開き,後ろの</argument>と</application-desc>の間に「<argument>-url</argument><argument>http://255.255.255.255:8080/jenkins/」を追加してください.(IPアドレス部分は自分のJenkinsマスターのIPアドレス)
この1文を追加するだけで,接続することができました!
なぜ,jenkins-agent.jnlpの中身が異なるものになっていたのか原因は分かりませんが,個人では中々気付くことが出来ないと思うので,同様のエラーが発生している方はやってみてください!

Java version違いエラー

発生エラー


    ** **, 20** **:**:** ** Main verifyJavaVersion
    SEVERE: Running with Java class version 63 which is not in the list of support versions: [52, 55]. Run with the --enable-future-java flag to enable such behavior, See https://jenkins.io/redirect/java-support/
    java.lang.UnsupportedClassVersionError: 63.0
        at Main.verifyJavaVersion(Main.java:130)
        at Main.main(Main.java:99)
    
    Jenkins requires Java versions [8, 11] but you are running with Java 19 from C:\**
        at Main.verifyJavaVersion(Main.Java:130)
        at Main.main(Main.java:99)

 

こちらのエラーはJenkinsでの対応可能なJavaのバージョンと使用環境のJavaバージョンの不整合により発生します.

JetnkinsでのJava対応バージョンは8か11なので,それ以外のバージョンを使用すると発生します.

私の場合はJavaのバージョンは19だったので,エラーが発生してしまいました.また,Jenkinのバージョン2.357以降はJava8の対応がなくなることがこちらの記事で発表されています.
Jenkins公式サイト(Java対応バージョン)
そのため,Javaをインストールし直す場合,バージョン11をおすすめします.

・agent.jar不足エラー

今後,追記予定

Javaパスエラー

今後,追記予定

【備忘録】instagram自動化プログラムが使えなくなった!?

こちらの記事で作成したインスタの自動実行プログラムなのですが,コードは変更していないのにエラーが発生し,実行出来なくなってしまいました.(リンク先記事のソースコードは修正済みです)

segoro.hatenablog.com

ある日突然以下のエラーが出るようになってしまいました.
target = driver.find_elements_by_class_name('_9AhH0')[10] IndexError: list index out of range
エラーの内容としてはクラスの名前「_9AhH0」が見つかりません というエラーです.
しかし,今まではこのコードで動いていたはずですし,特に何も触っていないのに...
そこでひとつひとつ動作を確認してみましたが,やはり
target = driver.find_elements_by_class_name('_9AhH0')[10]
の部分でエラーが出てしまいます.読み込み速度による問題でもなさそうでした.(何箇所か以前より読み込み速度が遅くなりエラーになるところがありました.)
キー自体が存在しないのか!?と思いブラウザから確認してみるとビンゴでした.
instagram側のアップデートの際にキーが変わっていたみたいです.この他にも2~3箇所キーが変わっている場所がありました.
ひとつずつキーを探して修正しましたが,毎回アップデートの度に変わるのであれば面倒ですね...
何か良い方法はないでしょうか...
修正部分のコードを載せておきます.

before


    driver.find_element_by_class_name('HoLwm').click()
    target = driver.find_elements_by_class_name('_9AhH0')[10]
    driver.find_elements_by_class_name('_9AhH0')[9].click()
    driver.find_element_by_class_name('fr66n').click()
    driver.find_element_by_class_name('coreSpriteRightPaginationArrow').click()

after


    driver.find_element_by_class_name('_a9_1').click()
    target = driver.find_elements_by_class_name('_aa8k')[10]
    driver.find_elements_by_class_name('_aa8k')[9].click()
    driver.find_element_by_class_name('_aamw').click()
    driver.find_element_by_class_name('_aaqg').click()

【備忘録】seleniumは定期的なメンテナンスが必要!? Chrome Driverエラー対応方法

Chrome Driverバージョン不整合対応方法

seleniumで自動実行プログラムを作成してちょくちょく回していたのですが,突然以下のエラーが出てしまいました.
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 94 Current browser version is 104.0.5112.101 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome こちらのエラーはChromeのバージョンとChrome Driverのバージョンが一致していません というエラーです.
Chrome Driverは更新はしていないので,Chromeが自動更新されていたみたいです.
現在のChromeのバージョン(このエラーの場合,104.0.5112.101)を確認し,対応するChrome Driverに更新すれば解決します.
バージョンの1番大きい数字が合うものをダウンロードすればOKです.(今回はバージョン104)
また,Chromeの自動更新が走らないように設定の変更方法も記載します.

chrome_version

Chromeの自動アップデート停止方法

Mac

公式リンクMac版
どうやら「com.google.Keystone.plist」の値を変更すれば良いみたいですね.
これだけではよく分からないと思うので,やり方を解説します.自動アップデートを停止する場合,「chrome://settings/help」からの手動アップデートも出来なくなるので注意してください.
terminalからコマンドdefaults write com.google.Keystone.Agent checkInterval 0 で自動アップデートをオフにすることが出来ます.再び自動アップデートをオンにしたい場合はdefaults write com.google.Keystone.Agent checkInterval 1で戻すことが出きます.

Windows

公式リンクWindows版
1.「Windows」+「R」で「ファイルを指定して実行」を起動
2. コマンド「gpedit.msc」を入力
3. コンピュータの構成->管理用テンプレート を右クリックし,テンプレートの追加と削除をクリック
4. 追加をせクリックし,「コンピュータの構成\管理用テンプレート\クラシック管理用テンプレート(ADM)\ Google \ Google Update \ Applications \ Google Chrome」のパスを選択
5. 「Update Policy Override」をクリックし,「Updates disabled」を選択すればOKです.
6. PC再起動後にchromeの自動アップデートは無効になります

【備忘録】インスタのフォロワーが自動で増える!? pythonで自動いいねを押すプログラム

seleniumを使用したブラウザ自動操作によってフォロワーが自動で増えるプログラムの作成を目指します.
本記事はこんな方におすすめです.

  • seleniumを使用したプログラムの勉強をしたい人
  • インスタのフォロワーを何もせずに増やしたい人

実装するプログラムのアルゴリズムは以下のようになります.
seleniumを起動
・instagrmのページにアクセスし,ログインする.
・設定したタグを検索し,最新投稿から複数個の投稿にいいねをつける.
このような手順の方がフォロワーが増えやすいよというアドバイスがありましたら,コメントいただけると嬉しいです.
以下に実際のコードを載せます.実際に使用する場合は,コピペしてID****とpass****を自分のユーザIDとパスワードに変更するだけで実行可能です.
検索ワードも自分に合ったものに変えて見てください.


from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
import time
import random

def login():
    # Instagramのログインページを指定
    driver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
    time.sleep(1)

    ### 追加箇所 Start ###
    # メアドとパスワードを入力
    driver.find_element_by_name('username').send_keys('ID*******')
    time.sleep(1)
    driver.find_element_by_name('password').send_keys('pass*****')
    time.sleep(1)

    # ログインボタンを押す
    driver.find_element_by_class_name('L3NKy').click()
    time.sleep(5)

    #後で
    driver.find_element_by_class_name('yWX7d').click()
    time.sleep(5)

    #後で
    driver.find_element_by_class_name('_a9_1').click()
    time.sleep(3)

def tagsearch(tag, driver):
    # tagで渡ってきたハッシュタグのページにアクセス
    tagurl = 'https://www.instagram.com/explore/tags/'
    driver.get(tagurl + tag)
    time.sleep(3)

def pushnice(nice_num, driver): # いいねの回数を引数で指定
    # 最新の投稿が見える位置まで移動(スクロール)
    time.sleep(3)
    target = driver.find_elements_by_class_name('_aa8k')[10]
    actions = ActionChains(driver)
    actions.move_to_element(target)
    actions.perform()
    time.sleep(3)

    # 最新の投稿の1枚目をクリックしていいねを実行
    driver.find_elements_by_class_name('_aa8k')[9].click()
    time.sleep(3)
    #次の投稿を表示(矢印を押す)
    driver.find_element_by_class_name('_aamw').click()
    time.sleep(5)

    # 指定回数繰り返し
    for nn in range(nice_num-1):
        # ループ中のエラー対策
        print(nn)
        MAX_RETRY = 10 # エラーリトライ上限
        for retry_n in range(MAX_RETRY): # エラー発生時MAX_RETRY回リトライする
            try:
                # 次の投稿へ移動
                driver.find_element_by_class_name('_aaqg').click()
                x = random.randint(0, 5)
                time.sleep(20 + x)

                # いいねを押す
                driver.find_element_by_class_name('_aamw').click()
                x = random.randint(0, 5)
                time.sleep(5)
            # エラー時にはリトライ
            except:
                time.sleep(5)
                print("except")
                x = random.randint(0, 5)
                # 次の投稿へ移動
                driver.find_element_by_class_name('_aaqg').click()
                x = random.randint(0, 5)
                time.sleep(20 + x)

            # エラーなし
            else:
                break


if __name__ == '__main__':
    # Macの方用のChrome Driverのパスの設定
    driver = webdriver.Chrome('./chromedriver')
    time.sleep(1)
    # ログイン
    login()

    #タグ検索
    # 検索するハッシュタグを指定する。
    taglist = ['followforfollowback', 'likeforfollow', 'l4f']
    countlist = [5, 5, 5] 
    
    for j in range (0, 10):
        for i in range(0, 3):
            print(taglist[i])
            tagsearch(taglist[i], driver)
            pushnice(countlist[i], driver) 

    

こちらから簡単にコードの動作と解説を行います.
chorme driverを起動後,login関数でinstagramのサイトにアクセスし,入力したIDとパスワードでログインを行います.
chrome driverの実行には少し時間がかかるので,sleep関数で時間を開けています.

インスタ自動ログイン画面

次に,「ログイン情報の保存」と「お知らせをオンにする」のポップアップの後でボタンを押してログイン関数は終了になります

ポップアップ画面スキップ

pushnice関数では,


       target = driver.find_elements_by_class_name('_aa8k')[10] 

検索した投稿の最新投稿の画面に移動し,


       driver.find_elements_by_class_name('_aa8k')[9].click()

いいねを押し,


       driver.find_element_by_class_name('_aamw').click()

次の投稿に移動の矢印を押す というプロセスを繰り返します.
ループ内ではsleepあ関数の待ち時間をランダムにすることで,インスタ側からの機能制限を回避する狙いがあります.
また,何らかの失敗が発生しても自動プログラムが終了しないように例外処理で次の投稿に進むように設定しています.

みなさんも自動プログラムで,寝ている間にフォロワー獲得を目指してみませんか?

【備忘録】pythonからはてなブログを自動投稿(更新)する方法<実装編>

今回の記事は前回の続きで実装編です.
pythonコードを丸ごと載せているので,前回記事で取得した情報を使って一部書き換えることで動作することができます

segoro.hatenablog.com

変更するのはsetting部分のみで,usernameにの''の間に自分のユーザーネームを入力してください.
同様に,blognameにブログの名前,blogtitleにブログのタイトル,api_keyにブログのキーを入力してください.
こちらが実装のコードとなります.


from datetime import datetime
import requests as req
import hashlib
import random
import base64
import requests

# setting -----------------------------------------------------------                                
username = 'username'
blogname  = 'segoro.hatenablog.com'
blogtitle = '12345678901234'
api_key = '*******'
draft = 'no' # yes or no    

# time check --------------------------------------------------------
import datetime
now = datetime.datetime.now()
dtime = str(now.year)+"""-"""+str(now.month)+"""-"""+str(now.day)+"""T"""+str(now.hour)+""":"""+str(\
now.minute)+""":"""+str(now.second)

# function  ---------------------------------------------------------

def create_data(title,body):
    template = """<?xml version="1.0" encoding="utf-8"?>                                             
    <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app">               
    <title>{0}</title>                                                                               
    <author><name>{1}</name></author>                                                                
    <content type="text/html">                                                                 
    {2}                                                                             
    </content>                                                                                       
    <updated>{3}</updated>                                                                           
    <category term="" />                                                                             
    <app:control>                                                                                    
    <app:draft>{4}</app:draft>                                                                       
    </app:control>                                                                                   
    </entry>                                                                                         
    """
     
    data = template.format(title, username, body, dtime, draft).encode()
    return data
    
    
def post_hatena(data):
    headers = {'X-WSSE': wsse(username, api_key)}
    url = 'http://blog.hatena.ne.jp/{0}/{1}/atom/entry'.format(username, blogname)
    r = requests.post(url, data=data, headers=headers)
    
    
def get_hatena(data):
    uri = 'https://ipocalender.hatenablog.com/entry/IPOsummary/2021/Nov'
    url = 'https://blog.hatena.ne.jp/{0}/{1}/atom/entry/{2}'.format(username, blogname, blogtitle)
    r = requests.get(uri, auth=(username, api_key))


def wsse(username, api_key):
    created = datetime.datetime.now().isoformat() + "Z"
    b_nonce = hashlib.sha1(str(random.random()).encode()).digest()
    b_digest = hashlib.sha1(b_nonce + created.encode() + api_key.encode()).digest()
    c = 'UsernameToken Username="{0}", PasswordDigest="{1}", Nonce="{2}", Created="{3}"'
    return c.format(username, base64.b64encode(b_digest).decode(), base64.b64encode(b_nonce).decode(\
    ), created)


if __name__ == '__main__':
    title = 'test'
    print(dtime)
    data = create_data(title, dtime)
    put_hatena(data)    

    

【備忘録】pythonからはてなブログを自動投稿(更新)する方法<準備編>

今回,解説する内容はpythonによるはてなブログ投稿です.
作成したコードを自動化する方法は,JenkinsとGoogleCloudPlatformの設定に関する過去記事を参考にしてください.

segoro.hatenablog.com

segoro.hatenablog.com

投稿用ブログページを作成する

仮のページで良いので,一度投稿用ページを作成してください.
今回の手法では同じページを自動更新する方法おを紹介します.
ブログの中からこれらの情報が必要になります.

    ・ブログのユーザネーム
    ・ブログの名前
    ・ブログのタイトル
    ・ブログのキー

これら4つの情報が自動取得する際に必要な情報です.
確認の仕方を含めて解説していきたいと思います.

・ユーザーネームの取得

設定->アカウント設定 を開いてください.
プロフィールのはてなIDがブログのユーザーネームに該当します.

ユーザーネームの取得
・ブログのキー

設定->アカウント設定 でキーの取得も一緒にしていまいましょう.
1番下までスクロールすると,APIキーという項目があるので全てコピーしてください.

・ブログ名の取得

設定->基本設定 のブログ全体の設定の先頭部分にブログURLが存在するのでこちらを確認してください.
必要な部分としてはhttps://から/までの間の文字列です.私のブログの場合,URLが https://segoro.hatenablog.com/ なので必要な情報は segoro.hatenablog.com になります.

ブログ名の取得
・ブログのタイトル

記事の管理 から仮に作成したページの作成画面に進みます.
この時のURLを取得してください. このようなURLになっていると思います. https://blog.hatena.ne.jp/ユーザーネーム/ブログ名/edit?entry=123456789012345123
最後のentry=以下の数値の部分がブログのタイトルになります.
ついでに先ほど調べたうユーザーネームとブログ名が正しいか確認してください

ここまでで,ユーザーネーム,ブログ名,ブログのタイトル,ブログのキーを取得することができました.
これで準備は完了になります.次の記事で実際に実行するpythonコードを取り扱います.