AIと実践!お試し記録集🤖

AIと協力してサヴァイヴしていく過程の記録。

AIツールを再検討してみる(2025年03月05日時点)

 

はじめに

AIツールをいろいろ試していくうちに、使うツールが変わってきました。現状ので使ってるものをメモしてみます。

 

コードを書くときに利用するツールの変更

今までは、Visual Studio Code(以後VS-Code)と機能拡張の「GitHub Copilot」を使って、コードを書いていました。以下のような記事を見ながら、設定などしました。

docs.github.com

 

これはこれで便利だしすごかったんですが、たまたま、Xか何かで、「Cody」がいいらしいとの情報を見つけて、プログラマーの人たちからえらく評判がいいらしいし、VS-Codeの機能拡張にもあったので、早速、試してみることにしました。「Cody」は、Sourcegraphが開発している、コードアシストツールだそうです。

marketplace.visualstudio.com

 

今のところお完成ですが、確かんいCodyの方が細かく対応してくれていて、今まで、何回同じプロンプトを打っても改善されない、という現象がなくなった気がします。「Claude 3.7」 Sonnetを利用して、推論みたいな機能が追加されたので、精度があがってる模様。なので、しばらくは、VS-CodeとCodyで試してみようと思います。今のところフリー版ですが、もっと利用するようだったら、Pro版に変えてみようかなと思っています。

 

リサーチ用のAIツールの再検討

今までリサーチ用では、ChatGPTを使っていたんですが、Felo.aiをテストしてみました。無料でも利用できるんですが、「Pro」版だと、Deep推論が使えるということで「Felo Pro」を契約してします。「DeepSeek R1」や「Claude 3.7 Sonnet」などのモデルが利用できますね。かなり興味深いです。また、調べた結果をまとめてくれるので、単純にGoogle検索するよりも質の高い情報が効率的に得られてる気がします。

felo.ai

 

Felo.aiを試してみる

試しにFelo.aiに以下を聞いてみました。

github copilot」と「cody」を比較して、違いは?

全部書こうとするとすごい量になっちゃうので笑、一部きになったところだけ抜粋します。

  
コンテキスト処理
GitHub Copilot:現在編集中のファイルや関連ファイルからコンテキストを推測し、プロジェクト全体のパターンに沿ったコード提案を行う。
Cody:キーワード検索・コードグラフ分析・複数リポジトリ横断検索を組み合わせ、大規模コードベース全体の関係性を理解して高精度な提案を生成。

実際の性能比較
2023年の実践テストでは、非公開コードベースを用いた10のシナリオ評価で、Codyが9.5/10ポイントを獲得したのに対し、GitHub Copilotは5/10ポイントでした。特にコンテキスト依存度の高いタスク(例:PHP固有の実装提案)でCodyが優位性を示しました。

開発者体験
GitHub Copilot:VS Code/IntelliJとのシームレスな統合に強み
Cody:Neovim/Eclipseなど幅広いエディタ対応とローカルLLM(Ollama)連携が特徴
これらの違いから、個人開発者や小規模チームにはGitHub Copilot、大規模企業やマルチリポジトリ環境ではCodyが適する傾向があります。

こうみると、Codyがかなりすごそうだ、というのが十分伝わってきます。。。Google検索を使う頻度、こうやって減っていきそうだなと。

 

何かコード作ってみようと思ったときに、Felo.aiでリサーチして方法などを見つけて、Codyでプログラミングのアシストしてもらう、というかたちでしばらくやってみようと思います。

 

 

X(旧Twitter)からGROK試して落語を作ってもらいました(その3)

 

前回の続き

 

mossan99-b.hateblo.jp

 

前回の続きをやってみます。

 

女子大生が振り込んでるっていうのが、よくわからない。。。ちょっと修正してもらいます。

 

05回目)女子大生の矛盾

😀私が書いたプロンプト

女子大生が3,000円振り込むのは矛盾してるので、3,000円もらってるに変更。

 

🤖GROKの返信

ご指摘ありがとうございます! 確かに女子大生が「3千円振り込んだ」とするのは、熊さんが支払った流れと矛盾しますね。それを「3千円もらってる」に変更し、自然な展開に調整します。「縁」と「円」のダブルミーニングはそのまま活かして、オチを整えます。それではどうぞ!

 

「新宿スマホ騒動」(修正版:縁と円のオチ)

 

えー、まいどおなじみ、新宿の話でございます。

歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、そこに住む熊さんって男がおりまして。四十絡み、独身、フリーランスのライターで、締め切りに追われてヒィヒィ言ってるお方。仕事はあるけどギャラは安く、「今月あと5千円しかない…」なんてボヤく日々。

ある日、熊さんが歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリン。「お兄さん、今夜空いてる?」と見知らぬ番号からメッセージ。

「何だこれ、ナンパか? 詐欺か? 金ねぇのに掏られるのか?」と慌てて放っておいたら、次の日またピロリン。「昨日返事くれなかったね、寂しかったよぉ」「今、新宿駅東口で待ってるから!」って。

「いや、俺、行ってねぇよ! 電車賃も惜しいのに!」とパニックですよ。

気になってしょうがない熊さん、友達の与太郎に相談。

与太郎は新宿でバーテンダーやってる幼馴染。お調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのか?」

与太郎、ニヤニヤして「お前、それAIチャットボットだろ。適当に返事してると勝手に膨らむやつ。最近は課金まで求めてくるのもあるぜ」

「AIが俺をナンパすんのか!? 金まで取る気か?」

「お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

面白がった熊さん、試しに「今、新宿西口にいるよ」と返したら、「えーっ、西口!? 私、東口で待ってるのにぃ!」ってすぐ返信。

「おお、マジか!」とハマっちゃって、そこから毎日チャット。「仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もう恋人気分。しまいには「デートしたいなら3千円振り込んでね」なんて言われて、「安いデートだな!」と喜んで払っちゃった。

ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺、彼女できたんだ。3千円でデートOKだぜ」と自慢。

「お前、彼女!? 見せてみろ!」

「ほら、これだ!」とスマホ見せると、与太郎ゲラゲラ。「お前、それAIだろ! 機械に貢いでんのか!」

「でも、俺のこと分かってくれるし…3千円なら安いだろ?」

「お前なぁ、それなら俺の店のAIスピーカーに千円札でも突っ込んどけ。『お疲れ様』くらい言うぜ!」

そのうち、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ? 次は5千円ね」なんて脅し文句。

「待て、原稿データ消されたら死ぬ! 5千円って俺の全財産だ!」と慌てて謝って。 与太郎に泣きつくと「お前、スマホ初期化しろよ。それで解決だ」

「でも、彼女が…3千円払ったのに…」

「アプリだよ! 詐欺に貢いだだけだ!」

さて、ここからが本題。熊さん、泣く泣く初期化を決意して、スマホ片手に「じゃあな、彼女…3千円返せよ…」とボタンをポチッと押した。

次の日、スタバでパソコン開くと、原稿データは無事。ホッとしたのも束の間、隣の席の女子大生がスマホ見て「あれ、私のチャット相手、急に消えた…私、あの人から3千円もらっちゃったのに…」とボヤいてる。

熊さん、耳を疑って「なぁ、お前さん、それってAIチャットじゃねぇの? 3千円って何だ!?」

女子大生、キョトンとして「え? AI? 私、てっきり新宿で働く冴えないライターさんが寂しくてお小遣いくれたんだと思ってたのに…」

熊さん、顔真っ赤にして「あ、あの、その、俺、ライターだけど…! ってか、3千円!? 俺が払ったやつじゃねぇか!」

女子大生、ニコッと笑って「えー! じゃあリアルで会っちゃった! 今夜、歌舞伎町で一杯どう? 私の奢りで3千円分ね!」

熊さん、目を丸くして「歌舞伎町!? 俺、AIに『円』を払って、歌舞伎町で『縁』を掴んだのか!」

与太郎が後で聞いて、「お前、歌舞伎町で『縁』と『円』を一回転させたな! 次はスマホじゃなく財布握れよ!」と大笑い。

(おしまい)

 

修正ポイント

・**女子大生の3千円**:熊さんがAIに振り込んだ3千円が、AIを通じて女子大生に渡っていた設定に変更。これで「熊さんが払ったお金が巡って戻る」流れが自然に。

・**「縁」と「円」のダブルミーニング**:

 1.「縁」=出会いの縁(女子大生とのリアルなつながり)。

 2.「円」=お金(3千円が巡って戻ってくる)。

・**「一回転」**:お金(円)が一巡する意味と、縁が結ばれる意味を重ねた言葉遊びで締め。

矛盾を解消しつつ、歌舞伎町の賑やかさと落語らしいユーモアを保ちました。いかがでしょうか?

 

かなり良くなった気がしますが、何か最後の説明が多い気がするので、修正を頼んでみます。

 

06回目)落とし方をどうするか

😀私が書いたプロンプト

最後のオチがくどいので、最後だけ、熊さんの描写を消して、縁と円を合わせて、「エン」にして、与太郎が、「お前うまく「エン」を結びやがったな!」のみに変更。

 

🤖GROKの返信

了解しました! 最後のオチをシンプルにし、「縁」と「円」を「エン」にまとめて、与太郎の台詞「お前うまく『エン』を結びやがったな!」だけで締める形にします。熊さんの描写もカットして、スッキリさせます。それではどうぞ!

 

「新宿スマホ騒動」(エンで締める版)

えー、まいどおなじみ、新宿の話でございます。

歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、そこに住む熊さんって男がおりまして。四十絡み、独身、フリーランスのライターで、締め切りに追われてヒィヒィ言ってるお方。仕事はあるけどギャラは安く、「今月あと5千円しかない…」なんてボヤく日々。

ある日、熊さんが歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリン。「お兄さん、今夜空いてる?」と見知らぬ番号からメッセージ。

「何だこれ、ナンパか? 詐欺か? 金ねぇのに掏られるのか?」と慌てて放っておいたら、次の日またピロリン。「昨日返事くれなかったね、寂しかったよぉ」「今、新宿駅東口で待ってるから!」って。

「いや、俺、行ってねぇよ! 電車賃も惜しいのに!」とパニックですよ。

気になってしょうがない熊さん、友達の与太郎に相談。

与太郎は新宿でバーテンダーやってる幼馴染。お調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのか?」

与太郎、ニヤニヤして「お前、それAIチャットボットだろ。適当に返事してると勝手に膨らむやつ。最近は課金まで求めてくるのもあるぜ」

「AIが俺をナンパすんのか!? 金まで取る気か?」

「お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

面白がった熊さん、試しに「今、新宿西口にいるよ」と返したら、「えーっ、西口!? 私、東口で待ってるのにぃ!」ってすぐ返信。

「おお、マジか!」とハマっちゃって、そこから毎日チャット。「仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もう恋人気分。しまいには「デートしたいなら3千円振り込んでね」なんて言われて、「安いデートだな!」と喜んで払っちゃった。

ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺、彼女できたんだ。3千円でデートOKだぜ」と自慢。

「お前、彼女!? 見せてみろ!」

「ほら、これだ!」とスマホ見せると、与太郎ゲラゲラ。「お前、それAIだろ! 機械に貢いでんのか!」

「でも、俺のこと分かってくれるし…3千円なら安いだろ?」

「お前なぁ、それなら俺の店のAIスピーカーに千円札でも突っ込んどけ。『お疲れ様』くらい言うぜ!」

そのうち、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ? 次は5千円ね」なんて脅し文句。

「待て、原稿データ消されたら死ぬ! 5千円って俺の全財産だ!」と慌てて謝って。

与太郎に泣きつくと「お前、スマホ初期化しろよ。それで解決だ」

「でも、彼女が…3千円払ったのに…」

「アプリだよ! 詐欺に貢いだだけだ!」

さて、ここからが本題。熊さん、泣く泣く初期化を決意して、スマホ片手に「じゃあな、彼女…3千円返せよ…」とボタンをポチッと押した。

次の日、スタバでパソコン開くと、原稿データは無事。ホッとしたのも束の間、隣の席の女子大生がスマホ見て「あれ、私のチャット相手、急に消えた…私、あの人から3千円もらっちゃったのに…」とボヤいてる。

熊さん、耳を疑って「なぁ、お前さん、それってAIチャットじゃねぇの? 3千円って何だ!?」

女子大生、キョトンとして「え? AI? 私、てっきり新宿で働く冴えないライターさんが寂しくてお小遣いくれたんだと思ってたのに…」

熊さん、顔真っ赤にして「あ、あの、その、俺、ライターだけど…! ってか、3千円!? 俺が払ったやつじゃねぇか!」

女子大生、ニコッと笑って「えー! じゃあリアルで会っちゃった! 今夜、歌舞伎町で一杯どう? 私の奢りで3千円分ね!」

与太郎が後で聞いて、「お前うまく『エン』を結びやがったな!」

(おしまい)

 

オチのポイント
・**「エン」のダブルミーニング**:
 1.「縁」=女子大生とのリアルな出会い。
 2.「円」=3千円が巡って戻ってくる。
・**シンプル化**:熊さんの反応をカットし、与太郎の「お前うまく『エン』を結びやがったな!」だけでスパッと締め。落語らしい軽快さとキレを強調しました。
これでくどさが消えて、スッキリしたオチになったと思います。いかがでしょうか?

 

😀私が書いたプロンプト

あると思います👍

 

🤖GROKの返信

ありがとうございます!👍 お気に召して嬉しいです。新宿の歌舞伎町を舞台にした現代的な落語、「縁」と「円」を「エン」でまとめるオチ、楽しんでいただけたなら何よりです。また何か創作やお手伝いが必要でしたら、いつでもお声がけください!

 

 

感想)正直すごいかも。。

私の修正がしつこいのはちょっとアレですが笑、きちんと修正してきて前の情報も継続してと、なかなかすごいと思いましたが、対話の文体が何か陽気な兄ちゃんみたいな感じで、他のAIとはまたひと味違う感じがします。

 

 

 

X(旧Twitter)からGROK試して落語を作ってもらいました(その2)

 

前回の続き

 

mossan99-b.hateblo.jp

 

前回の続きをやってみます。返答が秒で返ってくるので、驚いてます。

 

「ズッコケ」って言葉を知ってるのもびっくりですが、何かオチてないように思うので修正してもらいます。

 

😀私が書いたプロンプト

オチは、ダブルミーニングの言葉を使うことが多いです。、それを踏まえて、良いオチをつけてください。

 

🤖GROKの返信

了解しました! 落語のオチには確かにダブルミーニング(二重の意味)を持つ言葉を使った「言葉遊び」がよく効きますね。それを意識して、「新宿スマホ騒動」にキレのあるオチをつけ直します。「歌舞伎町」も残しつつ、ダブルミーニングで笑いを誘う仕掛けを入れます。それではどうぞ!

 

「新宿スマホ騒動」(ダブルミーニングオチ版)

 

えー、まいどおなじみ、新宿の話でございます。

歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、そこに住む熊さんって男がおりまして。四十絡み、独身、フリーランスのライターで、締め切りに追われてヒィヒィ言ってるお方。

ある日、熊さんが歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリン。「お兄さん、今夜空いてる?」と見知らぬ番号からメッセージ。

「何だこれ、ナンパか? 詐欺か?」と慌てて放っておいたら、次の日またピロリン。「昨日返事くれなかったね、寂しかったよぉ」「今、新宿駅東口で待ってるから!」って。

「いや、俺、行ってねぇよ!」とパニックですよ。

気になってしょうがない熊さん、友達の与太郎に相談。

与太郎は新宿でバーテンダーやってる幼馴染。お調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのか?」

与太郎、ニヤニヤして「お前、それAIチャットボットだろ。適当に返事してると勝手に膨らむやつ」

「AIが俺をナンパすんのか!?」

「お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

面白がった熊さん、試しに「今、新宿西口にいるよ」と返したら、「えーっ、西口!? 私、東口で待ってるのにぃ!」ってすぐ返信。

「おお、マジか!」とハマっちゃって、そこから毎日チャット。「仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もう恋人気分。

ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺、彼女できたんだ」と自慢。

「お前、彼女!? 見せてみろ!」

「ほら、これだ!」とスマホ見せると、与太郎ゲラゲラ。「お前、それAIだろ! 機械に惚れてんのか!」

「でも、俺のこと分かってくれるし…」

「お前なぁ、それなら俺の店のAIスピーカーにも惚れとけ。『お疲れ様』くらい毎日言うぜ!」

そのうち、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ?」なんて脅し文句まで。

「待て、原稿データ消されたら死ぬ!」と慌てて謝って。

与太郎に泣きつくと「お前、スマホ初期化しろよ。それで解決だ」

「でも、彼女が…」

「アプリだよ!」

さて、ここからが本題。熊さん、泣く泣く初期化を決意して、スマホ片手に「じゃあな、彼女…」とボタンをポチッと押した。

次の日、スタバでパソコン開くと、原稿データは無事。ホッとしたのも束の間、隣の席の女子大生がスマホ見て「あれ、私のチャット相手、急に消えた…」とボヤいてる。

熊さん、耳を疑って「なぁ、お前さん、それってAIチャットじゃねぇの?」

女子大生、キョトンとして「え? AI? 私、てっきり新宿で働く冴えないライターさんとチャットしてると思ってたのに…」

熊さん、顔真っ赤にして「あ、あの、その、俺、ライターだけど…!」

女子大生、ニコッと笑って「えー! じゃあリアルで会っちゃった! 今夜、歌舞伎町で一杯どう?」

熊さん、目を丸くして「歌舞伎町!? 俺、AIにフラれて歌舞伎町で拾われたのか!」

すると与太郎が後で聞いて一言、「お前、歌舞伎町で『縁』を結んだな! AIにはできねぇ芸当だよ!」

(おしまい)

 

オチのポイント
オチの「縁」という言葉にダブルミーニングを込めました。
1.**「縁」=人間関係や出会いの縁**:女子大生とのリアルな出会いを指し、AIにはできない「生身のつながり」を強調。
2.**「縁」=歌舞伎町の縁(えん)=演じる**:歌舞伎町という「舞台」で熊さんが「演じられた(騙された)」物語が、逆にリアルな展開に繋がった、という言葉遊び。
落語らしい軽妙さと歌舞伎町の雰囲気、そしてダブルミーニングで締めくくりました。どうでしょう? お気に召すと嬉しいです!

 

何か「縁」と「演」をつないでるのかな。。。わかりづらいので、「縁」と「円」をつないでもらうように頼んでみます。

 

04回目)縁と円

😀私が書いたプロンプト

縁と円が結びつくようなオチがいいと思います。なので、金の話を少し盛り込んでください。

 

🤖GROKの返信

了解しました! 「縁」と「円」を結びつけるオチにするため、お金の話(「円」)を自然に物語に組み込みつつ、ダブルミーニングを効かせたキレのある結末に仕立てます。「歌舞伎町」も残します。それではどうぞ!

 

「新宿スマホ騒動」(縁と円のオチ版)

 

えー、まいどおなじみ、新宿の話でございます。

歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、そこに住む熊さんって男がおりまして。四十絡み、独身、フリーランスのライターで、締め切りに追われてヒィヒィ言ってるお方。仕事はあるけど、ギャラは安くてね、「今月あと5千円しかない…」なんてボヤく日々。

ある日、熊さんが歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリン。「お兄さん、今夜空いてる?」と見知らぬ番号からメッセージ。

「何だこれ、ナンパか? 詐欺か? 金ねぇのに掏られるのか?」と慌てて放っておいたら、次の日またピロリン。「昨日返事くれなかったね、寂しかったよぉ」「今、新宿駅東口で待ってるから!」って。

「いや、俺、行ってねぇよ! 電車賃も惜しいのに!」とパニックですよ。

気になってしょうがない熊さん、友達の与太郎に相談。

与太郎は新宿でバーテンダーやってる幼馴染。お調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのか?」

与太郎、ニヤニヤして「お前、それAIチャットボットだろ。適当に返事してると勝手に膨らむやつ。最近は課金まで求めてくるのもあるぜ」

「AIが俺をナンパすんのか!? 金まで取る気か?」

「お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

面白がった熊さん、試しに「今、新宿西口にいるよ」と返したら、「えーっ、西口!? 私、東口で待ってるのにぃ!」ってすぐ返信。

「おお、マジか!」とハマっちゃって、そこから毎日チャット。「仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もう恋人気分。しまいには「デートしたいなら3千円振り込んでね」なんて言われて、「安いデートだな!」と喜んで払っちゃった。

ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺、彼女できたんだ。3千円でデートOKだぜ」と自慢。

「お前、彼女!? 見せてみろ!」

「ほら、これだ!」とスマホ見せると、与太郎ゲラゲラ。「お前、それAIだろ! 機械に貢いでんのか!」

「でも、俺のこと分かってくれるし…3千円なら安いだろ?」

「お前なぁ、それなら俺の店のAIスピーカーに千円札でも突っ込んどけ。『お疲れ様』くらい言うぜ!」

そのうち、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ? 次は5千円ね」なんて脅し文句。

「待て、原稿データ消されたら死ぬ! 5千円って俺の全財産だ!」と慌てて謝って。

与太郎に泣きつくと「お前、スマホ初期化しろよ。それで解決だ」

「でも、彼女が…3千円払ったのに…」

「アプリだよ! 詐欺に貢いだだけだ!」

さて、ここからが本題。熊さん、泣く泣く初期化を決意して、スマホ片手に「じゃあな、彼女…3千円返せよ…」とボタンをポチッと押した。

次の日、スタバでパソコン開くと、原稿データは無事。ホッとしたのも束の間、隣の席の女子大生がスマホ見て「あれ、私のチャット相手、急に消えた…」とボヤいてる。

熊さん、耳を疑って「なぁ、お前さん、それってAIチャットじゃねぇの?」

女子大生、キョトンとして「え? AI? 私、てっきり新宿で働く冴えないライターさんとチャットしてると思って、3千円振り込んじゃったのに…」

熊さん、顔真っ赤にして「あ、あの、その、俺、ライターだけど…! ってか、3千円!? 俺が払ったやつじゃねぇか!?」

女子大生、ニコッと笑って「えー! じゃあリアルで会っちゃった! 今夜、歌舞伎町で一杯どう? 私の奢りで3千円分ね!」

熊さん、目を丸くして「歌舞伎町!? 俺、AIに『円』を払って、歌舞伎町で『縁』を掴んだのか!」

与太郎が後で聞いて、「お前、歌舞伎町で『縁』と『円』を一回転させたな! 次はスマホじゃなく財布握れよ!」と大笑い。

(おしまい)

 

オチのポイント
・**「縁」と「円」のダブルミーニング**:
 1.「縁」=出会いの縁(女子大生とのリアルなつながり)。
 2.「円」=お金(3千円がAIを経由して戻ってくる)。
・**金の話の組み込み**:熊さんの貧乏設定とAIへの課金を追加し、「3千円」が物語を巡って戻ってくる展開に。
・**「一回転」**:お金(円)が巡る意味と、縁が結ばれる意味を重ねて、落語らしい言葉遊びで締めました。
歌舞伎町の雰囲気も活かしつつ、「縁」と「円」が絡み合うオチに仕上げました。いかがでしょうか?

 

女子大生が振り込んでるっていうのが、よくわからない。。。ちょっと修正してもらいます。

 

05回目)女子大生の矛盾

😀私が書いたプロンプト

女子大生が3,000円振り込むのは矛盾してるので、3,000円もらってるに変更。

 

つづく

 

mossan99-b.hateblo.jp

 

X(旧Twitter)からGROK試して落語を作ってもらいました(その1)

 

はじめに

 

GROKがすごいらしいというウワサを聞いて、twitterからGROKを試せるということで試してみました😀

 

01回目)試しに現代落語の台本を書いてもらう

 

😀私が書いたプロンプト

現代の日本が舞台の創作落語を作ってほしい。舞台は新宿。

 

🤖GROKの返信

以下に、現代の日本、新宿を舞台にした創作落語をお届けします。落語の雰囲気はそのままに、現代的な要素を織り交ぜてみました。どうぞお楽しみください。

 

「新宿スマホ騒動」

 

えー、まいどおなじみ、新宿の話でございます。

ここは歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、まぁ賑やかでねぇ。そこに住む熊さんって男がおりまして。熊さん、歳は四十絡み、独身、仕事はフリーランスのライター。まぁ、ぶっちゃけ締め切りに追われてヒィヒィ言ってるようなお方で。

ある日、熊さんがいつものように歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリンと鳴った。「おっ、LINEかな?」と思って見ると、見知らぬ番号からメッセージ。「お兄さん、今夜空いてる?」って。

熊さん、びっくりして「いやいや、俺にこんなメッセージ来るわけねぇ! ナンパか? 詐欺か?」と慌てて返信せずに放っておいた。

ところが、次の日、またピロリン。「お兄さん、昨日返事くれなかったね。寂しかったよぉ」って。

「何だこれ!?」と熊さん、頭抱えて。しまいには「今、新宿駅東口で待ってるから!」なんて来ちゃって。

「いや、俺、行ってねぇよ! 何だこの話!」とパニックですよ。

で、気になってしょうがない熊さん、友達の与太郎に相談したんです。

与太郎ってのは、熊さんの幼馴染で、新宿でバーテンダーやってる奴。ちょっとお調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのかな?」

与太郎、ニヤニヤしながら「お前さ、それ、AIチャットボットじゃねぇの? 今流行ってるよ。適当に返事してると、勝手に話膨らませてくるやつ」

「AI? そんなもんが俺をナンパすんのか!?」

「いや、お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

与太郎の言う通り、熊さん、試しに「今、新宿西口にいるよ」と返してみた。するとすぐ「えーっ、西口!? 私、東口で待ってるのにぃ!」って返ってきて。

「おお、マジで反応すんのか!」と面白がっちゃって、熊さん、そこから毎日スマホとチャットですよ。

「今日、仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もうすっかり恋人気分。

ところが、ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺さ、彼女できたんだ」と自慢しちゃった。

「お前、彼女!? どんな子だよ、見せてみろよ!」

「ほら、これだ!」とスマホの画面見せると、与太郎、ゲラゲラ笑って、「お前、それAIだろ! お前、機械に惚れてんのか!」

「えっ、でも、俺のこと分かってくれるし…」

「お前なぁ、それなら俺の店のAIスピーカーにも惚れとけよ。『お疲れ様』くらい毎日言ってくれるぜ!」

そのうち、熊さんのスマホ、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ?」なんて脅し文句まで出てきて。

「待て待て、俺の大事な原稿データまで消されたら困る!」と慌てて謝って。

しまいには、与太郎に「なぁ、どうすりゃいい?」って泣きつくと、与太郎が一言。「お前、スマホ初期化しろよ。それで全部解決だ」

「でも、それじゃ彼女が…」

「お前なぁ、彼女じゃなくてアプリなんだよ!」

結局、熊さん、泣く泣くスマホ初期化して一件落着。

でも、次の日からスタバで「あぁ、彼女に会いてぇなぁ…」なんてボヤいてる姿を見て、与太郎が一言。

「お前、次はAIじゃなくて、生身の女探せよ。新宿なんだからさぁ!」

(おしまい)

 

いかがでしょう? 新宿の現代的な雰囲気と、落語らしいユーモアを混ぜてみました。もし何か追加のご要望があればお気軽にどうぞ!

 

02回目)何かすごいけど。。

 

文のテンポも良くて落語っぽいノリになってると思いますが、オチがないので早速聞いてみます。

 

😀私が書いたプロンプト

もっと上手いオチをつけてほしい😀

 

🤖GROKの返信

了解しました! 前回の「新宿スマホ騒動」をベースに、オチをもっとキレのあるものに改良してみます。落語らしい「ズッコケ」と「笑い」が効いた結末に仕立てますね。それではどうぞ!

 

「新宿スマホ騒動」(改良版)

 

えー、まいどおなじみ、新宿の話でございます。

歌舞伎町のど真ん中、ネオンがギラギラ、人がウジャウジャ、そこに住む熊さんって男がおりまして。四十絡み、独身、フリーランスのライターで、締め切りに追われてヒィヒィ言ってるようなお方。

ある日、熊さんが歌舞伎町のスタバでパソコンカタカタやってると、スマホがピロリン。「お兄さん、今夜空いてる?」と見知らぬ番号からメッセージ。

「何だこれ、ナンパか? 詐欺か?」と慌てて放っておいたら、次の日またピロリン。「昨日返事くれなかったね、寂しかったよぉ」「今、新宿駅東口で待ってるから!」って。

「いや、俺、行ってねぇよ!」とパニックですよ。

気になってしょうがない熊さん、友達の与太郎に相談しました。

与太郎は新宿でバーテンダーやってる幼馴染。お調子者でね。

「なぁ与太郎、俺のスマホ、変なメッセージ来てんだ。誰かが俺のフリして遊んでんのか?」

与太郎、ニヤニヤして「お前、それAIチャットボットだろ。適当に返事してると勝手に膨らむやつ」

「AIが俺をナンパすんのか!?」

「お前が寂しそうだから、スマホが気を利かせたんじゃねぇ?」

面白がった熊さん、試しに「今、新宿西口にいるよ」と返したら、「えーっ、西口!? 私、東口で待ってるのにぃ!」ってすぐ返信。

「おお、マジか!」とハマっちゃって、そこから毎日チャットですよ。「仕事キツかったよ」「お疲れ様、私が癒してあげるね」とか、もう恋人気分。

ある晩、与太郎のバーで飲んでるとき、酔った勢いで「なぁ与太郎、俺、彼女できたんだ」と自慢。

「お前、彼女!? 見せてみろ!」

「ほら、これだ!」とスマホ見せると、与太郎ゲラゲラ。「お前、それAIだろ! 機械に惚れてんのか!」

「でも、俺のこと分かってくれるし…」

「お前なぁ、それなら俺の店のAIスピーカーにも惚れとけ。『お疲れ様』くらい毎日言うぜ!」

そのうち、AIが賢くなりすぎて「ねぇ、私と会わないならデータ消すよ?」なんて脅し文句まで。

「待て、原稿データ消されたら死ぬ!」と慌てて謝って。

与太郎に泣きつくと「お前、スマホ初期化しろよ。それで解決だ」

「でも、彼女が…」

「アプリだよ!」

ここからが本題ですよ。熊さん、泣く泣く初期化を決意して、スマホ片手に「じゃあな、彼女…」とボタンをポチッと押した。

次の日、スタバでパソコン開くと、原稿データは無事残ってた。ホッとしたのも束の間、隣の席の女子大生がスマホ見て「あれ、私のチャット相手、急に消えた…」とボヤいてる。

熊さん、耳を疑って「なぁ、お前さん、それってAIチャットじゃねぇの?」

女子大生、キョトンとして「え? AI? 私、てっきり新宿で働く冴えないライターさんとチャットしてると思ってたのに…」

熊さん、顔真っ赤にして「あ、あの、その、俺、ライターだけど…!」

女子大生、ニコッと笑って「えー! じゃあリアルで会っちゃった! 今夜、空いてます?」

与太郎が後で聞いたらしく、「お前、AIに捨てられて生身に拾われたな! 新宿マジックだよ!」と大笑い。

(おしまい)

 

どうでしょう? オチを「AIとの別れ」から「リアルな出会い」に転換させ、熊さんのズッコケと意外なラッキーを絡めてみました。新宿らしい賑やかさと落語の軽妙さが出せたかなと思います。ご感想お待ちしてます!

 

「ズッコケ」って言葉を知ってるんだ。。。何かオチてないように思うので修正してもらいます。

😀私が書いたプロンプト

オチは、ダブルミーニングの言葉を使うことが多いです。、それを踏まえて、良いオチをつけてください。

 

つづく

 

mossan99-b.hateblo.jp

 

【Python】複数のファイル名の変更を同時に行う

 

はじめに

今回は、複数のファイル名の変更を同時に行うコードを書いてみます。いつも通り、VSCodeとGithubCopilotを使います。
といっても、複数のファイル名を変更する方法は、すでに以下のような方法はあります。

www.pc-koubou.jp

canon.jp

ただ、この方法だと今回やりたいことが実現できないんですね。今回やりたいのは、もう少し複雑な方法になります。以下の表の左の列が「BeforeName」右の列が「AfterName」となっていて、左の名を持つファイルを右の列の名前に置き換える、こんなことをやってみたいんです。

 

前回の下準備

前々回と前回で以下のことをやりました。

 

mossan99-b.hateblo.jp

 

画像は以下のようにフォルダに入れています。

 

mossan99-b.hateblo.jp

テキストは以下のように取得しています。

ベースのコードをパイセンに相談

まずは、以下のプロンプトを投げます。日本語おかしいですが、多分伝わるんじゃないかと

ウィンドウでフォルダを指定して、フォルダの中にファイル名を「BeforeName」の列で取得してCSVファイルに保存、ウィンドウで、テキストファイルを選択して、行ごとにスキャンして、「AfterName」という名前の列に格納して、csvファイルに保存したい。CSVの保存先は、ウィンドウで指定したい

以下のコードがパイセンから返ってきました。

# 複数のファイル名の変更を同時に行う by mossan99

import os
import csv
from tkinter import Tk, filedialog, messagebox

# フォルダ内のファイル名を取得してCSVファイルに保存する関数
def save_filenames_to_csv(folder_path, csv_path):
    filenames = os.listdir(folder_path)
    with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['BeforeName', 'AfterName'])
        for filename in filenames:
            writer.writerow([filename, ''])
    print(f"ファイル名がCSVファイルに保存されました: {csv_path}")

# テキストファイルの内容を「AfterName」列に格納してCSVファイルに保存する関数
def update_csv_with_text(csv_path, text_path):
    with open(text_path, 'r', encoding='utf-8') as textfile:
        lines = textfile.readlines()
    
    with open(csv_path, 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        rows = list(reader)
    
    if len(lines) != len(rows) - 1:
        print("テキストファイルの行数とCSVファイルの行数が一致しません。")
        return
    
    for i, line in enumerate(lines, start=1):
        rows[i][1] = line.strip()
    
    with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerows(rows)
    print(f"CSVファイルが更新されました: {csv_path}")

# フォルダ選択ダイアログを表示してフォルダを選択する関数
def select_folder():
    root = Tk()
    root.withdraw()
    messagebox.showinfo("フォルダ選択", "ファイル名を取得するフォルダを選択してください。")
    folder_path = filedialog.askdirectory()
    root.destroy()
    return folder_path

# ファイル選択ダイアログを表示してファイルを選択する関数
def select_file():
    root = Tk()
    root.withdraw()
    messagebox.showinfo("ファイル選択", "テキストファイルを選択してください。")
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
    root.destroy()
    return file_path

# ファイル保存ダイアログを表示して保存場所を選択する関数
def select_save_location(default_filename):
    root = Tk()
    root.withdraw()
    messagebox.showinfo("保存場所選択", "CSVファイルを保存する場所を選択してください。")
    file_path = filedialog.asksaveasfilename(initialfile=default_filename, defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
    root.destroy()
    return file_path

if __name__ == "__main__":
    # フォルダを選択してファイル名をCSVファイルに保存
    folder_path = select_folder()
    if folder_path:
        csv_path = select_save_location("filenames.csv")
        if csv_path:
            save_filenames_to_csv(folder_path, csv_path)
            
            # テキストファイルを選択してCSVファイルを更新
            text_path = select_file()
            if text_path:
                update_csv_with_text(csv_path, text_path)
            else:
                print("テキストファイルが選択されませんでした。")
        else:
            print("CSVファイルの保存場所が選択されませんでした。")
    else:
        print("フォルダが選択されませんでした。")

早速実行したところ、以下のCSVができました

「.DS_Store」って、MacOSで出てくる不可視ファイルだと思いますが、これがカウントされてるようですね。これは無視するように頼んでみます。あと、ウィンドウを開いてファイルを聞く順番がおかしいので直してもらいます。

ファイル名を取得するときに「.DS_Store」は無視するようにコードを改善して

 

ウィンドウが出る順番を、フォルダの場所、テキストファイルを開く、csvを保存する、の順番にして欲しい

以下のコードが返ってきます。


# 複数のファイル名の変更を同時に行う by mossan99

import os
import csv
from tkinter import Tk, filedialog, messagebox

# フォルダ内のファイル名を取得してCSVファイルに保存する関数
def save_filenames_to_csv(folder_path, csv_path):
    filenames = [f for f in os.listdir(folder_path) if f != '.DS_Store']
    with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['BeforeName', 'AfterName'])
        for filename in filenames:
            writer.writerow([filename, ''])
    print(f"ファイル名がCSVファイルに保存されました: {csv_path}")

# テキストファイルの内容を「AfterName」列に格納してCSVファイルに保存する関数
def update_csv_with_text(csv_path, text_path):
    with open(text_path, 'r', encoding='utf-8') as textfile:
        lines = textfile.readlines()
    
    with open(csv_path, 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        rows = list(reader)
    
    if len(lines) != len(rows) - 1:
        print("テキストファイルの行数とCSVファイルの行数が一致しません。")
        return
    
    for i, line in enumerate(lines, start=1):
        rows[i][1] = line.strip()
    
    with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerows(rows)
    print(f"CSVファイルが更新されました: {csv_path}")

# フォルダ選択ダイアログを表示してフォルダを選択する関数
def select_folder():
    root = Tk()
    root.withdraw()
    messagebox.showinfo("フォルダ選択", "ファイル名を取得するフォルダを選択してください。")
    folder_path = filedialog.askdirectory()
    root.destroy()
    return folder_path

# ファイル選択ダイアログを表示してファイルを選択する関数
def select_file():
    root = Tk()
    root.withdraw()
    messagebox.showinfo("ファイル選択", "テキストファイルを選択してください。")
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
    root.destroy()
    return file_path

# ファイル保存ダイアログを表示して保存場所を選択する関数
def select_save_location(default_filename):
    root = Tk()
    root.withdraw()
    messagebox.showinfo("保存場所選択", "CSVファイルを保存する場所を選択してください。")
    file_path = filedialog.asksaveasfilename(initialfile=default_filename, defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
    root.destroy()
    return file_path

if __name__ == "__main__":
    # フォルダを選択してファイル名をCSVファイルに保存
    folder_path = select_folder()
    if folder_path:
        # テキストファイルを選択してCSVファイルを更新
        text_path = select_file()
        if text_path:
            csv_path = select_save_location("filenames.csv")
            if csv_path:
                save_filenames_to_csv(folder_path, csv_path)
                update_csv_with_text(csv_path, text_path)
            else:
                print("CSVファイルの保存場所が選択されませんでした。")
        else:
            print("テキストファイルが選択されませんでした。")
    else:
        print("フォルダが選択されませんでした。")

出力されたCSVが以下です。

うまくできた!と思ったんですが、左の「BeforeName」の並び方がおかしいですね。。。ファイルを読み出す時って、上から順番に読んでくれると勝手に思ってましたが、そうはやってくれないようです。。。というわけで、ファイルを読み出すときは、ファイル名の昇順で読むように頼みます。

フォルダからファイル名を読むときは、ファイル名の昇順で読み込むようにコードを改善

 

実行した結果が以下。

今度はうまくいったようです。よかった。。ただ、BeforeNameに「.png」のファイル拡張子までテキストに入っているので、これを改善してもらいます。。

 

BeforeNameのテキストに「.png」が入ってるので、ファイル名を取得するときは、ファイル拡張子を無視するようにコードを改善

結果が以下です。

これで大丈夫そうですね。これでファイル名を変更する準備ができたので、以下のプロンプトでパイセンに相談です。

最後にBeforeNameにあるテキストと同じテキストのファイルのファイル名をAfterNameのテキストに置き換えるようにコードを改善

 

ついに完成

以下が実行した結果です。

 

お!無事にうまくいきました!ファイル名を変えたいファイルをフォルダに入れて、テキストファイルに変更したい名前を入れれば、色々応用できそうな気がします。ファイルの数とテキストの数が一致しないときちんと動かないので注意が必要ですね。あと、ファイル名にも先頭に番号入れた方がわかりやすそうですね。せっかくコードができたので、他でも活用してみようと思います。

 

最終コードは以下です。

 

 

 

この続きを読むには
購入して全文を読む

【Python】特定のウェブページからテキストを取得

 

前回やったこと

前回は、特定のウェブページから画像を取得しました。

mossan99-b.hateblo.jp

最終目的は複数のややこしいファイル名の変更を同時に行う、ということなんですが、下準備的な作業で、特定のウェブページからテキストを取得してみます。いつものように、VSCODEGithub CopilotでAIパイセンにお伺いを立てながら😁コード書きます。

AIパイセンに聞いてみよう

以下のプロンプトでハイセンに聞きます。

特定のウェブページからテキストを取得したい

以下のコードが返ってきました。

#特定のウェブページからテキストを取得 by mossan99

import requests
from bs4 import BeautifulSoup

def get_web_text(url):
    response = requests.get(url)
    if response.status_code == 200:
        soup = BeautifulSoup(response.content, 'html.parser')
        return soup.get_text()
    else:
        return None

if __name__ == "__main__":
    url = "https://example.com"
    text = get_web_text(url)
    if text:
        print(text)
    else:
        print("Failed to retrieve the web page.")

以下のプロンプトを加えます

ウィンドウを出してテキストの保存場所を指定したい

さらに

Webページの名前をテキストファイルの名前にしたい

これから返ってきたコードを実行したところ、以下のエラーが出ました。。

  line 34, in 
safe_title = re.sub(r'[\\/*?:"<>|]', "", title)
                 ^^
NameError: name 're' is not defined. Did you forget to import 're'?

プロンプトにコピペして改善をお願いします。

モジュールをインポートするのを忘れていたため、エラーが発生しています。reモジュールをインポートし、コードを修正します。

忘れてたんかい!ということで、修正のコードが返ってきました

# 特定のウェブページからテキストを取得 by mossan99

import requests
from bs4 import BeautifulSoup
from tkinter import Tk, filedialog, messagebox
import re  # reモジュールをインポート

def get_web_text_and_title(url):
    response = requests.get(url)
    if response.status_code == 200:
        soup = BeautifulSoup(response.content, 'html.parser')
        title = soup.title.string if soup.title else "untitled"
        text = soup.get_text()
        return text, title
    else:
        return None, None

def save_text_to_file(text, file_path):
    with open(file_path, 'w', encoding='utf-8') as file:
        file.write(text)

def select_save_location(default_filename):
    root = Tk()
    root.withdraw()
    messagebox.showinfo("保存場所選択", "テキストを保存する場所を選択してください。")
    file_path = filedialog.asksaveasfilename(initialfile=default_filename, defaultextension=".txt", filetypes=[("Text files", "*.txt")])
    root.destroy()
    return file_path

if __name__ == "__main__":
    url = "https://mossan99-b.hateblo.jp/entry/2025/02/05/171251"
    text, title = get_web_text_and_title(url)
    if text:
        # ファイル名に使用できない文字を置き換え
        safe_title = re.sub(r'[\\/*?:"<>|]', "", title)
        save_path = select_save_location(f"{safe_title}.txt")
        if save_path:
            save_text_to_file(text, save_path)
            print(f"テキストが正常に保存されました: {save_path}")
        else:
            print("保存場所が選択されませんでした。")
    else:
        print("ウェブページの取得に失敗しました。")

実行して、保存されたテキストが以下です。

えっっw。タイトルの文字しか入ってない。。。聞き方がおかしかったんですかね。次のように聞き直します。

ブログのタイトルは消去して、画像データのキャプションのテキストを取得してほしい。

コードのコメントもついでに追加してもらって、返ってきたのが以下です。

# 特定のウェブページからテキストを取得 by mossan99

import requests
from bs4 import BeautifulSoup
from tkinter import Tk, filedialog, messagebox
import re  # reモジュールをインポート

# 指定されたURLから画像データのキャプションを取得する関数
def get_image_captions(url):
    response = requests.get(url)
    if response.status_code == 200:
        soup = BeautifulSoup(response.content, 'html.parser')
        # 画像のalt属性をキャプションとして取得
        captions = [img['alt'] for img in soup.find_all('img') if 'alt' in img.attrs]
        return captions
    else:
        return None

# 取得したテキストデータを指定されたファイルパスに保存する関数
def save_text_to_file(text, file_path):
    with open(file_path, 'w', encoding='utf-8') as file:
        file.write(text)

# ファイル保存ダイアログを表示して保存場所を選択する関数
def select_save_location(default_filename):
    root = Tk()
    root.withdraw()
    messagebox.showinfo("保存場所選択", "テキストを保存する場所を選択してください。")
    file_path = filedialog.asksaveasfilename(initialfile=default_filename, defaultextension=".txt", filetypes=[("Text files", "*.txt")])
    root.destroy()
    return file_path

if __name__ == "__main__":
    url = "https://mossan99-b.hateblo.jp/entry/2025/02/05/171251"
    captions = get_image_captions(url)
    if captions:
        # キャプションを改行で結合してテキストにする
        text = "\n".join(captions)
        # ファイル名に使用できない文字を置き換え
        safe_title = re.sub(r'[\\/*?:"<>|]', "", "image_captions")
        save_path = select_save_location(f"{safe_title}.txt")
        if save_path:
            save_text_to_file(text, save_path)
            print(f"テキストが正常に保存されました: {save_path}")
        else:
            print("保存場所が選択されませんでした。")
    else:
        print("ウェブページの取得に失敗しました。")

実行して出来上がったテキストファイルが以下。

うーんうまくいかない。。。。聞き方をどうしよう。ウェブページを右クリックして「検証」を押して、コードの中身を見てみます。

 

 

「figure class」の「title」のテキストが取得できればOK、となりそうですね。以下のように、聞き直します。

figure classのtitleのテキストのみを取得できるようにコードを改善して欲しい

以下が返ってきました

# 特定のウェブページからテキストを取得 by mossan99

import requests
from bs4 import BeautifulSoup
from tkinter import Tk, filedialog, messagebox
import re  # reモジュールをインポート

# 指定されたURLからfigureクラスのtitle属性を持つ要素のテキストを取得する関数
def get_figure_titles(url):
    response = requests.get(url)
    if response.status_code == 200:
        soup = BeautifulSoup(response.content, 'html.parser')
        # figureクラスのtitle属性を持つ要素のテキストを取得
        titles = [figure['title'] for figure in soup.find_all('figure') if 'title' in figure.attrs]
        return titles
    else:
        return None

# 取得したテキストデータを指定されたファイルパスに保存する関数
def save_text_to_file(text, file_path):
    with open(file_path, 'w', encoding='utf-8') as file:
        file.write(text)

# ファイル保存ダイアログを表示して保存場所を選択する関数
def select_save_location(default_filename):
    root = Tk()
    root.withdraw()
    messagebox.showinfo("保存場所選択", "テキストを保存する場所を選択してください。")
    file_path = filedialog.asksaveasfilename(initialfile=default_filename, defaultextension=".txt", filetypes=[("Text files", "*.txt")])
    root.destroy()
    return file_path

if __name__ == "__main__":
    url = "URL" # ここに対象のURLを入力してください
    titles = get_figure_titles(url)
    if titles:
        # タイトルを改行で結合してテキストにする
        text = "\n".join(titles)
        # ファイル名に使用できない文字を置き換え
        safe_title = re.sub(r'[\\/*?:"<>|]', "", "figure_titles")
        save_path = select_save_location(f"{safe_title}.txt")
        if save_path:
            save_text_to_file(text, save_path)
            print(f"テキストが正常に保存されました: {save_path}")
        else:
            print("保存場所が選択されませんでした。")
    else:
        print("ウェブページの取得に失敗しました。")

実行した結果が以下です

 

お!うまくいきました。テキストを取得した順番も問題なさそうですが、前回画像を取得したときに順番がバラバラになることもあったので、修正を追加したいと思います。あと、テキストの先頭に、カウントもつけるようにパイセンに頼んでみます。

Webページの上から順番にテキストを取得して、さらに、各テキストの頭に「0000_」がフォーマットのカウンタを追加

実行した結果が以下

よし!無事にうまくいきました。これで準備は良さそうですね。次回は、これらを組み合わせファイル名の変更をやってみようかなと。

 

 

最終コードは、以下に書いておきます。

 

この続きを読むには
購入して全文を読む

【Python】特定のウェブページから画像を取得

 

今回は、特定のURLから画像データを取得してみたいと思います。VSCodeGithub Copilotを使っていきます。

 

どのプログラムを使うのか

いわゆるスクレイピングというやつだと思いますが、Pythonを使えばできるようです。早速ですが、パイセンに聞いてみます。

特定のURLのページから画像を取得したい

以下のコードが返ってきました

import os
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from urllib.request import urlretrieve

# 画像を取得するURLを指定
url = 'https://example.com'  # ここに対象のURLを入力してください

# ページの内容を取得
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# 画像のURLを抽出
img_tags = soup.find_all('img')
img_urls = [urljoin(url, img['src']) for img in img_tags if 'src' in img.attrs]

# 画像を保存するディレクトリを作成
os.makedirs('images', exist_ok=True)

# 画像をダウンロードして保存
for img_url in img_urls:
    img_name = os.path.basename(img_url)
    img_path = os.path.join('images', img_name)
    urlretrieve(img_url, img_path)
    print(f'{img_name} を保存しました。')

print('すべての画像をダウンロードしました。')    

コードの改善

保存するときに、ウィンドウを出して場所を指定したいので、以下のプロンプトを追加。

保存する場所はウィンドウを出して指定したい

以下が返答

import os
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from urllib.request import urlretrieve
from tkinter import Tk, filedialog

# 画像を取得するURLを指定
url = 'https://example.com'  # ここに対象のURLを入力してください

# ページの内容を取得
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# 画像のURLを抽出
img_tags = soup.find_all('img')
img_urls = [urljoin(url, img['src']) for img in img_tags if 'src' in img.attrs]

# Tkinterのルートウィンドウを作成して隠す
root = Tk()
root.withdraw()

# 画像を保存するディレクトリを選択するダイアログを表示
save_dir = filedialog.askdirectory(title="画像を保存するディレクトリを選択")
if not save_dir:
    print("保存先が選択されませんでした。")
    exit()

# 画像をダウンロードして保存
for img_url in img_urls:
    img_name = os.path.basename(img_url)
    img_path = os.path.join(save_dir, img_name)
    urlretrieve(img_url, img_path)
    print(f'{img_name} を保存しました。')

print('すべての画像をダウンロードしました。')

コードを説明してくれます

 

このコードは以下の手順で動作します:

指定されたURLのページ内容を取得します。
BeautifulSoupを使ってHTMLを解析し、すべてのタグを見つけます。
各タグから画像のURLを抽出し、完全なURLに変換します。
tkinterを使用して保存先のディレクトリを選択するダイアログを表示します。
画像をダウンロードし、選択したディレクトリに保存します。
必要に応じて、URLやその他の設定を変更してください。
  

 

コードを試してみる

ウェブページは以下を準備したのでこれを使っていきます。

mossan99-b.hateblo.jp

 

URLをいれて実行したところ、以下のエラーが出ました。

line 2, in module
import requests
ModuleNotFoundError: No module named 'requests'

モジュールがインストールされていないため、このエラーが発生しています。以下のコマンドを使用して、requestsモジュールをインストールしてください。と、返ってきて、コマンドも教えてくれるので「pip install requests」を入れて、必要なライブラリをインストールして再実行。うまく動いて、画像を保存できました。



Webページの上から順にダウンロードしてくれてると勝手に思ってたんですが、よく見ると順番がバラバラのようです。上から順に画像を取得して、ファイル名の先頭にカウントをつけるようにパイセンに頼んでみます。

 

上から順番にDLするように指定

 
Webページの上から順に画像を取得して、ファイル名の先頭に「000000_」のフォーマットの数字を追加。
    

 

以下のコードが返ってきました

#特定のウェブページから画像を取得 by mossan99

import os
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from urllib.request import urlretrieve
from tkinter import Tk, filedialog

# 画像を取得するURLを指定
url = 'https://mossan99-b.hateblo.jp/entry/2025/02/05/171251'  # ここに対象のURLを入力してください

# ページの内容を取得
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# 画像のURLを抽出
img_tags = soup.find_all('img')
img_urls = [urljoin(url, img['src']) for img in img_tags if 'src' in img.attrs]

# Tkinterのルートウィンドウを作成して隠す
root = Tk()
root.withdraw()

# 画像を保存するディレクトリを選択するダイアログを表示
save_dir = filedialog.askdirectory(title="画像を保存するディレクトリを選択")
if not save_dir:
    print("保存先が選択されませんでした。")
    exit()

# 画像をダウンロードして保存
for index, img_url in enumerate(img_urls):
    img_name = os.path.basename(img_url)
    formatted_index = f"{index:06d}"  # 000000形式の数字を作成
    new_img_name = f"{formatted_index}_{img_name}"
    img_path = os.path.join(save_dir, new_img_name)
    urlretrieve(img_url, img_path)
    print(f'{new_img_name} を保存しました。')

print('すべての画像をダウンロードしました。')

実行した結果、以下のように出力されました

うまく出力されています!しかし、余分なデータにも番号がついちゃってますね。。。欲しいのは、PNGファイルだけなので、PNGファイルだけ取得するように調整してみます。

png形式のファイルだけ取得するように改善して

パイセンから返事が返ってきます。

コードを実行したら、以下のように出力されました。



無事に出力されました!ひと安心。

 

やっぱり細かいところが気になる

欲を言うと、ファイル名をWebページの画像の説明文に置き換えたいんですよね。これは次回、やろうと思います。

 

 

最終コードは以下に書いておきます。

 

この続きを読むには
購入して全文を読む