TECH PLAY

miracleave株式会社

miracleave株式会社 の技術ブログ

52

こんにちは!馬場です。 私はエンジニアとしての経験がまだ浅く、学ぶことが多い毎日です。 今回は、Spring Bootを使用してシンプルなX(旧Twitter)風のポストアプリケーションを作成する手順を、開発メモとしてブログにまとめていきます。このシリーズでは、環境構築から始まり、各機能の実装までのプロセスを詳しく解説していきます。全3回のシリーズとして、以下の内容を予定しています。 環境構築編 :開発環境のセットアップ方法を詳しく説明します。 ログイン機能編 :ユーザー認証とログイン機能の実装について解説します。 ポスト機能編 :基本的なポスト機能の実装について解説します。 環境構築編のゴール この「環境構築編」では、以下のゴールを目指します。 開発環境の準備 :必要なツールとソフトウェアのインストール Spring Bootプロジェクトの作成 :基本的なSpring Bootプロジェクトの作成と設定 依存関係の設定 :プロジェクトで使用するライブラリやフレームワークの設定 簡単なアプリケーションの起動 :作成したSpring Bootアプリケーションをローカルで起動して確認 これらのステップを完了することで、次の「ログイン機能編」にスムーズに進むための基盤が整います。それでは、早速始めましょう。 環境構築 必要なツールのインストール まず、Spring Bootの開発に必要なツールをインストールします。以下のツールが必要です。 JDK(Java Development Kit) :Java開発に必要なキットです。バージョン17を使用します。 IntelliJ IDEA :Javaの統合開発環境(IDE)です。Community Editionで十分です。 MySQL :データベースとして使用します。(本番環境用で使用) 1 JDKインストールJDKのインストール Oracle公式 からJDK 17をダウンロードしてインストールします。 環境変数 JAVA_HOMEを設定し、JDKのインストールディレクトリを指定します。 2 IntelliJ IDEAのインストール JetBrainsの JetBrainsの公式サイト からIntelliJ IDEA Community Editionをダウンロードしてインストールします。 インストール後、IDEを起動し、初期設定を行います。 必要な方は設定のプラグインから日本語言語化パックをインストールします。 3 MySqlのインストール 公式サイト からMySQLをダウンロードしてインストールします。 mysqlに接続してデータベースを作成する。 Spring Bootプロジェクトの作成 IntelliJ IDEAを起動し、「新規プロジェクト」を選択します。 必要なプロジェクト設定を入力します: ディレクトリ構造 Spring Bootプロジェクトの基本的なディレクトリ構造を確認しましょう。 テスト用( src/test )と本番環境用( src/main )ディレクトリの配置します。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } css Post/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── org.example/ │ │ │ │ └─controller/ │ │ │ │ └─model/ │ │ │ │ └─repository/ │ │ │ └──PostApplication.java │ │ └── resources/ │ │ └── application.properties │ └── test/ │ ├── java/ │ │ └── org.example/ │ │ │ └─controller/ │ │ │ └─model/ │ │ │ └─repository/ │ │ └──PostApplicationTests.java │ └── resources/ │ └── application-test.properties ├── build.gradle.kts └── gradlew プロジェクトの設定 テスト用設定 (application-test.properties) .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } application-test.properties # H2 Database configuration spring.h2.console.enabled=true spring.h2.console.path=/h2-console # DataSource Configuration - H2 Database (file-based) spring.datasource.url=jdbc:h2:/data/db/testdb;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect spring.datasource.initialization-mode=always # Hibernate Configuration spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true # Logging Configuration logging.level.org.example.repository=DEBUG logging.level.org.springframework.security=DEBUG # Thymeleaf Configuration spring.mvc.hiddenmethod.filter.enabled=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html spring.thymeleaf.cache=false # DevTools Configuration spring.devtools.livereload.enabled=true server.error.path=/error spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp 本番環境用設定 (application.properties) .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } application.properties # DataSource Configuration - MySQL Database (for production) spring.datasource.url=jdbc:mysql://localhost:3306/postdb?serverTimezone=UTC spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.username=tomoki spring.datasource.password=posts ing.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect # Hibernate Configuration spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=false # Logging Configuration logging.level.org.springframework=INFO logging.level.com.example=INFO # Thymeleaf Configuration spring.mvc.hiddenmethod.filter.enabled=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html 主な変更点 1 データベースの種類 テスト用: H2インメモリデータベースを使用。 spring.datasource.url , spring.datasource.driverClassName などの設定がH2用になっています。 本番環境用: MySQLデータベースを使用。 spring.datasource.url , spring.datasource.driverClassName , spring.datasource.username , spring.datasource.password などの設定がMySQL用になっています。 2 Hibernateの設定 テスト用: データベーススキーマを起動時に作成し、シャットダウン時に削除するように設定 ( spring.jpa.hibernate.ddl-auto=create-drop ) 本番環境用: 既存のデータベーススキーマを更新するように設定 ( spring.jpa.hibernate.ddl-auto=update ) 3 SQLの表示 テスト用: SQL文をコンソールに表示する設定( spring.jpa.show-sql=true )。 本番環境用: SQL文の表示をオフにする設定( spring.jpa.show-sql=false )。 4 ログ設定 テスト用: リポジトリのデバッグログを有効にする設定 ( logging.level.org.example.repository=DEBUG ) 本番環境用: スプリングとアプリケーションのログレベルをINFOに設定 ( logging.level.org.springframework=INFO , logging.level.com.example=INFO ) 依存関係の設定 1 IntelliJ IDEAがプロジェクトを生成した後、 build.gradle.kts ファイルを開いて、次のように設定します: .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } build.gradle.kts plugins { id("java") id("org.springframework.boot") version "3.2.2" id("io.spring.dependency-management") version "1.1.5" } group = "org.example" version = "1.0-SNAPSHOT" java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } repositories { mavenCentral() } dependencies { // テスト用の依存関係 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") // LombokとSpring Boot DevTools compileOnly("org.projectlombok:lombok") // Lombok:ボイラープレートコードを減らすため annotationProcessor("org.projectlombok:lombok") developmentOnly("org.springframework.boot:spring-boot-devtools") // Spring Boot DevTools:ホットスワップや開発ツールのため testImplementation("org.springframework.boot:spring-boot-starter-test") // Spring Boot Starter Test:Spring Bootのテストをサポート // Spring Boot WebとThymeleaf implementation("org.springframework.boot:spring-boot-starter-web") // Spring Boot Web Starter:Webアプリケーションを構築するため implementation("org.springframework.boot:spring-boot-starter-thymeleaf") // Thymeleaf:サーバーサイドテンプレートエンジン implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.5.3") // Thymeleaf Layout Dialect:レイアウトとフラグメント機能をサポート implementation("org.webjars:jquery:3.5.0") // jQuery:JavaScriptユーティリティ implementation("org.webjars:bootstrap:4.4.1-1") // Bootstrap:レスポンシブデザインとスタイリングのため // MySQLデータベース(本番環境用) runtimeOnly("mysql:mysql-connector-java:8.0.28") // MySQL Connector:MySQLデータベースに接続するため // H2データベース(テスト用) testRuntimeOnly("com.h2database:h2") // H2データベース:テスト用のインメモリデータベース // Spring Boot Starter Data JPA implementation("org.springframework.boot:spring-boot-starter-data-jpa") // Spring Data JPA:JPAを使用してリレーショナルデータベースと対話するため // javax.persistenceをjakarta.persistenceに置き換え implementation("jakarta.persistence:jakarta.persistence-api:3.1.0") // Jakarta Persistence API:JPA API仕様 // JetBrainsアノテーションを追加 implementation("org.jetbrains:annotations:24.0.1") // JetBrainsアノテーション:null安全性のためのアノテーション implementation("org.springframework.boot:spring-boot-starter-security") // Spring Security:認証と認可のため implementation("org.springframework.boot:spring-boot-starter-jdbc") // Spring JDBC:JDBCサポートのため } tasks.withType { systemProperty("spring.profiles.active", "test") } tasks.test { useJUnitPlatform() systemProperty("spring.profiles.active", "test") reports { junitXml.required.set(true) html.required.set(true) } } tasks.register("printRuntimeClasspath") { doLast { println(sourceSets["main"].runtimeClasspath.asPath) } } 2 ↓右上に「スクリプト構成のロード」と「Gradleの変更を読み込む」が出てくるので選択 アプリケーションの起動 1 ポストアプリのテストを実行する テストクラスの作成 PostApplicationTestsクラスを作成し、Spring Bootアプリケーションのテストを実行します。 このクラスには、 @SpringBootApplication アノテーションが付いており、Spring Bootアプリケーションのエントリーポイントとして機能します。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } PostApplicationTests.java package org.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class PostApplicationTests { public static void main(String[] args) { SpringApplication.run(PostApplicationTests.class, args); } } 2 プロジェクトの実行確認 IntelliJ IDEAの右にある「Gradle」から「bootTestRun」を右クリックして実行します。 コンソールを確認し「bootTestRun」プロジェクトは正常に起動されていることを確認する。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } console 18:34:56: 'bootTestRun --scan --stacktrace' を実行中... Starting Gradle Daemon... 2024-07-07T18:35:22.273+09:00 WARN 6440 --- [ main] org.hibernate.orm.deprecation : HHH90000025: MySQL8Dialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default) 2024-07-07T18:35:22.274+09:00 WARN 6440 --- [ main] org.hibernate.orm.deprecation : HHH90000026: MySQL8Dialect has been deprecated; use org.hibernate.dialect.MySQLDialect instead 2024-07-07T18:35:22.674+09:00 INFO 6440 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) 2024-07-07T18:35:22.681+09:00 INFO 6440 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-07-07T18:35:22.719+09:00 WARN 6440 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2024-07-07T18:35:23.100+09:00 INFO 6440 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '' 2024-07-07T18:35:23.113+09:00 INFO 6440 --- [ main] org.example.PostApplicationTests 3「 http://localhost:8080 」に接続 localhostの接続しようとすると下記のエラーが発生してしまいます。 Spring BootのWhitelabel Error Pageの解決方法 Whitelabel Error Page は、リクエストされたURLに対する明示的なマッピングがアプリケーションに存在しない場合に表示されます。このエラーページは、特に開発環境で便利ですが、本番環境では独自のエラーページを設定したい場合があります。 解決方法 1 コントローラの作成 まず、URLマッピングを行うコントローラを作成します。例えば、 / にマッピングされたエンドポイントを持つコントローラを作成します。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } HomeController package org.example.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { @GetMapping("/home") public String home() { return "home"; // templates/home.html に対応 } } /home にアクセスすると home という名前のテンプレートを返します。テンプレートファイル home.html を src/main/resources/templates/posts フォルダに作成します。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } home.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ホーム</title> </head> <body> <h1>ホーム</h1> <p>ようこそ、ポストアプリケーションへ!</p> </body> </html> 2 エラーページのカスタマイズ 本番環境では、独自のエラーページを設定することが推奨されます。Spring Bootでは、カスタムエラーページを簡単に設定できます。 まず、 src/main/resources/templates フォルダに error フォルダを作成し、その中にエラーページテンプレートを配置します。 .code-container { margin-bottom: 20px; } .filename { background-color: #1e1e1e; /* ダークグレーの背景 */ color: #ffffff; /* 白い文字 */ padding: 5px 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: Consolas, "Courier New", monospace; } pre { background-color: #2d2d2d; /* 黒い背景 */ color: #f8f8f2; /* 白い文字 */ padding: 10px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; overflow-x: auto; font-family: Consolas, "Courier New", monospace; margin: 0; } code { font-family: inherit; color: inherit; } error.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ページが見つかりません</title> </head> <body> <h1>404 - ページが見つかりません</h1> <p>お探しのページは存在しません。URLを確認してください。</p> <a href="/">ホームに戻る</a> </body> </html> 上記設定できたら再ビルドし、「 http://localhost:8080 」に接続します。 下記のように問題なく接続することができました! まとめ 今回のブログでは、Spring Bootを使ってポストアプリを作成するための開発環境の構築方法について説明しました。JDK、IntelliJ IDEA、MySQLのインストールから、Spring Bootプロジェクトの作成、必要な依存関係の追加、プロジェクトのビルドと実行までの手順を簡単に解説しました。次回からは、ログイン機能と基本的なポストの投稿機能を実装していきますので、お楽しみに! The post Spring Bootでポストアプリを作成してみる【環境構築編】 first appeared on miracleave Tech Blog .
アバター
Dify連載2回目の記事です。 前回 に引き続き、つきみがお送りいたします。 さて、前回ではDifyの初期設定とLLMのセットアップをしましたので、次はDifyを使い、簡単にAIを搭載したサービスを作っていきます。 そもそもDifyで何ができるのか? Difyは高度なプログラミングスキルや、応用的な数学の知識をあまり必要としないで、AIを使って自分好みにカスタマイズすることができます。 例えば、次のものを作ることができます。 チャットボット テキストジェネレーター エージェント ワークフロー チャットボットを作ってみる 今回は、「弊社の従業員を紹介するチャットボット」を作っていきます。 管理画面に移って作業を進めていきましょう。 デフォルト設定の場合は、 http://127.0.0.1/ にアクセスすることで、スタジオの画面が表示されます。Difyの初期設定とログインが終わっていない方は実施ください。 スタジオの画面が開かれたら、左上の「最初から作成」を選択し、「チャットボット>基本」を選択した上で、各種項目を入力していきましょう。 入力内容が決まったら、「作成する」をクリックして、進みます。 前回、デフォルトで使用されるLLM(AIモデル)を設定しました。そのため、右上に「GPT-4o」などと表示されていると思います。表示されていたら適切に初期設定が完了しています。 ただ単純に、「何もカスタマイズしなくていいから、ChatGPTを導入したい」という場合はすでにこの時点で設定が完成しています。試しに右半分の画面の「デバッグとプレビュー」の下にあるテキストボックスになにか打ち込んでみましょう。すると、質問に合わせた回答がされます。 ただ、弊社ではよりAIを活用するために、内部情報と組み合わせてチャットボットの開発を行っています。今回作成するものは「従業員の紹介をするチャットボット」です。 そこで、登場するのが 「 RAG 」 という技術です。 RAG とは? RAG(ラグ、Retrieval-Augmented Generation) は、一般的に次のような意味を持っています。 Retrieval-Augmented Generation (RAG) は、大規模言語モデル(LLM)によるテキスト生成に、外部情報の検索を組み合わせることで、回答精度を向上させる技術のこと。 「検索拡張生成」、「取得拡張生成」などと訳されます。外部情報の検索を組み合わせることで、大規模言語モデル(LLM)の出力結果を簡単に最新の情報に更新できるようになる効果や、出力結果の根拠が明確になり、事実に基づかない情報を生成する現象(ハルシネーション)を抑制する効果などが期待されています。 (読み:ラグ) 野村総合研究所 用語解説 より – 2024/06/18 閲覧 つまり、「この事柄は、こういう意味だよ」というネットに転がっていない情報を人間がAI(LLM)に対して与えることによって、より専門的な知識に対して憶測ではなく、できるだけ事実に基づいて回答させるというのが、RAGの役割です。 例えば、「miracleaveの経費精算ってどうするの?」という質問に対して、パブリックな情報しか知らない「GPT-4o」は正確には回答できません。これは、GPT-4oがmiracleaveの内部情報や経費精算に関するプライベートな情報を持ち合わせていないためです。 人が事前に経費精算に関する情報を用意し、GPT-4oがそれらの情報を取り扱えるようになれば、プライベートな問題でもなるべく正確に答えてくれるようになるということです。 RAGに使用するデータを用意する では、RAGで使用するデータを用意しましょう。 今回の場合簡単に自己紹介の情報を集めたいと思うので、弊社のテックブログで自己紹介を設定している従業員の皆様の情報をまずは収集しました。 (軽く書いたコードのため乱雑なのと、CSMとESな書き方が混在しているのはご容赦ください…) 従業員一覧の取得部(Node.js) const fs = require('fs'); (async function () { async function wait(second) { return new Promise(resolve => setTimeout(resolve, second)); }; let totalData = [] for (let i = 1; ; i++) { const data = await (await fetch(`{ブログのURL}/wp-json/wp/v2/users?orderby=id&page=${i}`, { headers: { "Authorization": "[ここに認証情報]" } })).json() const returnData = data.filter((data) => { if (data.description === "") return false return true }).map((data) => { return { name: data.name, description: data.description.replace("\r\n", "\n") } }) console.log(returnData) totalData = [...returnData, ...totalData] await wait(2000) if (data.lenght !== 10) break; } console.log(totalData) const header = 'name, description\n'; const csvData = totalData.map(item => `${item.name}, ${item.description}`).join('\n'); const csvContent = header + csvData; fs.writeFile('output.csv', csvContent, 'utf8', (err) => { if (err) { console.error('Error writing to file', err); } else { console.log('CSV file has been saved.'); } }); }()); このソースコードを実行することによって、次のようなcsvファイルがフォルダーに作成されました。 name, description miracleave, miracleaveはワクワクする最高のITサービスをユーザーに提供するテクノロジー集団です。 「ITでワクワクできる未来へ」をミッションに掲げ、楽しいを創り出す組織から、お客様に感動を与えるようなサービスを届けること、そして、新たな挑戦をする人をデジタルコンテンツの力で後押し、幸せな未来を作っていきたいと考えています。 木村, ブライダル業界 → 2021年9月 miracleave に転職 未熟者ですが、よろしくお願いいたします! 甘いもの大好きすぎる。。 長田, miracleave初期メンバー。 コロナで機会が激減しましたがライブやフェスに行くのが好きです。 竹村, 2021年2月にmiracleaveにジョインしました。 現在はPythonとDjangoで開発しています。 大友, AWS資格取得に向けて絶賛勉強中! S.S, ゲーム好きプログラマ。 2021年12月よりmiracleaveに入社しました。 次は、作成されたファイルをDifyにアップロードをします。 RAGのために作ったファイルをアップロードする 上のヘッダーから、ナレッジに移動し、左上の「知識を作成」をクリックします。 そうしたら、テキストファイルからインポートを選択した状態で、ファイルをアップロードしましょう。 (今回の場合は先ほど作成した、弊社のテックブログのデータをアップロードします) 次へを押すと、次のような画面になります。 今回の場合初めての人を想定しているため、デフォルトの選択肢のまま進みます。 (検索設定に再ランクモデルと表示されていますが、これは次回触れます。ぜひお待ちください。) 設定を終わらせ、次に進むと以下のような画面になります。 ここまでで、RAGの準備完了です。 動作するか検証しよう ドキュメントに移動し、左のナビゲーションバーから真ん中の「検索テスト」に移動し、ソーステキストというテキストボックスの右上の設定を「全文検索」にしてみてください。 (オプションとりあえずデフォルトのままで大丈夫です。) 試しに「miracleaveってなに?」と聞いてみましょう。 全文検索の場合 おや?表示されませんでした。 ここでいう、全文検索とは「miracleave」「なに」といった単語単位で一致するものを検索します。今回、この単語に一致する文章が存在しないがために発生します。 試しにもう一つの検索手法である、ベクトル検索を試してみましょう。 ベクトル検索の場合 検索結果が表示されましたね。なぜ表示されたのでしょうか? 簡単に言えば私が聞いた文章を、言語モデルがベクトル化(Embedding)してくれます。事前にすべての文字列は言語モデルによってベクトル化が済んでおり、似ているコンテンツは座標上で近いところのベクトルとして保存されています。 私が「miracleaveってなに?」と聞いた場合、この文章をベクトル化し、そのベクトルを元に近いベクトルのデータを探します。検索結果が先ほどの全文検索と違う理由となります。 質問文章を元に近いデータを探る方法は第一回にも軽く触れたコサイン類似度を使いますが、それらの知識がなくても代わりにDifyがやってくれます。非常に便利ですね。 この辺りの仕組みは「ベクトル検索 コサイン類似度」などと検索することでより深い理解を得られます。ぜひ参照してみてください。 チャットボットに組み込む さて、Difyのスタジオに戻り、先ほど作成したアプリケーションに戻りましょう。 コンテキスト>追加 に進み、作成したナレッジ(今回の場合は output.csv )を選択して追加しましょう。 さて、これで準備は整いました。 続いて、「木村さんってどんな人?」と質問してみましょう。 元データ(自己紹介文) 木村, ブライダル業界 → 2021年9月 miracleave に転職 未熟者ですが、よろしくお願いいたします! 甘いもの大好きすぎる。。 AIの返信(元データを元に返信した場合) 木村さんはブライダル業界から転職してきて、2021年9月にmiracleaveに入社しました。まだ未熟者だとご本人は言っていますが、甘いものが大好きな一面もあります。よろしくお願いいたします! 完璧な木村さんの紹介が取り出せました。 まとめ いかがだったでしょうか? 今回は、Difyを使ったRAGの構築をしてみました。その中で、全文検索やベクトル検索といった事柄を扱いました。皆様の理解の助けになれば幸いです。 番外編 AIの文章は、どこか堅苦しさが見られます。もうちょっと気前のいい、ラフに話しかけられるようなAIを作っていきましょう。 これは、ChatGPTでよく言われる「プロンプトエンジニアリング」の分野に入っていきます。この意味は、プロンプトを日本語でどれだけAIにわかりやすく書くかです。気になる人はインターネットで調べてみてください。 さて、今回は気分で大阪のおばちゃんをAIに演じてもらいます。今回は番外編で深掘りしようとは考えていないので、軽くプロンプトを書きます。 プロンプトは左上のテキストボックスである「手順」から追加します。プロンプトを記載し終わったら、右側のプレビューがリロードを要求してくるため、リロードをしてみましょう。 登録が完了したら、試しに話しかけてみましょう。 今回は事前にデータを登録していない「鈴木さん」と、データが登録されている「木村さん」について聞いてみたところ、いい感じに大阪のおばちゃん風に返してくれました。まるで大阪の人情の温かみを感じます…(私は都民なので実際にこんな優しいおばちゃんが居るのかは不明ですが…) The post 【第二回】高校生が書く、生成AI基盤Dify入門 first appeared on miracleave Tech Blog .
アバター
初めまして。miracleaveでアルバイトをしております。現役高校生の「つきみ」です。 私は普段、TypeScriptをメインに個人開発でコードを書いており、Denoが最近のお気に入りです。 先輩方と比べたら若輩者ではありますが、これから一人前のエンジニアと呼ばれるまで努力して参ります。 さて、弊社では社内生成AI基盤の利活用を積極的に推進しております。今回はそのナレッジをできるだけわかりやすく落とし込み、解説をしていきます。 また、今回の記事はタイトルのもあるとおり、シリーズとなります。計3回を予定しており次の順番でお届けしていきます。 第一回 シリーズを進めるにあたっての前提知識 Difyのインストール 各種APIキーのセットアップ 第二回 チャットボットの制作 RAGの構築 第三回 Rerankを使った回答精度の向上 前提知識チェック OpenAI / GPT-4o まず、今回使うAIは米国のOpenAI社が研究・開発しているGPT-4oというものです。 最近では「ChatGPTなら聞いたことあるよ!」であったり、「書類・レポートの作成をAIに助けてもらってる!」といった使い方でご存知の方も多いかもしれませんが、今回は厳密にはChatGPTは使用しません。 ここら辺は複雑な問題になりがちですが、ChatGPTはGPT-4o、GPT-3.5といった大規模言語モデル(LLM)を使用するための一つのサービスであり、今回はそのサービスにあたるChatGPTではなく、GPT-4oを利用していきます。 Azure OpenAI Service Azure OpenAI ServiceはAI周りを取り扱う際に言われる「セキュリティ」「信頼性」「コンプライアンス」「データプライバシー」などを保証した、エンタープライズをはじめとした、多くの企業が求める機能を提供しているAzureのサービスです。 弊社は、多くのお客様のデータをお預かりしており、守秘義務を果たす必要があります。そのため、使用するAIは慎重に選定しており、データがAIの学習データとして再利用されないことが重要な観点です。 2021 年 11 月に、マイクロソフトは、Azure OpenAI Service を発表し、お客様が Azure クラウドとコンピューティングインフラに期待するセキュリティ、信頼性、コンプライアンス、データプライバシー、および、組み込み型 Responsible AI といったエンタープライズ級機能を備えた大規模生成 AI モデルのパワーを利用できるようにしました。 Azure OpenAI Service の一般提供開始 大規模かつ高度な AI モデルへのアクセスを拡大し、企業に付加価値を提供 Microsoft Japan News Center Embedding そして今回のシリーズではEmbeddingを取り扱っていく予定です。「ベクトル化」と言われる作業です。 高校生で言うと、数C(新課程の場合・旧課程は数B範囲です)で取り扱う「ベクトル」となりますが、日常用語でもベクトルという言葉は聞いたことがあるかもしれません。 文章を一つの点として巨大な地図の中に配置していきます。点の位置をベクトルと言います。そのとき、点と点が近ければ関連性の高い事柄ですし、逆に遠ければ関連性の低いものとしてみなします。 文章を与えたときに地図上での点の位置「ベクトル」を返してくれる。それがEmbeddingと言われる技術です。 参考: 東京書籍 2022年4月からの新課程(数学)対応について Rerank 最後の用語としてお伝えするのが、Rerank(リランク)です。検索をした際に検索結果を最適な順に並ばせる技術のことを指します。特に、このシリーズでは、米国のCohere社が提供するRerankのモデルを使用します。 例えば公式サイトから引用すると「Where is NYC located?」という質問に対して、基本的には「Where is NYC(New York City) located?」と解釈できるのに対して、全文検索では「NYC」の部分と似ているということで「NYC Media」が出てきてしまうかもしれません。 このような省略名称が検索文字列に入っていたとしても適切に検索結果を返答するための言語モデルが、Rerankです。 参考: https://cohere.com/rerank Difyとは? ここまでで、前提知識をお伝えしました。では、ここからDifyの説明に入っていきたいと思います。 Difyとは複数のAIを組み合わせてアプリケーションを作ることができるツールです。すごく抽象的な解説になりましたが、これから具体的に説明していきます。 例えば、Difyではベクトル検索の機能が標準で入っていますが、もしDifyがなければ、 「ベクトル検索のためのデータベースを用意して、ベクトル検索をかけて、Rerankさせてあげて…」といった複数の手段をすべてソースコードに落とし込むコーディングスキルが必要になり、「コサイン類似度を調べて〜…」と言った数学の応用知識も求められます。 Difyは、それを「ウェブから簡単にできるようにした」という強みに加えて「オープンソース」という太っ腹さが感じられます。私も実際に触ってみましたが、用語の理解や使用方法さえ理解すれば誰でもでもできるほど簡単なものでした。 恐れる必要はありません、次に行きましょう。 Difyのインストール・設定 Difyを始めるにあたって、今回の記事では主に次のものを使用していきます。 Docker & Docker Compose Azure OpenAI Service API Key GPT-4o text-embedding-3-large DALL-E-3 TTS (Text to Speach) Whisper 開発環境は、私はM1 MacBookを使用しておりますが、適時ご自身の端末に合わせて調整ください。 Difyのダウンロード・実行 Difyのダウンロードと実行方法について説明していきます。この作業は、Difyのソースコードをダウンロード、Docker Composeによって立ち上げるだけです。 # ダウンロード $ git clone https://github.com/langgenius/dify.git # Up Docker Compose on background $ cd dify/docker $ docker compose up -d エンジニアのみなさんであれば、「えっ、これだけ?」と感じるかもしれません。これだけで、Difyを立ち上げることができました。 次からはDifyでLLMの設定を進めていきます。 参考: https://docs.dify.ai/getting-started/install-self-hosted/docker-compose Difyの初期設定を進める 登録が完了すると、管理画面にアクセスするためのURLがコンソールに出力されます。 デフォルトでは、次のようなURLになります。 http://localhost 最初に管理者アカウントの作成が求められるので登録します。ログインまで終わらせるとダッシュボードが出てきます。 右上のユーザーアイコンをクリックし、設定>ワークススペース>モデルプロバイダーに行きましょう。 自身の使っているモデルプロバイダーを選択し、セットアップを表示に従って進むとこのような画面になります。 各種キーの登録が終われば、モデルプロバイダー設定の右上にある「システムモデル設定」を設定できます。そこで各種使用したいモデルを指定するようにしてください。 続いて、Azure DALL-E-3の設定をしていきます。 Azure OpenAI Serviceをお使いの場合は「DALL-E」ではなく、「Azure DALL-E」をお使いするようにご注意ください。 「認証する」をクリックし、必要な情報を入力すれば次のような画面になります。 参考: 公式ドキュメント まとめ ここまででDifyを使うための前提知識の学習、Difyのインストール、DifyへのLLMの設定を行ってきました。スムーズに進めたのではないでしょうか? 次回は、設定したLLMを使って、簡単なチャットボットを作っていきたいと考えております。次回もぜひ購読をよろしくお願いします。 The post 【第一回】高校生が書く、生成AI基盤Dify入門 first appeared on miracleave Tech Blog .
アバター
※本記事は2023年までSEOをまとめた内容となります。  SEOの仕組みは定期的に変わるため最新の仕組みでは無い表現も含まれることご了承ください。 こんにちは。さいとうです。 「SEO対策」という言葉を耳にする機会は多いのではないでしょうか。 しかし、「いったい何ものなの?」だったり、「何をすればいいの?」と思う方も少なくないと思います。 この記事では、「SEO対策=白背景に白文字をぶち込む」という古代の認識を持っていた自分が、認識改め最新のSEO対策についてまとめた内容になっています。 普段SEOに関わりがない方でも、検索エンジン(主にGoogle)がどういった観点で結果を表示させているのかについて少しでも、なるほど!という発見があっていただければ幸いです! 検索上位表示とクリック率について 〜そもそもなぜ「SEO対策」?〜 この記事の中ですでに5回の「SEO対策」という単語を使ってしまいましたが、「そもそもなぜそんな対策が必要なのか?」についてさらっと記載したいと思います! 結論としては、「検索結果の上位表示をさせるため」です 検索結果の上位に表示させることで、クリック率(CTR率)が増えることでアクセス数を増やせることです。 firstpage.com の 2023 年のデータは、ランキング 1 位の通常の CTR が 39.8% であることを示しています。これは、2 位の CTR 18.7% の 2 倍以上、3 位の CTR 10.2% のほぼ 4 倍です。 SEO対策のために何をすればいいのか? 〜ぶっちゃけどうすればいい?〜 SEO対策のために一番必要だと感じたのは、「最適化する対象である 検索エンジン(Google)の公式ドキュメント を読むこと」です。 ただ、Google公式ドキュメントは文字の羅列が続き、語彙の解説などはあるものの、初学者には難しく、読みにくいと感じてしまいました。ネットにはサクッと理解できる詳しく解説していただいているSEO対策関連記事が沢山あり、全体像を認識した上でGoogle公式ドキュメントを読むことで、スムーズに理解&実行ができるのではないかと感じました。 沢山の内容がある中で今回は6点の発見についてお伝えしたいと思います。 Webページの健康診断的存在「コアウェブバイタル」 コアウェブバイタルは”ページ読み込みパフォーマンス”、”インタラクティブ性”、”視覚的安定性”3つの指標によって測定される指標です。 Largest Contentful Paint(LCP): 読み込み開始から 2.5 秒以内 First Input Delay(FID): FID を 100 ミリ秒未満に収めるようにします。 Cumulative Layout Shift(CLS): CLS スコアを 0.1 未満に収めるようにします。 (2024 年 3 月以降、Interaction to Next Paint(INP)が FID に代わって Core Web Vitals の一つになります。) 参考にした記事: Core Web Vitals と Google 検索の検索結果について (Google検索セントラル) 「パンくずリスト」について これまで、自分は「パンくずリスト」のことをパン屋さんにあるものだと思っていました。 しかし、このリストはクローラーが文字やサイトの構造を把握するために重要なものの一つ、とのことでした。 由来になっているのが、「道しるべになるように」という兼ね合いから、童話ヘンゼルとグレーテルのお話が由来になっているそうです。 SEO対策において、内部リンクが強化され検索エンジンがクローリングしやすくなるという点で、パンくずリストは重要になるようです。 参考にした記事: パンくずリスト( BreadcrumbList )の構造化データ (Google検索セントラル) 「robots.txt」について 今回SEOのことを調べて初めて知った存在が「robots.txt」でした。 Google先生のドキュメントを読む限りでは、トラフィックの制御や、無駄なクロールの回避などを防げる優れものだと捉えられると思います。 Google のクローラからのリクエストによってサーバーが過負荷になっていると考えられる場合に、ウェブページ(HTML や PDF など、メディア以外で Google が読み取れる形式)に対して robots.txt ファイルを使用することで、クロール トラフィックを管理できます。また、サイト上の重要でないページや類似したページのクロールを回避することもできます。 robots.txt の概要 robots.txtを設置するだけで、順位が上がるといったものではないようでした。 クローラーによるサイト内の各ページへのアクセス管理を行なった方が良いのは、ページ数が1,000を超える中・大規模なサイトです。小規模なサイトであればクローラーの最適化は基本的に不要のようです。 参考にした記事: robots.txt の概要 (Google検索セントラル) キーワードについて Google はウェブ ランキングにキーワード メタタグを使用しません Google検索セントラル という明確な表示の通り、キーワードを盛り盛りにしても、GoogleブラウザのSEOはできないということがわかりました。 もちろん、コンテンツの中に適正にキーワードを組み込むのは大事ということがわかりました。 画像に「pictureタグ」を使用する 画像を配置する際、 <img> タグを <div> タグで囲うことがしばしばあると思います。 しかし、この場合、レスポンシブ対応のためにスマホ用の画像とPC表示用の画像2種類記載し表示させていないでしょうか。(自分はよくしていました…。) pictureタグとは色々な条件下でも最適な画像リソース提供できる仕組みで、CSSやjavascriptを使用しないで画像を切り替えることができるようになります。 Picture Elementに関するCan I Use によるとカバー率は97.61%(2023年12月時点)でした。 <picture> タグのメリット pictureタグの場合は読み込む画像は1つだけなので、複数行書いても余分な画像は読み込みを行わない →データ通信量を減らし、読み込みをサクサクにできる ※CSSのメディアクエリでは、PCとSPどちらの場合でも画像を両方読み込み自体は行われる <picture> タグのデメリット 記述する順番によって表示が異なってしまう CLS対策が必要 ( <img> タグも同様ではある) picture要素を使うことで、読み込み速度UP→UX向上→ひいてはSEO対策に繋がると感じました。 参考にした記事: pictureタグでレスポンシブに画像の表示を切り替える方法 (ウェブスペ) h1タグは1ページに1回、内容は明瞭簡潔に 「h1タグを乱用するとSEOに悪影響がある」という虚構のSEOあるあるを持っていました。 しかし、Googleガイドラインによると、「h1タグを過度に使用することは、ユーザーにとってもクローラーにとっても不親切になる」とのこと。結果的にSEO対策として良くないということだと理解しました。 これらのことから、h1タグ・見出しタグなどの適正利用を心がけたいと感じました。 参照: h1タグは1ページに1つだけ使うことをGoogleは推奨している? (NYマーケティング) 参照: 見出しタグを使用して重要なテキストを強調する (Google検索セントラル) まとめ ChatGPTにSEO対策について質問したところ、以下の回答を得られました。 SEO対策はちょうど魔法の呪文みたいなもので、自分のウェブサイトをたくさんの人に見てもらえるように手助けしてくれるのさ! おまけに、これを覚えれば、みんなともっとたくさんのお友達になれるよ! 一緒にウェブの世界を楽しもうね! https://chat.openai.com/ 今回、SEO対策を知り、SEOは、UXを爆上げするための基準となり、より良いものが正しく評価されるシステムだと感じ、「SEO対策をする=見てくれるユーザーのためにできることをする」ことなんだと感じました。 参考にした記事 https://firstpagesage.com/reports/google-click-through-rates-ctrs-by-ranking-position Google Click-Through Rates (CTRs) by Ranking Position in 2024 (October 23, 2023) The post 現代の様々なSEO対策をまとめてみた! first appeared on miracleave Tech Blog .
アバター
はじめに こんにちわ!新人社員のキタジマと申します。 今回研修カリキュラムとしてオリジナルアプリ作成をしていた中で、開発用ビルドツールとして用いた「Vite」の快適さを「vue-cli」と比較していきながら紹介していきます! 今回は開発用サーバを立ち上げてみて確認してみます。 Viteとは? Vue.jsは、優れた開発者体験と柔軟性を提供する人気のあるJavaScriptフレームワークです。Vueプロジェクトのセットアップとビルドには、Vue CLIが広く利用されていますが、近年、Viteと呼ばれる新しいビルドツールが登場し、その速さとシンプルな開発体験で注目を集めています。 Vite(フランス語で「速い」を意味する)は、そのVue.jsのためのビルドツールであり、開発時に高速でリアルタイムなフィードバックを提供します。Vue 3の新機能を最大限に活用し、ESM(ECMAScript Modules)を使用しているため、開発プロセスが非常に迅速になります。 Vite公式ホームページ:「 https://ja.vitejs.dev/ 」 Viteのセットアップ まずはViteのインストールを行います。これには、Node.jsとnpm(またはyarn)が事前にインストールされている必要があります。今回はnpmでセットアップしていきます! まずはViteのインストールとプロジェクトを作成します。 npm init vite@latest my-vite-project プロジェクトディレクトリに移動します。 cd my-vite-project 依存関係のインストールを行い、これで完了です。 npm install 開発用サーバを起動してみます。 npm run dev 無事立ち上がりました!それでは起動にどれほど時間を要したでしょうか? 「350ms  = 0.350秒」という結果でした!次は実際にビルドしてみましょう。 npm run build 「519ms  = 0.519秒」!これがどれだけ違うかを確かめるためVue CLIも同様にプロジェクトを作成します。 Vue CLIのセットアップ Vue CLIをインストールします。 ※-gはグローバルオプションです。Vue CLIに関してはプロジェクトごとに異なるバージョンのVue CLIを 利用することが難しいため、グローバルにインストールされることがあるようです。 npm install -g @vue/cli Vue CLIがインストールされたら、新しいVueプロジェクトを作成します。 vue create my-vue-project プロジェクトが作成されたら、作成したプロジェクトのディレクトリに移動して開発サーバーを起動します。 cd my-vue-project npm run serve こちらも立ち上がりました!こちらも時間を確認してみましょう。 「5254ms=5.254秒」でした。プロジェクト作成の段階でもViteと比較して約15倍時間がかかっています…! こちらもビルドを実行してみます。 npm run build 「8825ms=8.825秒」!Viteと比較して約17倍もの違いがありました。 なぜ速いのか? ViteはデフォルトでESM (ECMAScript Modules) を使用します。ESMはモジュールの読み込みが静的解析可能であり、これによりビルドプロセスがより効率的になります。一方、Vue CLIのような他のビルドツールは、CommonJSなどの他のモジュール方式を使用することがあり、これは静的解析が難しく、ビルドに余分な時間がかかる可能性があります。 他にも、Viteは高速なJavaScriptバンドラであるESBuildを使用しています。ESBuildは非常に高速で、バンドルの速度がVue CLIや他の一般的なバンドラよりも優れています。これにより、ビルドプロセス全体のパフォーマンスが向上します。 このような要因などにより、迅速で効率的なビルドを実現しています。 こちらも参照ください Viteを使う理由「 https://ja.vitejs.dev/guide/why.html 」 まとめ 当初私はオリジナルアプリのフロント部分を開発中Vue CLIを用いていましたが開発中に変更点を反映させて サーバを立ち上げた際に待つ時間が多々あり悶々としておりましたが、Viteで開発を行うように早期にシフトチェンジして効率性を上げたことで快適に作業を行えました。 昨今、Viteは、Vue.js開発者にとって新たな選択肢となりつつあります。高速な開発体験と最適化された本番ビルドが、プロジェクトの効率性とパフォーマンス向上に寄与します。Vue CLIとの比較を通じて、最適なツールを選択することが重要だと痛感しました! The post 【ビルド時間大幅改善】Vue.jsビルドツールとしてViteを使ってみた! first appeared on miracleave Tech Blog .
アバター
【Hinemos】環境構築してみた – インストール①  の続きです。 Hinemosと関連パッケージをCentOS7にインストールしていきます。 前回の記事と同様に、公式記事を参考に構築していきます。 Hinemos ver.7.0 入門編① Hinemos ver.7.0を使ってみよう 関連パッケージのインストール 今回構築するHinemosはVer7.0系で、以下のパッケージが必要になります。 OpenJDK8(Java8実行環境) vim-common(vimの機能補完) unzip(圧縮ファイルを取り扱うコマンド) CentOS7のminimalインストールだと付属しないため、yumコマンドで追加インストールします。 # yum -y install java-1.8.0-openjdk vim unzip # yum list installed | grep openjdk java-1.8.0-openjdk.x86_64 1:1.8.0.392.b08-2.el7_9 @updates java-1.8.0-openjdk-headless.x86_64 1:1.8.0.392.b08-2.el7_9 @updates # yum list installed | grep vim-common vim-common.x86_64 2:7.4.629-8.el7_9 @updates # yum list installed | grep unzip unzip.x86_64 6.0-24.el7_9 @updates Hinemos マネージャ(本体)とHinemos Webクライアント(管理画面)をインストールしていきます。 事前にインストールしたwgetコマンドで、インストールに使用するrpmファイルをダウンロードします。 ※一旦ユーザー「manager」のホームディレクトリにダウンロードしています。 # cd /home/manager # wget https://github.com/hinemos/hinemos/releases/download/v7.0.1/hinemos-7.0-manager-7.0.1-1.el7.x86_64.rpm # wget https://github.com/hinemos/hinemos/releases/download/v7.0.1/hinemos-7.0-web-7.0.1-1.el7.x86_64.rpm # ls -l 合計 226944 -rw-r--r-- 1 manager manager 162298960 12月 29 14:57 hinemos-7.0-manager-7.0.1-1.el7.x86_64.rpm -rw-r--r-- 1 manager manager 70087101 12月 29 14:58 hinemos-7.0-web-7.0.1-1.el7.x86_64.rpm rpmコマンドでファイルからのインストールを行います。 # rpm -ivh hinemos-7.0-manager-7.0.1-1.el7.x86_64.rpm 準備しています... ################################# [100%] 更新中 / インストール中... 1:hinemos-7.0-manager-0:7.0.1-1.el7################################# [100%] Created symlink from /etc/systemd/system/multi-user.target.wants/hinemos_manager.service to /usr/lib/systemd/system/hinemos_manager.service. Created symlink from /etc/systemd/system/multi-user.target.wants/hinemos_pg.service to /usr/lib/systemd/system/hinemos_pg.service. # rpm -ivh hinemos-7.0-web-7.0.1-1.el7.x86_64.rpm 準備しています... ################################# [100%] 更新中 / インストール中... 1:hinemos-7.0-web-0:7.0.1-1.el7 ################################# [100%] Created symlink from /etc/systemd/system/multi-user.target.wants/hinemos_web.service to /usr/lib/systemd/system/hinemos_web.service. Hinemos マネージャのサービスを起動してステータスを確認してみます。 Active行が “active (running)” の為、正常に起動できたようです。 # service hinemos_manager start Redirecting to /bin/systemctl start hinemos_manager.service # service hinemos_manager status Redirecting to /bin/systemctl status hinemos_manager.service ● hinemos_manager.service - Hinemos Manager Loaded: loaded (/usr/lib/systemd/system/hinemos_manager.service; enabled; vendor preset: disabled) Active: active (running) since 金 2023-12-29 15:21:18 JST; 6s ago Process: 18746 ExecStart=/opt/hinemos/bin/jvm_start.sh -W (code=exited, status=0/SUCCESS) Main PID: 18813 (java) CGroup: /system.slice/hinemos_manager.service mq18813 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Djdk.xml.entityExpansionLimit=0 -javaagent:/opt/hinemos/lib/eclipselink-3.0.2... 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.default.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.eth0.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.lo.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.all.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.default.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.eth0.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: sysctl: reading key "net.ipv6.conf.lo.stable_secret" 12月 29 15:21:17 hinemos01 jvm_start.sh[18746]: waiting for Java Virtual Machine startup... 12月 29 15:21:18 hinemos01 systemd[1]: Started Hinemos Manager. 12月 29 15:21:18 hinemos01 jvm_start.sh[18746]: Java Virtual Machine started (with -W option) Hinemos Webクライアントのサービスも起動してみます。 こちらも問題ないようです。 # service hinemos_web status Redirecting to /bin/systemctl status hinemos_web.service ● hinemos_web.service - Hinemos Web Loaded: loaded (/usr/lib/systemd/system/hinemos_web.service; enabled; vendor preset: disabled) Active: active (running) since 金 2023-12-29 15:26:19 JST; 3s ago Process: 19216 ExecStart=/opt/hinemos_web/bin/tomcat_start.sh -Wq (code=exited, status=0/SUCCESS) Main PID: 19269 (java) CGroup: /system.slice/hinemos_web.service mq19269 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Djava.util.logging.config.file=/opt/hinemos_web/tomcat/conf/logging.propertie... 12月 29 15:26:18 hinemos01 systemd[1]: Starting Hinemos Web... 12月 29 15:26:19 hinemos01 tomcat_start.sh[19216]: clearing temporary tomcat data 12月 29 15:26:19 hinemos01 tomcat_start.sh[19216]: successful in clearing temporary tomcat data. 12月 29 15:26:19 hinemos01 tomcat_start.sh[19216]: waiting for WebClient startup... 12月 29 15:26:19 hinemos01 tomcat_start.sh[19216]: Tomcat started. 12月 29 15:26:19 hinemos01 tomcat_start.sh[19216]: WebClient started. (with -W option) 12月 29 15:26:19 hinemos01 systemd[1]: Started Hinemos Web. Web クライアントのサービスまで起動できたため、ブラウザでWebクライアントにアクセスしてみます。 無事Webクライアントにアクセスできました。 Hinemos WebクライアントのログインPW変更 初期設定されている管理者権限ユーザーのパスワードを変更します。 ユーザーID「hinemos」でログインします。パスワードも「hinemos」です。  初期ログイン時のスタートアップ画面が表示されます。 上部タブから「パースペクティブ」→「アカウント」を選択し、登録ユーザーを確認します。 「hinemos」ユーザーのみ登録されている為、右クリックメニューで「パスワード変更」を選択し、任意のパスワードに変更します。 変更後は再ログインが必要になります。 新規ユーザーを追加したり、より権限を絞ったロール(ユーザーグループ)を作成し、ユーザーに紐づけることも可能です。 総括 wgetでのパッケージダウンロードがWAFに引っかかったり、作業で使っていたVPNが頻繁に落ちたり、 Hinemos用にパッキングされたサービスの設定ファイルを見ていたり、関係ないところで時間が融けました。 本筋から逸れる設定は、変更してみるタイミングがあれば追記します。 The post 【Hinemos】環境構築してみた – インストール② first appeared on miracleave Tech Blog .
アバター
現場で Hinemos という統合運用監視ツールを利用することになりまして、なんでも国産のオープンソースソフトウェアだとか。 OSSってことは自分でイジイジしてもよいのでは、という発端で記事にさせていただきました。 元々自宅に以下のような仮想ネットワーク環境を構築しており、似たようなOSSの監視ツール( Zabbix )を利用して各ノードの監視をしていたのですが、これを機にHinemosにやってもらおうかなと思います。 ジョブ管理機能も利用できるのでより便利になるはず、おそらくきっと想定では。 以下公式記事を参考に構築していきます。 Hinemos ver.7.0 入門編① Hinemos ver.7.0を使ってみよう 下準備(OSの準備) 現場ではRedHat系のOSに乗っているので、カーネル互換のAlmaLinuxあたりで組んでみようと思いましたが、 動作環境 に対応している旨の記載がなかった為、スタンダードにCentOS7で構築します。 Hyper-V上にデプロイするためのisoをダウンロード。 無駄なパッケージが入らないよう、最小(minimal)インストールにします。 http://ftp.riken.jp/Linux/centos/7.9.2009/isos/x86_64/ CPU、メモリ、ストレージは最小要件のあまめ2倍を目途にします。 あとからLoadAverageなど見て調整するつもり。 CentOSのインストールウィザードからサクサクと進めます。 インストールが完了したら、SSHで接続して基本設定っぽいことをしていきます。 yum:パッケージのアップデートと必要そうなパッケージの追加。 # yum -y update # yum -y install bash-completion bind-utils wget sshd:rootユーザーのssh接続を禁止。 # vi /etc/ssh/sshd_config ================================================== #PermitRootLogin yes #コメントアウト PermitRootLogin no #追記 ================================================== wheelグループに追加されているユーザー以外のsuコマンド(ユーザーの切替)を禁止。 構築用アカウントはwheelグループに追加しておきます。今回は「manager」で作成。 # vi /etc/pam.d/su ================================================== # Uncomment the following line to require a user to be in the "wheel" group. auth required pam_wheel.so use_uid #コメントアウトを外す ================================================== # usermod -G wheel manager selinux:Hinemos公式の手順で無効化するようです。 # vi /etc/selinux/config ================================================== #SELINUX=enforcing #コメントアウト SELINUX=disabled #追記 ================================================== firewalld:Webクライアント、SNMPTRAP、Hinemosマネージャ接続用のポートを開放。 # firewall-cmd --add-service=https --zone=public --permanent # firewall-cmd --add-service=http --zone=public --permanent # firewall-cmd --add-port=162/udp --zone=public --permanent # firewall-cmd --add-port=8081/tcp --zone=public --permanent # firewall-cmd --zone=public --remove-service=dhcpv6-client --permanent # firewall-cmd --reload # firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: http https ssh ports: 162/udp 8081/tcp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: その他環境に合わせてNTPやネットワーク設定等変更しました。 再起動して下準備完了です。 # reboot 総括 Hinemosというよりは、CentOSのインストール手順になってしまいました… 次の記事 で、実際にHinemosと関連パッケージをインストールしていきます。 The post 【Hinemos】環境構築してみた – インストール① first appeared on miracleave Tech Blog .
アバター
こんにちは。西です! 最近、GoogleのLooker Studioでのデータ可視化プロジェクトに取り組んでいました。 そもそもLooker Studioってなんなの?という疑問や、「データの統合」や「ディメンション」など、Looker Studioの用語、プロジェクトの中で詰まってしまった制限についても共有したいと思います! そもそもLooker Studioとは? Looker Studioは、データの可視化とレポーティングのためのオンラインツールです。 直感的な操作ができ、機能も多彩なためとても魅力的なツールとなっています! しかしデータの可視化というと、いまいちピンと来ない方もいるかもしれませんので簡単に説明いたします。 例えば、このようなデータがあるとします。 これは、果物の種類と値段を表した表です。 果物の値段 果物 値段 りんご 100 みかん 120 バナナ 200 梨 150 イチゴ 500 メロン 1000 もう一つ、データがあるとします。これは果物の売れた個数を表した表です。 売れた個数 果物 個数 りんご 100 みかん 50 バナナ 70 梨 30 イチゴ 67 メロン 5 このデータだけだと、その月にどれだけ売り上げたのか?をすぐに把握することが出来ません。 ではどうするのか?というと、二つの表を結合し、グラフ化してあげると見やすくなります! 例えば、果物毎の売り上げを見たいとします。これを、表にすると以下のようになります。 (※売り上げは、個数×値段です。) では、さらにこれを円グラフにしてみましょう。 月全体の売り上げのうち、イチゴが一番売れているのがすぐにわかります! つまり、このようなグラフをプログラミング言語を知らなくてもデータソースから作れるツール・・・それがLookerStudioです! 今回は簡単な例を挙げたため、いまいちその便利さが伝わりにくいかもしれませんが、膨大なデータを表やグラフにまとめる時にとても簡単に作成できるものだと思っていただけると嬉しいです! 「データの統合」「ディメンション」など聞きなれない言葉がたくさん・・・ 「データ統合」という言葉の説明をするために、まずはLooker Studioのデータソースについて簡単に説明する必要があります。 まず、Looker Studioでは、さまざまなデータソースを使うことが出来ます。(Googleスプレッドシート、Google Analytics、SQLデータベースなど) その中で今回はGoogleスプレッドシートをデータソースとした場合の説明をしますが、スプレッドシートのSheet1に果物の値段、Sheet2に売れた個数というデータがあった場合に、Sheet1とSheet2のデータを結合して表示することが出来ます。以下のようなシートですね。 この結合のことを「 データ統合 」と呼びます。 Looker Studioの画面ではこのような画面で統合出来ます。 ここでは、二つのテーブルを統合する際に両方のテーブルにある「果物」というキーを使って統合しています。 「 ディメンション 」というのは、果物の値段シートで言うところの「果物」と「値段」がそれに該当します。 それぞれの列のタイトル部分(ヘッダー)と言うとわかりやすいかと思います! また、Looker Studioの画面ではこのような表示です。 Looker Studioを使う際には必ず使う言葉ですので、この二つは確実に押さえておきましょう! Looker Studioプロジェクトで詰まったこと 一番伝えたかった事はこちらになります(笑) 今後Looker Studioを使おうとした方は必ず引っかかる部分だと思うので、ぜひ見て頂けると幸いです。 データ統合出来るテーブルの数は最大5つ データ統合は無制限に統合出来るわけではありません。データ統合には制限があり、一つの統合につき最大5つのテーブルしか結合できません。 利用可能なディメンションは最大10個 ディメンションにも制限があります。ディメンションは一つのデータソースにつき最大10個までしか利用できません。 データソースの更新 もし上記例でイチゴの個数を間違えて入力していた場合、Googleスプレッドシートの変更を行うのは簡単にできますが、Looker Studioは自動的にシートの更新を検知してくれません。 必ずデータの更新作業が必要になります。 関数も使える!だが・・・ Looker Studioでは関数も使えます!CASEといった条件分岐の関数や、文字列の置換、COUNTといった関数を使えるのはとても便利です!!! しかし、使える関数は決まっているため、自分のやりたいことを実現することが出来ない可能性があります。 使える関数と、自分の実現したい表示の仕方と、是非検討してみて下さい。 出典: Looker Studioの関数一覧 さいごに ここまでお付き合いいただきありがとうございました!! Looker Studioの基本的な概念と、プロジェクトで詰まった部分について、いくつかお話ししました。 Looker Studioは、大量のデータを扱う際に非常に便利なツールであり、ビジネスの意思決定を支援してくれます。 このブログがLooker Studio初心者や興味を持っている方々に役立つ情報を提供できれば幸いです! The post 売り上げデータで遊ぼう!Looker Studioの簡単テクニック first appeared on miracleave Tech Blog .
アバター
はじめに おはこんばんにちは!鈴木です。 突然ですが、倒しても倒してもエラーに遭遇すると心が折れそうになりませんか?私はなります。 ・エラーの解決方法などを何度も調べては忘れてしまったり… ・そもそもどのようにエラーと向き合ったらいいんだっけ? となる私のような初心者の方向けに今回はJavaのエラーについてまとめてみたいと思います! Javaのエラーの種類について エラーには、Java プログラムの文法上の問題があったときに発生する コンパイルエラー と、 実行することが不可能な処理を行なおうとしたときに発生する 実行時エラー の2つがあります。 簡単にそれぞれエラーの種類となぜ起きるかを紹介していきたいと思います! コンパイルエラー コンパイル時 に検出されるエラーであり、Java 言語の文法に誤り(構文エラーや型エラー)があることでコンパイルができない場合に発生するエラーのこと。 これもよく見るエラーですね! 以下のポイントを確認して修正して再コンパイルすることで解決できます。 解決策 ・大文字小文字を間違えている ・つづりを間違えている ・行末の ; が抜けている ・ . と , や ; と : などの記号を間違えている ・開きカッコ ( { [ と閉じカッコ ) } ] の数があっていない(開いたカッコが閉じていない) ・{ } ; などの記号が全角になっている ・空白部分に全角スペースを利用している ※コンパイルとは コンパイルとは、人間が作成したソースコードをコンピュータが実行できるように変換すること。 実行時エラー Javaの文法に誤りがなくコンパイルは通るが、使い方が誤っているなどの理由からプログラム実行時に発生するエラーのこと。 私が遭遇した実行時エラーを今回は3つ紹介します! ①NullPointerException javaの代表エラーとして挙げられ、「ぬるぽ」とよく言われるエラーですね! 参照型の変数がnullを指している時に発生する例外です。 //出力結果 Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "text" is null at main.NullPointerExceptionExample.main(NullPointerExceptionExample.java:7) 上記例ではnullの入った値を7行目で呼び出していることでエラーが発生していますね。 解決策 インスタンスの生成や値の設定が正しく行われているかをチェックする。 オブジェクトがnullになってしまうタイミングをデバッグで確認する。 プログラムでオブジェクトがnullかどうかのチェックを行い、エラーの発生をできる限り回避する。 ②ArrayIndexOutOfBoundsException 配列の無効なインデックスにアクセスしようとした時に発生するエラーです。 //出力結果 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at main.ArrayIndexOutOfBoundsExceptionExample.main(ArrayIndexOutOfBoundsExceptionExample.java:7) ここでは配列の範囲外を指定しているため、7行目にてエラーが発生してしまっていますね。 解決策 正しい配列のインデックスを指定できているかチェックする。 配列の設定を繰り返し処理で行っている場合、繰り返し回数などに問題がないかチェックする。 ③ArithmeticException 数学的に許されていない計算を行うとしたときに発生するエラーです。 //出力結果 Exception in thread "main" java.lang.ArithmeticException: / by zero at main.ArithmeticExceptionExample.main(ArithmeticExceptionExample.java:6) 解決策 ゼロ除算が行われてないかをチェックする。 数値型変数で計算している場合、割る数の変数にゼロが設定されていないかチェックする。 今回はとても有名なエラーについて取り上げてみました! しかし、これ以外にもある様々なエラーに遭遇したらどのように対応していったらよいでしょうか。 次で対応策を検討したいと思います! エラーに遭遇したら ①エラー文を読もう! エラーに遭遇したらまずは慌てずに、勇気を出して エラー文をちゃんと読みましょう !これが意外と大事です! 上記のサンプルエラーコードの出力結果にもきちんとどこでどんなエラーが発生していたかを教えてくれていましたね。英語で慌ててしまうかもしれませんが、翻訳したりしてみましょう! エラー文を読んでなんとなく目星をつけたら、次のステップです! ②検索とデバッグツールを活用しましょう! 目星をつけたあたりにブレークポイントを置いてみてデバッグを行ったり、メソッドの使い方が正しいかなどを検索してみましょう! 具体的な手順のイメージとしては以下です。 どこを実行したタイミングでエラーが出たかを確認する その原因となった処理を特定する 何が正しい処理なのかを確認する 正しい処理になるよう修正する 端的に紹介してしまいましたが、大体のエラーは上記方針で対処できると思います。 (他のやり方があったらぜひ教えてください!) ただ、私も含め初心者だと複雑な処理の場合はどこからエラーが起きているかなどを追うのが難しいこともあると思います。 その時は今回紹介した手順などで自身でもできるだけ調査を行い、分からないところを少しずつ明確にして先輩や有識者の方の力を借りられるようにできたらいいですね! 調べていくことでどんどん処理の解像度が上がっていくと思います!私も頑張ります…! おわりに 今回、記述してみてエラーは意外と誤っているおおよその場所や理由を教えてくれたりする親切なヤツってことがわかりました。エラーは友達!敵じゃない!ってことですね!(?) とは言ってもなかなか解決できるようになるまでは最初は難しいですが、解決していくことで少しずつ理解が深まるので、エラーに負けずに一緒に頑張りましょう! The post 【Java】よく遭遇するエラーについて first appeared on miracleave Tech Blog .
アバター
はじめに こんにちは。S.Sです。 今回はC#(ASP.NET)で、multipart/form-dataを用いたファイルアップロード機能を実装することになり、受信したファイルをフォルダに保存する際、アップロードされたファイル名が一時ファイル名になってしまい、元のファイル名で保存するための処理の作成に時間がかかってしまったので、備忘録を兼ねて記します。 ファイルアップロード処理を作成する ファイルのアップロード実装自体は公式が参考ページを用意してくれていましたのですんなり実装できました。( こちら ) MultipartFormDataStreamProviderクラスのインスタンスを作成し、 await Request.Content.ReadAsMultipartAsync() とすることで実装ができるようです。 string path = ("任意のアップロード先フォルダー") var provider = new MultipartFormDataStreamProvider(path); await Request.Content.ReadAsMultipartAsync(provider); アップロードされたファイル名が一時ファイル名として保存されている 上記でファイルアップロードを実装し、実際にPostmanでform-dataでファイルを送信してみたところ「BodyPart_……」のようなファイル名で保存されていました。 provider.FileDataから一時ファイル名とオリジナルのファイル名を取得し、任意のフォルダにコピーすればいいようなのですが、最初から元のファイル名で保存されるようにできないかな~…。と思いもう少し調べました。 MultipartFormDataStreamProviderを継承したクラスを作成する ( こちら )が参考になりました。 ReadAsMultipartAsyncでファイル読み込み完了時に呼び出されるMultipartFormDataStreamProviderクラスのGetLocalFileNameという処理をオーバーライドして、オリジナルのファイル名をReturnするようにすれば良い。ということのようです。 /// MultipartFormDataStreamProviderを継承したカスタムクラス class MyMultipartFormDataStreamProvider : MultipartFormDataStreamProvider { /// コンストラクタ public MyMultipartFormDataStreamprovider(string path):base(path) { } /// ファイル読み込み完了時呼び出される処理をオーバーライド public override string GetLocalFileName(System.Net.http.Headers.HttpContentHeaders headers) { return headers.ContentDisposition.FileName.Trim('\"'); } } 上記で作成したカスタムクラスのインスタンスを作成し、await Request.Content.ReadAsMultipartAsync()とすることで string path = ("任意のアップロード先フォルダー") var provider = new MyMultipartFormDataStreamProvider(path); // GetLocalFileNameをオーバーライドしたカスタムクラス await Request.Content.ReadAsMultipartAsync(provider); 元のファイル名で保存することができました。 書いてみたらこれだけか。。という感じですが、これで元のファイル名で保存することができ、目的達成です。 The post 【C#,ASP.NET】multipart/form-dataでファイルをアップロードする際に少し困った話 first appeared on miracleave Tech Blog .
アバター
はじめに こんにちは 最近、Kotlinを触り始めた田代です。 今回は実際の業務で時間がかかってしまった三次元リストの作り方をご紹介します! Kotlin Playgroundについて Kotlin Playground とは、WEB上で気軽にKotlinを試すことができるサービスです。 Kotlin Playground: Edit, Run, Share Kotlin Code Online play.kotlinlang.org 初期画面は「Hello, world!!!」を表示するコードが書かれていて、画面右上の「Run」を押すとmainメソッドが実行され、画面下に結果が表示されます。書いたコードを共有でき、ちょっとした開発時に使えそうです! 今回は、このKotlin Playgroundを使用していきます。 ゴールの形 以下の形の三次元リストをList型で作成します! fruitsList = [ [ [A, apple], [C, cherry], [G, grape] ] , [ [K, kiwi], [B, banana], [O, orange] ] ] Kotlinでのリストの作り方 一次元リストの作り方 まずは一次元リストの作り方から! リストの変数の型を List<String> とし、 listOf() を使用して初期化します。 リストに値を入れるときは「+=」で1つずつ要素を追加できます。 またlistOf()を使用して、要素をまとめて追加することもできます。 一次元リストの取り出し方 index を指定してあげることで、値を取り出すことができます。 二次元リストの作り方 次に二次元リストの作り方です! Listの中にListが入るように変数の型を List<List<String>> としています。 二次元リストの値の取り出し方 一次元リストと同じようにindexを指定して値を取り出すことができます。 三次元リストの作り方 最後にゴールの形である三次元リスト(fruitsList)の作り方です! 二次元リストと同じように変数の型を List<List<List<String>>> とします。 次に三次元リストに入れる二次元リストを作成します。 作成した二次元リストを三次元リストに入れて完成です。 三次元リストの取り出し方 取り出し方は今までの取り出し方と同じで、indexを指定してあげることで取り出すことができます。 まとめ 学んでみるとなんだこういうことかくらいのちょっとした記述でも、初めて触る言語だと意外と調査に時間がかかってしまうことってありますよね。 今回は、私が調べて時間がかかったところについて備忘も兼ねて簡単にまとめてみました。 同じように悩んでいる人に読んでもらえたら嬉しいです! リストにはArrayListやMutableListなどの型があり、私はまだまだ使い所が理解できていないので引き続き勉強していこうと思います! 初学者の皆さん一緒に頑張りましょう! その他 例文では、listの初期化をlistOf()で空のlistを作成していますが、listを明示的に空であることを示したいときは emptyList() を使って記載することもできます。emptyList()で空のリストを作成した後からでもリストに値を入れることはできますので、コードの可読性を上げたい場合に使用してみて下さい。 Kotlinを学び始めたときに公式から出ている問題演習ができるサービスを見つけたので、ご紹介させていただきます! Kotlin Koans Kotlin Koans は、WEB上でKotlinの基礎を学ぶことができるサービスです! Kotlin Playground: Edit, Run, Share Kotlin Code Online play.kotlinlang.org Kotlinの構文について問題が出題され、環境構築なしでKotlinを書いて学ぶことができます。 初めてKotlinを触る方にぴったりなサービスだと思いますので、よかったら試してみてください。 The post [Kotlin] 三次元リストの作り方 first appeared on miracleave Tech Blog .
アバター
はじめに こんにちは! そろそろエンジニア2年目が終わり、3年目を迎えることに恐怖している新垣修一です! 今回はPythonWebフレームワークの一つであるStreamlitを使用して、アプリを作成してみます。 最近技術系の記事を見るとフロントエンドの知識なしで早くアプリを作成できるStreamlitというフレームワークの存在を知り、少し触れてみたいなと思い今回の記事を書かせていただきました。 Streamlitとは Streamlitは、Streamlit社が開発したPythonのWebアプリケーションのフレームワークです。 Streamlitを使うと、簡単にWebアプリケーションが作成できます。細かい設定とかは行えないですが、HTMLやCSS、JavaScriptの知識が不要で全てPythonの記述だけで完結します。 最近だとデータサイエンティストや機械学習エンジニア等が、収集・生成したデータをさくっと可視化してデプロイするために利用しているケースが多いそうです。 Streamlit • The fastest way to build and share data apps Streamlit is an open-source app framework for Machine Learning and Data Science teams. Create beautiful web apps in minutes. streamlit.io Streamlit Docs docs.streamlit.io インストール方法 インストールは下記コマンドを入力すればインストールできます。 pip install streamlit 今回のゴール import streamlit as st import pandas as pd import numpy as np text = st.text_input(label='Message', value='Hello World!') text2 = st.text_input(label='Message2', value=' こんにちは 世界') text3 = st.text_input(label='Message3', value='Hello 世界!') st.sidebar.header('サイドバー') st.sidebar.write(text) st.sidebar.write(text2) st.sidebar.write(text3) def main(): df2 = pd.DataFrame( np.random.rand(20, 3), columns=['a', 'b', 'c'] ) st.line_chart(df2) st.area_chart(df2) st.bar_chart(df2) if __name__ == '__main__': main() ソースの中身について まず第1ステップとしてアプリの内容を任意のファイル名の.pyファイルに作成します。 その後第2ステップとしてターミナルにて、下記.pyフォルダの場所に以下のコマンドを打ち込むことで、アプリが既定のブラウザで立ち上がります。 streamlit run ファイル名.py 下記ソースは左のサイドーを表示させるのと入力した文字をサイドバーに表示させるソースです。 実際の画面は下記画像となります。デフォルトではvalueの文字ですが、文字入力欄を任意の文字に変えれば動的にサイドバーの文字が変わります。 text = st.text_input(label='Message', value='Hello World!') text2 = st.text_input(label='Message2', value=' こんにちは 世界') text3 = st.text_input(label='Message3', value='Hello 世界!') st.sidebar.header('サイドバー') st.sidebar.write(text) st.sidebar.write(text2) st.sidebar.write(text3) 次に文字入力欄の下にある三つのグラフです。 np.random.randでランダムな数字を取り出してくれます。そして()の中身ですがここでは例として20と3を設定します。一つ目の20がグラフのx軸の最高値となります。二つ目の3がグラフ表示されるデータの数です。そしてcolumns=[‘a’, ‘b’, ‘c’]で表示したいデータを設定します。最後にline・area・barで各グラフを表示します。 def main(): df2 = pd.DataFrame( np.random.rand(20, 3), columns=['a', 'b', 'c'] ) st.line_chart(df2) st.area_chart(df2) st.bar_chart(df2) if __name__ == '__main__': main() 実装する機能としては、簡易的であまり意味がないものですがデータを持っていきグラフを出したりすることもできます。上記以外で地図を表示したり表を表示したりするすることができます。フロントエンドの技術を使用しない分自由度は下がりますが、簡単なアプリであればサクッと作れます。他の機能を搭載したい表示したいなどあれば調べてみると良いでしょう。 デプロイしてみる 1.Streamlit Cloudにサインインするために以下のリンクにアクセスしてください。 https://share.streamlit.io/signup 下記ページが開いたら、Googleアカウント、Githubアカウント、メールアドレスのいずれかを利用してアカウントを作成します。 2.Githubアカウント連携 今回はGitHubアカウントを使用してアカウント作成します。お手持ちのGitHubアカウント情報の入力してサインインしてください。 3.アカウント情報を入力 下記画面が表示されたらご自身の情報を入力し、Continueボタンをクリックしてください。 4.デプロイする 上記でContinueボタンをクリックした後に下記画面が表示されたら右上の”New app”をクリックしてください。 New appボタンをクリック後に下記画面が表示されると思います。 次にリポジトリ、ブランチ、実行ファイル名を入力します。 必要項目を入力しDeploy!をクリックするとデプロイされます。 おわりに いかがでしょうか。今回はデプロイを簡単にできるという軸で記事を書かせていただいたので、実装されているソースは簡易的なものでしたが、他にもやれる機能はあるのでご自身が良いと思ったものを作成してみてはいかがでしょうか。 それでは良きPythonライフをお過ごしください! The post Pythonの”Streamlit”でアプリをデプロイするまで first appeared on miracleave Tech Blog .
アバター
こんにちは! 現在Reactでフロントエンドの開発を担当している土井です😎! 今回はDOM参照に使うref属性の使い方について、実際の業務で詰まった事と解決方法をご紹介したいと思います! 実現したいこと ページからボタンを押下してダイアログを開く際に、下の画面イメージのように、ある一定の位置まで自動スクロールして表示したい。 ハマったこと スクロール処理は、 Element.ScrollTo() で対応できるが、肝心のElementの参照はどうするか? 当初はuseRefを使って参照しようとした。(以下のような感じで↓) //ダイアログのrefオブジェクト const dialogRef = useRef(null) // ダイアログを開けたら、スクロールするuseEffect React.useEffect(() => { if (open) { if (dialogRef.current !== null) { dialogRef.current.scrollTo(0, 2000); // スクロール処理 } } }, [open]); // 依存配列にはダイアログの開閉state ~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~ <Dialog open={open}   // ダイアログの開閉state onClose={handleClose} scroll="paper" aria-labelledby="scroll-dialog-title" aria-describedby="scroll-dialog-description" > <DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle> <DialogContent dividers        ref={dialogRef} // ref属性にrefオブジェクトをセット > しかし、ダイアログを開いた時は、dialogRef.current が nullになっておりスクロール処理が実行すころとが出来ない。 なぜdialogRef.currentがnullになっているのか? 原因 Dialogは常にDOM内には存在せず、Dialogを開いた際にマウントされる ため。 openがtrueになった時点ではまだマウントされておらず、dialogRef.currentはnullになるらしい。 <補足> マウント   :  DOMnodeがDOMツリーに追加されること ちなみに混同しやすいものとして”レンダリング”もありますが、レンダリングはreactコンポーネントからDOMnodeを作るためにpropsとかstateなどが読み込まれる処理です。 解決方法 refオブジェクトはstateのように中身に変更があった際の通知はされないので、useEffectは使えない。 React公式にも記載があるが、ref属性にコールバック関数を渡して、そのコールバック関数の中でスクロール処理を実行することができる! またコールバック関数の引数には、nodeを受け取ることが可能!! (←ここがポイント) 関数はref属性に更新がある(マウントする)度に呼び出されるので、 つまり、マウントされてnodeが参照できるようになった段階で何らかの処理が可能になる。 コールバック関数は、以下のように実装。 cost scrollDialog = useCallback((node) => { // 引数にnodeを受け取る if (!node) return; // nodeがnullの場合はリターンして処理終了 if (node.scrollTop !== 2000) { node.scrollTo(0, 2000); // スクロール処理 } },[]); ~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~ <Dialog open={open}   // ダイアログの開閉state onClose={handleClose} scroll="paper" aria-labelledby="scroll-dialog-title" aria-describedby="scroll-dialog-description" > <DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle> <DialogContent dividers        ref={scrollDialog} // ref属性にコールバック関数をセット > React公式は こちら 最初は、なぜrefオブジェクトがnullになるのか原因が掴めず、解決に結構時間を要してしまった。 なんだかんだ公式を読むのはやはり大事と実感しました😄 The post [ React ref ]ダイアログを開いた時に自動スクロールさせたい first appeared on miracleave Tech Blog .
アバター
新年あけましておめでとうございます🎍大友です! 無料でWordPressで書いたブログ記事を投稿した際に、Twitterへ自動で投稿したかったのですがその際に使用した「NextScripts: Social Networks Auto-Poster」というプラグインについて、その設定方法などを今回は記載したいと思います。 NextScripts: Social Networks Auto-Posterとは 以下の公式サイトなどよりダウンロードすることが出来るWordPressプラグインです。 NextScripts: Social Networks Auto-Poster Automatically publishes blogposts to profiles/pages/groups on Twitter, Google+, Pinterest, LinkedIn, Blogger, Tumblr ... 22 more ja.wordpress.org WordPressで投稿した記事の内容を、TwitterやFacebookなどの各種SNSへ自動連係することの出来るプラグインとなります。頭文字を取ってSNAPと呼称されたりもします。 その他SNS連携することの出来るプラグイン SNAPの他にもWordPressで作成した記事をSNSへ連携することが出来るプラグインは存在します。( NelioContent や JetPack ) が、 無料 で記事投稿と同時にSNS連携をしてくれるのはSNAPしかありませんでした。。 NelioContentやJetPackについては、Twitterの APIキー取得が不要 で設定が容易であったり、NelioContentに関してはInstagramへの連携も可能であったりといったメリットがあるのですが、無償版の場合は自動でSNS連携が不可(もしくは回数制限あり)でした。 Social Networks Auto-Posterを設定してみる まずは TwitterのDeveloperサイト にサインアップします。 上記画面にて入力したアドレスに届いたコードにて認証を行うと(この際にユニークなプロジェクト名の入力が求められますので任意の名称を設定してください)、以下の通り各種キー情報が表示されます。後ほど再生成をするのですが念のため控えておきましょう。 ダッシュボード上の作成したプロジェクトの歯車アイコンより、Twitterアプリケーションの権限を「Read and Write」に変更します。変更後は各種キー情報の再生成を行った後にメモなどに控えるようにしましょう。SNAPで使用するのは「 API Key 」「 API Key Secret 」「 Access Token 」「 Access Token Secret 」の4種類になります。 WordPressの管理画面よりSNAPを検索・インストールし有効化しましょう SNAPが左メニュー上表示されるようになります。「Add new account」ボタンを押下し対象のSNSアカウントを追加します。 控えておいたTwitterの各種キー情報を入力し更新することで設定は完了となります。 Message Format部分にはTwitterへ投稿する際のフォーマット(ブログのタイトル等)を設定することが可能です。 最後に いかがでしたでしょうか? NelioContentやJetpackなど他プラグインについても素敵なものなのですが、まずは無料で記事投稿と同時にSNS連携したい!というような要望をお持ちの方がいらっしゃいましたら是非SNAPを利用してみるのが良いかと思います! ちなみに当記事についても、バッチリ弊社miracleaveのTwitterへ自動連係されるようなっているはずです! Tweets by miracleave これからも様々な記事を公開していく予定ですので、この機会に是非上記アカウントをフォローいただきチェックしていただけると嬉しいです! The post 「Social Networks Auto-Poster」を使ってみる first appeared on miracleave Tech Blog .
アバター
はじめまして!インターン生の momo です! 普段は、大学院で暗号理論の研究をしています✏️ いきなりですが・・・ 普段、暗号の安全性って考えたことありますか? 本記事では、ビット演算子の一つである「排他的論理和」を用いた暗号の紹介をします♬ ワンタイムパッドとは? ちょっと変わった暗号方式 “ ワンタイムパッド ” を紹介します! ※ワンタイムパスワードとは別物です。 この暗号を一言でいうと、 「 安全性が高いけど、不便な暗号方式 」 ですかね。 暗号って「安全だから良い!」ってわけではないのです・・・ 仕組みはシンプル。 排他的論理和(XOR)を利用して平文を暗号化する これだけです。 ここで、排他的論理和(XOR)について復習すると・・・ A と B を以下のように入力した時に、 A ∨ B として出力される論理演算です! ワンタイムパッドは、この論理演算を利用して暗号化しています! 実際に、例を用いてワンタイムパッドの仕組みを見ていきます🌱 例えば、平文と秘密鍵が以下のように与えられたとき、排他的論理和を考えると、暗号文は以下のようになります。 ワンタイムパッドの実装 Pythonでワンタイムパッドを実装してみました👇 import random plain_text = "1010010101" secret_key = "" for _ in range(len(plain_text)): secret_key += str(random.randint(0, 1)) cipher_text = "" for i in range(len(plain_text)): xor = int(plain_text[i]) ^ int(secret_key[i]) cipher_text += str(xor) print(f"平文: {plain_text}, 秘密鍵: {secret_key}, 暗号文: {cipher_text}") 実装結果 平文: 1010010101, 秘密鍵: 0101001000, 暗号文: 1111011101 ポイント! secretKey (秘密鍵) は、plainText (平文) と 同じ長さ をとってくる。 secretKey (秘密鍵) は、 ランダム に設定する。 1ビットずつ排他的論理和を計算する。 ワンタイムパッドの特徴 メリット 暗号化も復号化も仕組みがシンプル。 乱数を用いることによって、暗号化の安全性が高い。 デメリット 平文と秘密鍵は同じ長さである必要があるため、平文が長くなると秘密鍵も長くなってしまう。 送信者と受信者で事前に秘密鍵を共有しておく必要がある。 余談 ワンタイムパッドは、1917年に ギルバート・バーナム が発案し、数学者 クロード・エルウッド・シャノン によって安全性が示された暗号です。 また、太平洋戦争で日本陸軍が利用したことで有名です。 まとめ ワンタイムパッドは排他的論理和を用いて暗号化する暗号方式! 安全性は高いけど、秘密鍵の共有に手間がかかるため不便なのです(泣) 参考文献 Johannes A. Buchmann 著、林芳樹 訳「 暗号理論入門 」 2001/07/01第1刷 Springer-Verlag Tokyo 岡本栄司 著、林芳樹 訳「 暗号理論入門 」 2002/04/10第2刷 共立出版 The post 強力な暗号「ワンタイムパッド」とは? first appeared on miracleave Tech Blog .
アバター
こんにちは、Bellです。 今回は初学者から初心者までAWSユーザなら知っておくべきアカウントの保護方法についてです。 アカウント保護って? 基本的にAWSアカウントは個人や組織のために存在するわけなのですが、ときに悪意ある外部のユーザに利用されてしまう懸念があります。 サーバへの不正アクセスだったり、IAMユーザの不正利用だったり不正アクセスの方法は様々であり、そういった悪意ある第三者からアカウントを保護する必要があるわけですね。 GuardDuty を使ってアカウントを保護する アカウント保護の手法はいくつかあるわけなのですが、今回は GuardDuty を使って不正なアクセスを検知してみましょう。 AWS コンソールにサインインして GuardDuty のページを開きます。 利用が初めての場合は 今すぐ始める ボタンから設定しましょう GuardDuty 用に権限を作成します。GuardDuty では各種ログを分析することで不正アクセスを検知するため、ログの読み取り権限が必要になります。 付与される権限は サービスロールのアクセス権限の表示 ボタンから確認しましょう。 GuardDuty を有効化する ボタンから有効化しましょう。 これですべてではありませんがAWS側が用意している検査対象の不正アクセスを検知することができるようになりました。 ですが、このままでは検知できても利用者が気がつくことができませんので通知の設定をしていきましょう。 流れとしては GuardDuty で不正アクセスを検知 EventBridge でイベントを発火 SNS で通知 の3段階です。 1つ目の GuardDuty で不正アクセスを検知 はすでに設定しているのでイベント発火の設定をします。 がしかし、先に SNS トピックを作成しておきましょう。 EventBridge のルール作成時に必要になるためです。 SNS を検索して SNS の画面に行きましょう。 左メニューのトピックからトピックの一覧を表示して トピックの作成 ボタンから作成していきましょう。 今回は以下の内容で作成しました。 タイプ スタンダード 名前 guard-duty-notification 表示名 guard-duty-notification 作成したトピックにサブスクリプションを登録します。 guard-duty-notification を選んで サブスクリプションの作成 ボタンから登録します。 今回は特定のメールアドレス宛に通知することにしました。設定したメールアドレス宛に送信されてくる確認メールから承認しておきます。 これで通知先の作成ができました。 次に EventBridge のルールを作成していきます。 EventBridge を検索して EventBridge の画面にいきましょう。 初回の場合はルールを作成するボタンから EventBridge のルールを作成します。 内容は以下で作成しました。 名前 guard-duty-notification イベントパス default ルールタイプ イベントパターンを持つルール イベントソース AWS イベントまたは EventBridge パートナーイベント サンプルイベントタイプ AWS イベント サンプルイベント GuardDuty Finding Creation method Use pattern form イベントパターン イベントソース AWS のサービス AWS のサービス GuardDuty イベントタイプ GuardDuty Finding ターゲット 1 ターゲットタイプ AWS のサービス ターゲットを選択 SNS トピック トピック guard-duty-notification ※先程作成したトピックを設定します タグ 今回は省略 これで通知設定ができました。 通知が送られるか試してみましょう。 GuardDuty のページに戻り左メニューの 設定 を開きます。 検出結果サンプルの作成 ボタンからサンプルを作成しましょう。 画面上部に 検出結果サンプルが正常に生成されました のメッセージが出たら左メニューの 検出結果 を開きます。 検出結果タイプに 例 とついた結果がたくさん出力されています。 SNSに設定したメールを見るとたくさん通知されいることが確認できますね。 おわりに いかがだったでしょうか? AWSの理解度にかかわらず、不正利用がないようにアカウントを保護する必要があるわけですが、この GuardDuty を利用してみてはいかがでしょうか? (さらにこのメール通知を見逃さないようなサービスが出るといいのですが・・・ 今後のAWSさんに期待ですね!) ではまた。 The post AWSユーザなら知っているべきアカウント保護方法 – GuardDuty編 first appeared on miracleave Tech Blog .
アバター
はじめに こんにちはあるいはこんばんは! 残暑もようやく影を潜め、秋らしくなって過ごしやすくなりましたね!季節も変わって心機一転、新たな取り組みや勉強も始める方もいるかもしれません。 僕も新たにRustでも入門してみようかなと読みふけっています。 ところで皆さんは自分で開発したツールやアプリのREADMEは書いていますか? 自分用で開発すると意外とちゃんと書ききれていなかったりするのではないでしょうか? 書き方がいまいちわからないとか、何が正解なのかと手をこまねくかもしれませんが、みなさんのアウトプットをより良くするためにもREADMEを残しておくことはとても大事なことです。 ということでREADMEを書く上で意識すると良いところをまとめてみました。 READMEとはなにか ではまず、READMEとはなにか。 簡単にいうと、プロジェクトを適切に使用するためのガイドを担うワンストップドキュメントです。 これはつまり、README一つでそのプロジェクトを説明することができるドキュメントであるということです。 多くは、プロジェクトのインストール方法、実行方法や実行環境などを説明します。 誰に向けて書くものか (個人的にこれが一番難しいのですが) ドキュメントと呼ばれるものを書く上で重要な要素の一つは、「読み手の事を考えること」です。 そのドキュメントはどんな人のためのもので、どんな人が読むものなのか。 これはREADMEに限った話ではないですよね。 丁寧なドキュメント書いてくれる方はこの辺をよく心がけてくれているなぁと感じることが多いです。 自身が作成したプロジェクトやアプリを対象にした場合ですと、以下のようにカテゴライズされると思います。 エンドユーザー ( End users ) 属性としては、あなたのプロジェクトやアプリ、ツールの利用者。機能の側面を重視する。 技術的な知識を有していない方。技術的な実装に対する関心は薄い。 テクニカルユーザー ( Technical users ) 属性としては、技術者あるいは技術的な面に関心を持つ方。もしくは自身のプロジェクトに統合させたり、APIやライブラリとして使いたい方。提供される機能に対する関心は強いが、実装内容については関心が薄い。 貢献者 ( Contributors ) 属性としては、あなたのプロジェクトと関わり・交流を持つ方。 プロジェクトやアプリ、ツールをインストールするためのサポート、バグや新しい機能を提案する方。あるいは拡張機能を含むプルリクエストを送信したいユーザーや経済的にプロジェクトを支援したい方。 提供先によってはもっと細かく定義する必要があったりすると思いますが、これらの対象を一つのグループとして含んで考えるといいですね。 また、内部での資料でない限り、言語は英語で統一するようにしましょう。 母国語のみのREADMEは公開するにあたり、親切ではないので、、 フォーマットと書き方 READMEはMarkDownで記述しましょう。 多くのホスティングサービス(github、gitlabなど)でMarkDown構文がサポートされていますし、実際みなさんが目にするREADMEのほとんどがMarkDownで記載されていると思います。 「 人々は読むのではなく、スキャンする 」という公理に基づき、Markdownを適切に使用することで、ドキュメントに視覚的な構造を与え、ユーザーがファイルの内容をスキャンしやすくすることができます。 How Users Read on the Web Summary: They don’t. People rarely read Web pages word by word; instead, they scan the page, picking out individual words and sentences. By Jakob Nielsen on September 30, 1997 Topics: Writing for the Web https://www.nngroup.com/articles/how-users-read-on-the-web/ (余談ですが、先日ドキュメントの書き方を学んでいた際にも似たような内容で「ドキュメントはすべて読まれることを想定してはいけない」旨が記載されていました。) では、どう書けばよいのか。 テキストをオンラインで読む方法、つまりは 「スキャンする」 、 「検索する」 に適応させるためのWeb用のいくつかの基本原則に沿って書くようにします。 短い段落 を使用する。3~5行程度が目安です。各段落には1つの概念しかないようにします。そうすることで、スキャニングがしやすくなります。 箇条書きまたは番号付きのリスト を使用してください 。 click hereリンク (いわゆる「こちらをクリック」)は使用しないでください。意味のあるテキストを使用しましょう。 click hereリンクを使用すると、ユーザーはリンクの前後の脈絡や文脈を読む必要があります。 キーワードや文章の段落 は太字で強調する。下線はリンクと混同される可能性があるため、使用しないようにしましょう。 各段落で最も重要な情報 から始める。文章には逆ピラミッド構造を使用しましょう。 読み手にとって、最も重要な内容から始め、その後に追加の情報を提供するような構成にしましょう。 以下については、今回挙げた基本原則の中でも紹介されていますが、いずれも目を通しておくと理解が深まると思います。 click hereリンクを使ってはいけない理由 逆ピラミッド構造 READMEの内容 誰のために書くか、提供するドキュメントの構造・形式についての慣習が整理できたところで推奨される構成で内容を整理します。 提供するプロジェクトがどのようなものか簡単に説明する。 インストール方法と実行方法を記載する。 訪問者にどのようにプロジェクトに参加し、どのように協力できるかを提供する。 この構成は、これまで紹介した各カテゴリーのユーザーから期待される、プロジェクトへの関与の度合いに沿っています。 例えば、エンドユーザーはただプロジェクトについて知りたいだけですので、1と2が対象になりますね。 多くのプロジェクトでは上記以外に用意すべき内容があると思いますので、必要に応じて内容の要素は増やしても良いでしょう。 いずれにせよ、上記の構造は最低限適用させるべきと考えます。 具体的な内容はプロジェクトの動機や経緯、解決する課題、使用することへのメリット、あるいはプロジェクトで学んだ内容などから考えると記載しやすいのではないでしょうか。 ここまでの内容を踏まえて、READMEに以下のような項目を用意するとよいかと思います。 プロジェクトのタイトル プロジェクトの説明 目次 プロジェクトのインストール方法、実行方法 プロジェクトの使用方法 謝辞(貢献してくれたチームメンバーの名前、参考にしたプロジェクトへのリンクや資料などの情報) ライセンス プロジェクトのステータスバッジ プロジェクトへの貢献方法、行動規範 また、READMEを自動で作成してくれるオープンソースプロジェクトを利用するのも良いかと思います。 readme-md-generator readme.so さいごに 最後になりますが、READMEに唯一の正解は存在しません。すべてのプロジェクトに独自な考え方を含んだ、ユニークなガイドになって良いと思います。 ですが、今回挙げたようなドキュメントとしてのルールや慣習に沿うことは一定のクオリティを保つ上で遵守すると良いですね。 優れたREADMEをまとめたリポジトリもあったので、こちらもぜひ参考にしてみてください。 awesome-readme ここまで読んでくれてありがとうございました! それではまた! The post 俺たちのREADMEは「読まれない」 first appeared on miracleave Tech Blog .
アバター
はじめに こんにちは! 最近一人暮らしをしてバタバタしている新垣です! 業務でPythonを使用していた時期があり、趣味レベルでもPythonを使ってみたいなと思いました。 なにかできないかなと思い、そういえばPythonってスクレイピングする言語として有名だったなと思い、最近触り始めました。今回Pythonのスクレイピング初心者が実際に触ってみて、便利だと思った所について書ければ良いかなと思い今回のブログを投稿させていただきます。 筆者について  高校・大学でプログラミングをかじり、2021年4月にmiracleaveに入社した新卒2期生です。 スクレイピングとは スクレイピングとは、WebページやWeb上で公開されているデータについて、ソフトウェアで処理しやすい形に整形したり必要な部分を抽出することをWebスクレイピングと言います。 https://e-words.jp/w/%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0.html 昨今業務効率化が叫ばれており、Webページをいちいちダウンロードしたりするなど非効率なことをせずPythonを使ってそこら辺を自動化しようみたいな動きが出ています。エンジニアのみならず、ビジネスマンが普段の業務を効率よく行うためにPythonを学んでいくことも近年流行っています。 Seleniumについて 今回スクレイピングするライブラリはSeleniumを使用します。 PythonのスクレイピングのライブラリはScrapyやBeautifulSoupなど他にいくつかありますが、今回はSeleniumを使おうと思います。Seleniumは主にWEBスクレイピングでは、JavaScriptが使われているサイトからのデータの取得や、サイトへのログインなどに使われています。 Seleniumは、標準ではインストールされていませんので各自個人でインストールしましょう。 インストールするには、下記コマンドを打ち込めばインストールできます。 pip install selenium ChromeDriverのインストール 今回WebブラウザはGoogle Chromeを使います。Chromeを操作できるようにするために、ChromeDriverをダウンロードします。 ChromeDriver とは、Chromeを操作するために必要なソフトで、Seleniumを使用してのWebスクレイピングには必要不可欠な存在です。 ここでChromeDriverをインストールする際の注意点なのですが、MacとWindowsではインストールの仕方が違うのでここは注意しておきましょう。 〜ChromeDriverのインストール Mac編〜 MacのChromeDriverのインストールは簡単です。ターミナルに以下のコマンドを打ち込むだけでインストールができます。 brew install chromedriver 〜ChromeDriverのインストール Windows編〜 下記URLからダウンロードし、作業ファイルと同階層に  chromedriver.exe  を置いてください。 https://sites.google.com/a/chromium.org/chromedriver/downloads 完成ソース from selenium import webdriver USER = 'test'  PASS = 'testpass' # Mac browser = webdriver.Chrome() # Windows browser = webdriver.Chrome('chromedriver.exe') browser.get('https://anime-bulletin-board.herokuapp.com') elem_username = browser.find_element_by_name('session[name]') elem_username.send_keys(USER) elem_password = browser.find_element_by_name('session[password]') elem_password.send_keys(PASS) browser_from = browser.find_element_by_name('commit') browser_from.click() print("ログイン成功です!") ※今回自動ログインするサイトのURLは大学生時代に自分が趣味で開発したサイトで、低クオリティのサイトなのでそこはご了承ください。。。 解説 ①seleniumの読み込みと今回ログインするサイトのユーザー名とパスワードを”USER”と”PASS”に設定します。 from selenium import webdriver USER = 'test'  PASS = 'testpass' ②今回使用するブラウザ(chrome)の宣言を行います。MacとWindowsでは宣言するソースが違うので注意してください。そのあとbrowser.getでログインしたいサイトのURLを指定してあげます。 # Mac browser = webdriver.Chrome() # Windows browser = webdriver.Chrome('chromedriver.exe') browser.get('https://anime-bulletin-board.herokuapp.com') ③ここでサイトのフォームの要素を取得して、①で設定したユーザー名とパスワードを設定してあげます。 elem_username = browser.find_element_by_name('session[name]') elem_username.send_keys(USER) elem_password = browser.find_element_by_name('session[password]') elem_password.send_keys(PASS) find_element_byでclass属性やname属性を取得できます。今回はサイトにあるformがname属性なのでfind_element_by_nameを使用します。要素を確認したい場合は、Chromeの検証ツールを使用すれば確認することができます(検証ツールは画面を右クリックした時のメニューにあります)。 次に”send_keys”を使用することで、取得した要素に値を設定することができます。 ④要素を取得してログインボタンをクリックする browser_from = browser.find_element_by_name('commit') browser_from.click() print("ログイン成功です!") ③と同様に検証ツールを使用して要素を確認します。 browser_from.clickでサイトのログインボタンをクリックします。”click”を使用すればその要素をクリックすることができます。 あとはコンソールに「ログイン成功です」の文字が表示され、ブラウザでもログインができている状態になります。 動きがないただの画像でわかりくいかもしれないですが、下記のようなイメージです。 Ⅰ初期状態 Ⅱユーザー名・パスワード自動入力 Ⅲログインボタン押下後、ログイン成功画面 最後に 今回のPythonのライブラリのSeleniumを使用したブラウザ操作はいかがでしたか。今回はログインのみでしたが他にもログインした後の情報を抽出して情報を取得するなどもできます。ただし注意していただきたいのは スクレイピングはサイトによっては規約違反になります 。自分もAmazonやTwitterでスクレイピングしようと思ったら規約違反でできないと知って、ちょっとショックでした。なのでスクレイピング行為をする時はそのサイトがスクレイピングを許容してくれるのかしっかりと調査が必要です。 ルールを守って楽しくスクレイピング!! The post PythonのSeleniumを使ってサイトを自動的にログインしてみよう first appeared on miracleave Tech Blog .
アバター
こんにちは、竹村です!ELDEN RINGが日本ゲーム大賞で大賞を獲得しましたね!自分はずっとDLCが出るのを心待ちにしています。。。 さて、前回「 DockerでPython×Django×Vue.jsの環境を構築する(サーバー起動編) 」で、フロントエンドとバックエンドのサーバー起動までの設定周りについて書きました。 今回は、2つのサーバー間の通信を行うために必要なCORS(Cross-Origin Resource Sharing:オリジン間リソース共有)設定について触れていきたいと思います。 なお、フォルダやアプリ構成については前回の記事 DockerでPython×Django×Vue.jsの環境を構築する(サーバー起動編) を参照してください。 CORSとは CORS(Cross-Origin Resource Sharing:オリジン間リソース共有)とは、異なるオリジン(プロトコル+ホスト+ポート)の間で通信を許可し、リソースを共有する事です。 詳しくは割愛しますが、以下の記事がとても良くまとまっていました! CORSの理解を深める zenn.dev django-cors-headers DjangoでCORSを扱う為に、django-cors-headersをインストールします。 requirements.txtに以下を記載し、Dockerコンテナを立ち上げます。 django-cors-headers==3.11.0 setting.py settings.pyを編集していきます。 INSTALLED_APPSとMIDDLEWAREに、以下を追記します。 INSTALLED_APPS = [   ・・・  'corsheaders', ] MIDDLEWARE = [   ・・・ 'corsheaders.middleware.CorsMiddleware', ] 次に以下を追記しましょう。 CORS_ALLOWED_ORIGINS = [ 'http://localhost:8080', 'http://127.0.0.1:8080', ] CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINSは、通信を許可する対象のIPとポートを記載します。 今回、フロントエンド側で使用するポートは8080ですので(前回記事のdocker-compose.ymlを参照)、 ‘http://localhost:8080’と記載しています。 CORS_ALLOW_CREDENTIALSは、Trueに設定する事でCookie をクロスオリジンの HTTP リクエストに含めることができます。詳しくはdjango-cors-headersのドキュメントをご覧ください。 django-cors-headers django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS). pypi.org 終わりに Docker環境でふたつの異なるサーバーを立ち上げて構築するにあたって、最初につまずいたのがCORS認証でした。 setting.pyに記載する環境変数については情報が古くなる可能性もあるので、公式ドキュメントを参照する事を推奨します。 この記事が、同じような境遇の方の一助となれば幸いです。 ではまたお会いしましょう! The post DockerでPython×Django×Vue.jsの環境を構築する(CORS認証編) first appeared on miracleave Tech Blog .
アバター
こんにちはこんばんわ!積ん読が増え続けている佐々木です! ここ最近フロントエンド開発時にモックをつかうことがあり、そこではモックにjson-serverを使っていました。 ですが、個人的にはあまり使い勝手が良くなかったので「もっと便利なのあるだろ〜」と思って調べてみたら「MSW(Mock Server Woker)」という結構イケてるライブラリがあったので実際に使ってみました! MSW(Mock Server Woker) MSWはService Workerを通じてAPIリクエストをインターセプトし、モックのレスポンスを返すことができるライブラリです。 ローカル開発以外にJestなどのテストやStoryBookにも利用することができます。 Introduction What is Mock Service Worker? mswjs.io json-serverとは違って、別プロセスを立てる必要がないというのが個人的な推しポイントです。 公式ドキュメントより、本番環境ではMSWの利用を勧めておりませんのでご留意ください。 環境 2022/8/27時点 MacBook Pro (2019late) Monterey v12.5 私はReact(TypeScript)でやってみましたので以下が主要な内容です。 node v18.2.0 react v18.2.0 typescript v4.7.4(後述のmswの兼ね合いで4.2.x <= 4.7.x で指定する必要がありました) MSWのinstall ではinstallから始めていきます(記事作成時、latestはv0.45.0でしたが念の為指定します) npm install msw@0.45.0 --save-dev install後にはmock用のディレクトリとhandlers.tsを作成しましょう。 mkdir src/mocks && touch touch src/mocks/handlers.ts handlers.tsの中身は以下のように記載します。 // src/mocks/handlers.ts import { graphql, GraphQLVariables } from 'msw'; export const handlers = [ graphql.query('GetUserInfo', (req, res, ctx) => { const authenticatedUser = sessionStorage.getItem('is-authenticated'); if (!authenticatedUser) { return res( ctx.status(400), ctx.errors([ { message: 'Not authenticated', errorType: 'AuthenticationError', }, ]) ); } return res( ctx.status(200), ctx.data({ user: { auth: authenticatedUser, firstname: 'USER_FIRSTNAME', lastname: 'USER_LASTNAME', }, }) ); }), graphql.mutation('Login', (req, res, ctx) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const username: string = req.variables.username; sessionStorage.setItem('is-authenticated', username); return res( ctx.status(201), ctx.data({ login: { username, }, }) ); }), ]; API定義 次はAPI定義を選択します。APIは「REST」と「GraphQL」から選択することができます。 今回は「GraphQL」で進めてみます。 GraphQLでのモックの場合は、GraphQLClientを設定する必要があるようです。 Since we will be working with a GraphQL API, we need to have a GraphQL client installed and configured in our application. We need that client primarily to dispatch queries and mutations. Please refer to the getting started steps of the respective client. https://mswjs.io/docs/getting-started/mocks/graphql-api#pre-requisites 私はApolloClientを使用することにします。 npm install @apollo/client graphql Get started with Apollo Client www.apollographql.com Service Worker -Browser- 次はブラウザでのリクエストをインターセプトさせるためのService Workerを作成します。 Service Workerは以下のコマンドを実行することで自動で作成されます。 なお、<PUBLIC_DIR>の部分は各JavaScriptプロジェクト毎にディレクトリを指定されていますので従いましょう。 ( ReactやVue.jsなどでは public , GatsbyJSでは static に読み替えてください。) npx msw init <PUBLIC_DIR> --save ex.react) npx msw init public/ --save コマンドを実行すると、指定したディレクトリ内に「mockServiceWorker.js」が作成されます。 Service Workerの構成を設定します。 touch src/mocks/browser.ts browser.tsには以下の内容を記載します。 // src/mocks/browser.ts import { setupWorker } from 'msw' import { handlers } from './handlers' export const worker = setupWorker(...handlers) 設定についてはこれで終了です。 画面の作成 簡単な画面を作成して正常に動作するか試していきます。 まずApolloClientの設定を記載します。 touch src/ApolloClient.ts // src/ApolloClient.ts import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client' const cache = new InMemoryCache() const link = new HttpLink({ uri: 'http://localhost:3000/graphql', fetch: (...args) => fetch(...args), }) // Isolate Apollo client so it could be reused // in both application runtime and tests. export const client = new ApolloClient({ cache, link, }) 次に入力フォームを作成します。 touch src/LoginForm.tsx // src/LoginForm.tsx import React, { useCallback, useState } from 'react'; import { gql, useMutation, useQuery } from '@apollo/client'; const LOG_IN = gql` mutation Login($username: String!) { login(username: $username) { username } } `; interface LoginSessionDetails { id: number; username: string; } // login form export const LoginForm = () => { const [username, setUserName] = useState(''); // mutation const [Login, { data, loading, error }] = useMutation<{ Login: LoginSessionDetails }, { username: string }>(LOG_IN, { variables: { username }, }); const handleUsernameChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { setUserName(event.target.value); }, []); const handleFormSubmit = useCallback( (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); Login({ variables: { username, }, }).catch((err) => console.log(err)); }, [username, Login] ); if (loading) { return <p>Loading...</p>; } if (error) { return <p>Error while fetching the user data ({error.message})</p>; } if (data) { return <UserInfo />; } return ( <div> <h1>Login</h1> <form onSubmit={handleFormSubmit}> <div> <label htmlFor='username'>Username:</label> <input id='username' name='username' value={username} onChange={handleUsernameChange} /> <button type='submit'>Submit</button> </div> </form> </div> ); }; interface UserInfo { firstname: string; lastname: string; } interface User { user: UserInfo; } const GET_USER_INFO = gql` query GetUserInfo { user { firstname lastname } } `; const UserInfo = () => { // queries const { loading, data, error } = useQuery<User>(GET_USER_INFO); if (loading) return <p>Loading ...</p>; return ( <> {data && ( <> <h3>FirstName:</h3> <div>{data.user.firstname}</div> <h3>LastName:</h3> <div>{data.user.lastname}</div> </> )} {error && ( <> <div>{error.message}</div> </> )} </> ); }; 次にindex.tsxを修正します。 // src/index.tsx import React from 'react'; import { ApolloProvider } from '@apollo/client'; import { client } from './ApolloClient'; import { LoginForm } from './LoginForm'; import { createRoot } from 'react-dom/client'; import { worker } from './mocks/browser'; const container = document.getElementById('root'); const root = createRoot(container!); // createRoot(container!) if you use TypeScript // Start the mocking conditionally. if (process.env.NODE_ENV === 'development') { worker.start().catch((err) => console.log(err)); } root.render( <React.StrictMode> <ApolloProvider client={client}> <LoginForm /> </ApolloProvider> </React.StrictMode> ); これで試してみる環境は整いましたので、ブラウザで確認していきます。 画面確認 http://localhost:3000/ にアクセスして検証ツールを開きます。 検証ツールのコンソールを開いて、以下のような表示がされていれば正常に動作しています。 現在の画面では、フォームに入力してSubmitボタンを押すと、mutation、queryを実行します。 入力してSubmitボタンを押すと、以下のような画面になることを確認出来ます。 ちなみになにも入力せずにSubmitボタンを押すとエラーを返すようにしています。 作成物のリンクはこちらです。 GitHub - daisuke8000/msw-sample Contribute to daisuke8000/msw-sample development by creating an account on GitHub. github.com 最後に 基本的に公式のGettingStartedに従った内容になりますが、すごいシンプルに実装できました。 皆さんのフロントエンド開発のモック検討時の選択肢にぜひ加えてみてください!! それではまた〜! The post フロントエンド開発のモックにMSWという選択肢 first appeared on miracleave Tech Blog .
アバター