μログ

ゆるく日常と技術について書きたい

devcontainerにStarshipをインストールするメモ

 devcontainer環境でもStarshipを使いたかったのですが、シェル・ワンライナーへの理解が乏しくてインストールに苦戦したのでメモを書き残しておきます。

TL;DR

devcontainerのDockerfileに以下のコマンドを書くことでインストール可能です。

RUN curl -sS https://starship.rs/install.sh | sh -s -- --yes

なんで苦戦したか

 通常、LinuxStarshipをインストールするには以下のワンライナーを実行するのですが、インストールの過程でインタラクティブな入力が求められます(よくパッケージのインストール時に[y/N]が表示されて続行するにはyを入力する必要があるヤツ)。

starship.rs

curl -sS https://starship.rs/install.sh | sh

 今回の場合、devcontainerのビルド中、つまりdocker buildの実行中にインタラクティブな入力が求められるため、自動でyを入力してくれるようにする必要がありました。aptyumといったパッケージマネージャーを使ったインストールの場合は、-yをオプションとして指定することでインタラクティブな入力を求められずに済みます。

今回も同じようにオプションを指定したかったのですが、上記のワンライナーではStarshipのインストールスクリプトcurlで取得して、shに標準入力として渡して実行しています。インストールスクリプトのソースを見てみると、実行時にオプションで-f, -y, --force, --yesのいずれかを渡すとインタラクティブな入力がスキップされると書かれています。

https://github.com/starship/starship/blob/c40f0e7722dc4cf23dac4f19061d1342e4792002/install/install.sh#L142

なるほどと思い、以下のようにDockerfileに記載してdevcontainerを起動したのですがエラーになりました。

RUN curl -sS https://starship.rs/install.sh | sh --yes

この指定ではインストールスクリプトではなくshコマンドのオプションとして-yが渡されてしまうためです。

sh: 0: Illegal option -y

解決

 適当に「devcontainer starship」で検索したら、以下のコードを発見しました。

https://gist.github.com/jarrodldavis/928c90036273a557848f4c73d5d4e701#file-vscode-devcontainer-sh-L35

Dockerfileではないですが、ファイル名的にdevcontainerにStarshipをインストールするスクリプトのようだったので、bash -s -- --yesの意味を調べてみました。man bashを見ると以下のことが書いてあります(一部抜粋)。

--        -- はオプションの終わりを示し、それ以降のオプション処理を行いません。 -- 以降の引き数は全て、ファイル名や引き数として扱われます。 引き数 - は -- と同じです。
-s        -s オプションが指定された場合と、 オプションを全て処理した後に引き数が残っていなかった場合には、 コマンドは標準入力から読み込まれます。 このオプションを使うと、 対話的シェルを起動するときに 位置パラメータを設定できます。

 どうやら、-- --yes--yesをオプションではなく引数として扱うという意味で、-s -- --yesとすることで引数--yesを標準入力として読み込むという意味だと思われます。これにより、Starshipのインストールスクリプトのオプションとして--yesを渡すことができているという認識です(間違っていたらコメントいただけるとうれしいです)。

Starshipの公式インストールワンライナーではbashではなくshで実行するようになっていたのでそこだけ変更して実行するとうまくいきました(shコマンドでもオプションの意味は同じです)。

RUN curl -sS https://starship.rs/install.sh | sh -s -- --yes

最後に

 今回はDockerfileにStarshipのインストールを定義して不変的なイメージにしたかったので苦戦しましたが、devcontainerにStarshipをインストールして使うだけであれば、devcontainerの起動後にStarshipのインストールスクリプトを実行すれば問題ないです。また、devcontainerのpostCreateCommandを使うとコンテナビルド時の初回のみインストールスクリプトが実行されます。

GitHub ActionsでDockerイメージをビルドしてDockleを実行するようにした

 GitHub ActionsでDockerイメージをビルドして、コンテナイメージのセキュリティ診断ツールDockleを実行するようにしました。
 GitHub Actionsの設定ファイルは下記になります(Docker BuildとDockleの実行部分のみ抜粋)。

env:
  TEST_TAG: textlint-articles:1.0.0

jobs:
  dockle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: docker/setup-buildx-action@v2

      - name: Cache Docker layers
        uses: actions/cache@v3
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
            
      - name: Only docker build
        uses: docker/build-push-action@v3
        with:
          context: .
          load: true
          tags: ${{ env.TEST_TAG }}
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

      - name: Move cache
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache

      - uses: hands-lab/dockle-action@v1
        with:
          image: ${{ env.TEST_TAG }}
          exit-code: '1'
          exit-level: WARN

 ちなみに設定ファイル全体は下記の通りで、Dockerfile自体のLintツールであるhadolintも実行するようにしています(記事管理用のリポジトリなのでtextlintも)。

github.com

 Dockleを実行するうえでの工夫点は2つあります。
 1つ目は、docker/build-push-action@v3を使ってイメージをビルドしたあとにloadオプションでDockerイメージとして出力するようにしている点です。

https://github.com/docker/build-push-action/blob/master/docs/advanced/export-docker.md

 2つ目は、hands-lab/dockle-action@v1exit-codeオプションに1を設定している点です。これにより、DockleのチェックでWARNレベル以上の項目に引っかかればCIが失敗します。

参考

Power Automateのデスクトップ版でTwitterの「いいね」した画像を保存してみた

 Mirosoftが提供するPower AutomateというRPAツールを使ってみたかったので、試しにTwitterで「いいね」した画像をまとめて保存してくれるフローを作成しました。Power Automateについては、下記の記事が分かりやすいと思います。

DX時代のRPAツール Microsoft Power Automate解説 | パソコン工房 NEXMAG

 私はUdemy for Businessが利用可能な環境なため、入門として下記の講座を受講しました。こちらの講座はエンジニアではない人を対象にしているようですので、説明が非常に丁寧で分かりやすかったです。

Microsoft Power Automate Desktop 入門講座 | Udemy

 この記事で使うのはデスクトップ版のPower Automate Desktopになります。

実現したこと

 今回実現したのは、ブラウザでTwitterアカウントのプロフィールから「いいね」のタブを開き、下にスクロールしながら画像が含まれるツイートの画像を保存することです。私の場合は約7000件の画像があったのでそれらをすべて保存しました。ブラウザはGoogle Chromeを利用しました。

「いいね」画面の例

 ちなみに、少なくとも今回作成したフローは、大量の画像を保存することに実行速度という面で向いていません(7000件保存するのに24時間くらいかかりました)。ノーコードでRPAを実現できるのがPower Automateの強みなのでやむなしですが、TwitterAPIを利用してプログラムを書いたほうが大量の画像を高速に保存できると思います。

作成したフロー

下記が成果物のフローです(Robin言語版は記事の最後に示します)。

フローの解説

 まず、Google ChromeTwitterアカウントのプロフィールから「いいね」のタブを開いて下にスクロールしていくと、Google ChromeデベロッパーツールのElementsパネルから表示されるツイートのHTMLソースが入れ替わることが確認できます。
 下記にHTMLソースの一部を示します。<div data-testid="cellInnerDiv"で始まる行が各ツイートのHTMLソースで、スクロール前には1行目に表示されているツイートがスクロール後には消えていることが分かります。そして、スクロール前に2行目以降に表示されていたツイートが1行上に繰り上がっています(transformの部分を見ると分かりやすい)。

スクロール前

スクロール後

 作成したフローはこのしくみを利用して、HTMLソースの1行目に表示されているツイートの画像を保存したら、次のツイートが1行目に表示されるまでスクロールする流れになっています。

 各アクションについて軽く説明していきます。
 3~5行目では初期処理として下に100回スクロールしていますが、これは最初にHTMLソースの1行目が入れ替わるまでには多くのスクロールが必要になるからです。
 6行目以降で下スクロールしながら画像を保存するループ処理になります。ループ条件には、保存したい画像の枚数を設定します。
 7~9行目では下に15回スクロールしていて、これより多くスクロールすると画像を保存する前にさらに次の画像に入れ替わってしまいそうでした(あんまり詳細には検証していない)。
 10行目では同じ画像を2回保存しない条件分岐のために、直前の画像を保存しています。
 11~16行目では画像を取得して、まだ保存していなければ保存する処理になっています。画像のファイル名にツイートに含まれている文字と投稿者のIDを含めたかったので取得しています。また、11、15行目ではツイートに画像が含まれていない場合やツイートに文字が含まれていない場合の例外処理でラベルに飛ぶようにしています。16行目では、ツイートの文字が絵文字だったりしてファイル名には使用できない場合に、20行目で別のファイル名として保存する例外処理を設定しています。

 ツイートの画像や文字を指定する方法は下記の記事を参考にしました。

PowerAutoMateで写真投稿サイトから写真を名前を付けて保存する – オレンジの国

フローの課題

 自分が使うためにお試しで作ったので多分改善しないですが一応書いておきます。

  • ツイートに画像が2枚以上含まれている場合は保存できない
    • 条件を追加すれば解決しそう
  • 実行に時間がかかる
    • 大量の画像保存にはプログラミングしましょう
  • スクロールができないところまで読み込むと、HTMLソースの入れ替わりが起きないため最後の数枚は手動で保存する必要がある
    • 条件を追加すれば解決しそう

感想

 初めてPower Automateを使いましたが、ノーコードで簡単に操作を自動化できて便利だなと思いました。特に環境構築がPower Automateのインストールだけで済むのが良いですね。Windowsで定期的にどうしても単純作業をする必要がある場合は活用していきたいと思いました。


フローをテキスト出力したものは下記になります。フローの画面にペーストすれば(TwitterのHTMLソースの構造が変わらなければ)動くはず。

SET Count TO 0
WebAutomation.LaunchChrome.LaunchChrome Url: $'''https://twitter.com/[*****  TwitterのユーザーID  *****]/likes''' WindowState: WebAutomation.BrowserWindowState.Maximized ClearCache: False ClearCookies: False WaitForPageToLoadTimeout: 60 Timeout: 60 BrowserInstance=> Browser
LOOP LoopIndex FROM 1 TO 100 STEP 1
    MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Down}''' DelayBetweenKeystrokes: 1 SendTextAsHardwareKeys: False
END
LOOP WHILE (Count) < ([*****  保存したい画像の数  *****])
    LOOP LoopIndex FROM 1 TO 15 STEP 1
        MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Down}''' DelayBetweenKeystrokes: 1 SendTextAsHardwareKeys: False
    END
    SET OldImage TO image
    WebAutomation.GetDetailsOfElement BrowserInstance: Browser Control: appmask['Recording']['Image'] AttributeName: $'''src''' AttributeValue=> image
    ON ERROR
        GOTO Next_Loop
    END
    IF image <> OldImage THEN
        Variables.IncreaseVariable Value: Count IncrementValue: 1
        WebAutomation.GetDetailsOfElement BrowserInstance: Browser Control: appmask['Recording']['Span'] AttributeName: $'''innertext''' AttributeValue=> UserID
        WebAutomation.GetDetailsOfElement BrowserInstance: Browser Control: appmask['Recording']['Div'] AttributeName: $'''Own Text''' AttributeValue=> ImageName
                ON ERROR
                    GOTO Catch_Error
                END
        Web.DownloadFromWeb.DownloadToFile Url: image FilePath: $'''C:\\[*****  画像を保存するフォルダーのパス  *****]\\%ImageName%_%UserID%_%Count%.png''' ConnectionTimeout: 30 FollowRedirection: True ClearCookies: False UserAgent: $'''Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6''' Encoding: Web.Encoding.AutoDetect AcceptUntrustedCertificates: False DownloadedFile=> DownloadedFile
                ON ERROR
                    GOTO Catch_Error
                END
    END
    GOTO Next_Loop
    LABEL Catch_Error
    Web.DownloadFromWeb.DownloadToFile Url: image FilePath: $'''C:\\[*****  画像を保存するフォルダーのパス  *****]\\%UserID%_%Count%.png''' ConnectionTimeout: 30 FollowRedirection: True ClearCookies: False UserAgent: $'''Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6''' Encoding: Web.Encoding.AutoDetect AcceptUntrustedCertificates: False DownloadedFile=> DownloadedFile
    LABEL Next_Loop
END

# [ControlRepository][PowerAutomateDesktop]

{
  "ControlRepositorySymbols": [
    {
      "Name": "appmask",
      "ImportMetadata": {
        "DisplayName": "Computer",
        "ConnectionString": "",
        "Type": "Local"
      },
      "Repository": "{\r\n  \"Screens\": [\r\n    {\r\n      \"Controls\": [\r\n        {\r\n          \"AutomationProtocol\": null,\r\n          \"ScreenShot\":null,\r\n          \"ElementTypeName\": \"img\",\r\n          \"InstanceId\": \"e1bae100-666e-4638-a98c-f75772a74955\",\r\n          \"Name\": \"Image\",\r\n          \"SelectorCount\": 1,\r\n          \"Selectors\": [\r\n            {\r\n              \"CustomSelector\": \"html > body > div:eq(0) > div > div > div:eq(1) > main > div > div > div > div > div > div:eq(1) > div > div > section > div > div > div:eq(0) > div > div > div > article > div > div > div > div:eq(1) > div:eq(1) > div:eq(1) > div:eq(1) > div > div > div > div > div > a > div > div:eq(1) > div > img\",\r\n              \"Elements\": [],\r\n              \"Ignore\": false,\r\n              \"IsCustom\": true,\r\n              \"IsWindowsInstance\": false,\r\n              \"Order\": 0,\r\n              \"Name\": \"Selector\"\r\n            }\r\n          ],\r\n          \"Tag\": \"img\"\r\n        },\r\n        {\r\n          \"AutomationProtocol\": null,\r\n          \"ScreenShot\":null,\r\n          \"ElementTypeName\": \"span\",\r\n          \"InstanceId\": \"7f1fa613-e9da-42e9-a744-d5ceb31e81f9\",\r\n          \"Name\": \"Span\",\r\n          \"SelectorCount\": 1,\r\n          \"Selectors\": [\r\n            {\r\n              \"CustomSelector\": \"html > body > div:eq(0) > div > div > div:eq(1) > main > div > div > div > div > div > div:eq(1) > div > div > section > div > div > div:eq(0) > div > div > div > article > div > div > div > div:eq(1) > div:eq(1) > div:eq(0) > div > div > div:eq(0) > div > div > div:eq(1) > div > div:eq(0) > a > div > span\",\r\n              \"Elements\": [],\r\n              \"Ignore\": false,\r\n              \"IsCustom\": true,\r\n              \"IsWindowsInstance\": false,\r\n              \"Order\": 0,\r\n              \"Name\": \"Selector\"\r\n            }\r\n          ],\r\n          \"Tag\": \"span\"\r\n        },\r\n        {\r\n          \"AutomationProtocol\": null,\r\n          \"ScreenShot\":null,\r\n          \"ElementTypeName\": \"div\",\r\n          \"InstanceId\": \"feee3c25-5fc6-41a9-81de-2e04536235d2\",\r\n          \"Name\": \"Div\",\r\n          \"SelectorCount\": 1,\r\n          \"Selectors\": [\r\n            {\r\n              \"CustomSelector\": \"html > body > div:eq(0) > div > div > div:eq(1) > main > div > div > div > div > div > div:eq(1) > div > div > section > div > div > div:eq(0) > div > div > div > article > div > div > div > div:eq(1) > div:eq(1) > div:eq(1) > div:eq(0) > div\",\r\n              \"Elements\": [],\r\n              \"Ignore\": false,\r\n              \"IsCustom\": true,\r\n              \"IsWindowsInstance\": false,\r\n              \"Order\": 0,\r\n              \"Name\": \"Selector\"\r\n            }\r\n          ],\r\n          \"Tag\": \"div\"\r\n        }\r\n      ],\r\n      \"ScreenShot\": null,\r\n      \"ElementTypeName\": \"Web Page\",\r\n      \"InstanceId\": \"34c30439-3854-4b4a-928a-dd5583594fae\",\r\n      \"Name\": \"Recording\",\r\n      \"SelectorCount\": 1,\r\n      \"Selectors\": [\r\n        {\r\n          \"CustomSelector\": null,\r\n          \"Elements\": [\r\n            {\r\n              \"Attributes\": [],\r\n              \"CustomValue\": null,\r\n              \"Ignore\": false,\r\n              \"Name\": \"Web Page\",\r\n              \"Tag\": \"domcontainer\"\r\n            }\r\n          ],\r\n          \"Ignore\": false,\r\n          \"IsCustom\": false,\r\n          \"IsWindowsInstance\": false,\r\n          \"Order\": 0,\r\n          \"Name\": \"Selector\"\r\n        }\r\n      ],\r\n      \"Tag\": \"domcontainer\"\r\n    }\r\n  ],\r\n  \"Version\": 1\r\n}"
    }
  ],
  "ImageRepositorySymbol": {
    "Name": "imgrepo",
    "ImportMetadata": {},
    "Repository": "{\r\n  \"Folders\": [],\r\n  \"Images\": [],\r\n  \"Version\": 1\r\n}"
  }
}

LinuC レベル1 合格体験記

 LinuCのレベル1に合格したので、主に勉強方法や試験当日についての体験記を書きます。

LinuCとは

 LinuCは正式名称をLinux技術者認定試験と言い、その名の通りLinuxの技術力を測るテストです。

linuc.org

Linuxの資格には有名なLPICもありますが、こちらは全世界共通で実施されており、一方でLinuCは日本のIT市場に特化した日本独自の資格です。LinuCにはレベル1、レベル2、レベル3があり、レベル3を受験するにはレベル2に合格する必要があり、レベル2を受験するにはレベル1に合格する必要があります。また、レベル1とレベル2には2つの試験があり、両方に合格しないとそのレベルに合格したことになりません。

今回は第一歩となるレベル1の101試験と102試験の合格についてです。

勉強開始前

  • Linuxは業務で毎日使うが、コマンドは基本的なもの(ls, cd, cat, mkdir, grepなど)しか知らない
    • 基本的なコマンドでもオプションは覚えていなかったりするので、その都度ググっていた
  • sshdockerは業務でよく使うため事前に知識があり
  • 基本情報技術者試験応用情報技術者試験に合格しており、基本的なITに関する知識は持っているはず

勉強方法

 私は101試験から受験して、101試験、102試験のどちらも下記の順に行いました。

  1. 参考書を一通り読んで、実際にLinux環境でコマンドを叩いてみる
  2. 問題集を解いて、解説をすべて読む
  3. 参考書と問題集の問題をすべてもう一周する

1. 参考書を一通り読んで、実際にLinux環境でコマンドを叩いてみる

 参考書は、あずき本と呼ばれている「Linux教科書 LinuCレベル1 Version 10.0対応」を使いました。 あずき本を読みながら、登場したコマンドや設定ファイルはできるだけLinux環境で実際に確認しました。Linux環境としては、あずき本にも記載があるVirtualBoxクラウド上のLinuxサーバーを使いました。 この試験では、コマンドのオプションやファイル名をある程度暗記しなければならないので、実際にLinux環境で動作を確認することは理解を深めるうえで重要だと思いました。ただ、パーティション管理やファイルシステムの作成など、実行するための準備が面倒なコマンドはあずき本を読むだけにしました。

2. 問題集を解いて、解説をすべて読む

 問題集は、「Linux教科書 LinuC レベル1 スピードマスター問題集 Version10.0対応」を使いました。 個人的には、問題集の方があずき本よりも問題の難易度が高く感じました。問題集の解説は詳細に記載されているため、正解した問題についても一通り読んでおきました。

3. 参考書と問題集の問題をすべてもう一周する

 最後に、復習として参考書の練習問題、模擬試験と問題集の問題と模擬試験をすべて解き直しました。すべての分野で9割程度の正答率になっていたので、私はこのまま受験しました。

勉強時間

 勉強時間はよく覚えていないのですが、101試験、102試験のどちらも1ヵ月半程度だったと思います。1ヵ月半の間毎日勉強していたかというとそんなことはなく、土日に1時間ずつだけ勉強するということも多かったので、各試験30時間未満で勉強した記憶です。 ちなみに、101試験に合格してから約3ヵ月後に102試験の勉強を開始しました。

受験申し込み

 受験の申込みはこちらのページから行いましたが、初回の受験時(101試験)はEDUCO-IDとピアソンVUEアカウントを新規発行する必要があったので、少し面倒(住所を英語表記で入力など)でした。  私は自宅での受験を選択したのですが、受験日は平日の午後の時間帯から結構自由に選択できるみたいでした。申し込みの翌日から選択できる場合もあるみたいです。

試験当日

 私は他の方の合格体験記から受験環境の撮影が必要という情報を得ていたので、受験するPCデスク周りはできるだけものを置かないようにしました。とはいえ1Kに住んでいるため、同じ部屋に複数のディスプレイやPCがある状態でした。そのため、ディスプレイには無理やりカーテンや新聞紙を被せて、後述する360度撮影でバレないようにしました。

試験当日は、開始時刻の30分前から試験へのチェックイン(下準備)ができるため事前にメールで届いたリンクから実施しました。 試験の開始までに、下記の実施を要求されました。

  • 試験に使用するPCのカメラ、マイク、スピーカーが正常に動作するかの確認
  • ネットワーク環境の正常性確認
  • 不要なアプリケーションが動作していないかの確認
  • 受験者の肩から上の写真(スコアレポートの写真に使われてました)
  • 身分証明書の表面と裏面の写真を撮影(スマートフォンで実施)
  • 受験する自宅環境の前後左右を撮影(スマートフォンで実施)
  • 試験官からチャットでPCのカメラに以下を映すように指示
    • 試験に使用する机(机の上に不要なものがないかの確認)
    • その場でカメラを持ち上げて360度全方向を映す(カメラを持って回転すればヨシ)
    • (眼鏡をしていれば)眼鏡(特殊な機能がついていないかの確認)
    • 両腕(腕時計をしていないかの確認)

 上記の確認がすべて終わり、こちらから確認したいことがなければ試験の開始となりました。試験開始前と試験中の試験官とのやりとりはすべてチャットでした。また、試験中は常にPCのカメラでこちらが撮影されている状態でした。 試験時間はアンケートも含めて90分ですが、すべての問題を解き終えたら途中で終了可能だったので、私はどちらの試験も40分くらい残して終了しました。(もちろん時間ギリギリまで見直し可能です)試験問題の難易度は、あずき本の問題以上、問題集の問題以下といった感じでした。 試験終了後は、試験官とのやりとりはなく自動で撮影が停止してアンケート画面に遷移した感じでした。

総得点と分野別の正解率

 上記の勉強で受験した結果は下記でした。

101試験

102試験

  • 総得点:720点
  • 合格基準:480点
  • 分野別正解率
    • シェルとスクリプト:100%
    • ネットワークの基礎:78%
    • システム管理:100%
    • 重要なシステムサービス:77%
    • セキュリティ:100%
    • オープンソースの文化:66%

最後に

 私がLinuCを受験した目的は、Linuxが枯れている技術であり、一度体系的に学んでおけば今後の趣味や業務などで応用が効きそうと思ったからです。その第一歩としてLinuCレベル1を受けてみて、結果としては体系的に学べているなと感じました。私は普段からLinuxに触れていますが、使うコマンドというのは限られていてオプションまで覚えているのはごく一部になっています。今回の勉強を通して、初めて知ったコマンドのオプションをすべて覚えたわけではないですが、「これができるコマンドがある」という認識が得られたのは良かった点の1つだと思います。(そもそもコマンドの存在を認識できていないと調べるという発想に至らないこともあるので)
 LinuCレベル1に合格したことで、LinuCレベル2の受験資格が得られたので、モチベーション次第でLinuCレベル2にもチャレンジできればと思っています。

引越し候補地を複数駅間の移動時間から絞り込む方法のメモ

 引越し先の大まかな場所を決めるにあたって、〇〇駅までN分以内の場所!という条件で探すことはよくあると思います。  私は前回の記事(引越し先を探すために物件条件リストを作成した)で「会社の最寄り駅まで90分以内」と「東北新幹線の停車駅まで60分以内」という条件を考えました。このN分以内が小さければそれだけ候補となる駅や場所が絞られるのですが、私の場合は候補となる駅が膨大になってしまいました。こうなると、物件を探す足がかりとなる大まかな場所を決めるのがたいへんです。

 今回は、複数の駅までの移動時間をすべて満たすような、引越し候補地の絞り込み方を自分の覚書としてまとめます。

引越し候補地を絞り込む方法

 NAVITIMEの住まい検索から住みたい駅・路線をお探しの方に条件を入力するだけです。  たとえば、東京駅まで60分以内で乗り換え1回以内という条件で検索すると、下記のように該当する駅が路線と地図情報を含めて表示されます。とっても便利ですね!

realestate.navitime.co.jp

 私のように、会社の最寄り駅まで90分以内かつ東北新幹線の停車駅まで60分以内で乗り換え1回以内、という場合はNAVITIMEの住まい検索を複数ページ開きます。それぞれの条件を入力して該当する駅が表示されたら、ブラウザのページ内検索などを使用しながら照合して絞り込みました。(照合作業がそこそこたいへんだったので、うまい方法を考えたい)

引越し先を探すために物件条件リストを作成した

 来年引っ越し予定ですので、そろそろ自分が物件を選ぶ条件を明確にしたいと思い、物件の何を重視するかのリストを作成しました。

はじめに

 この記事を読む人は、筆者がどんな環境に身を置いているのかが気になると思うので、簡単に説明します。  私はいわゆる2020年度新入社員というやつですので、社会人2年目です。入社に合わせて上京して、会社の社員寮に住んでいます。学生時代は実家にいたので、自分で家を探すのはこれが初めてです。仕事はほぼフルリモートワーク(年に数回の出社)です。

 このような環境にいる人が、物件を選ぶときに重視するポイントを優先順位付けすると下記になりました。(まだ実際に物件を探してはいないので、随時更新予定です)

物件条件リスト


必須

  • 1LDK(2部屋)
  • バス・トイレ別
  • 浴室乾燥機
  • 独立洗面台
  • 室内洗濯機置場
  • エアコン付き
  • TVモニター付きインターフォン
  • クローゼット
  • シューズボックス
  • 窓に網戸付き
  • 給湯スイッチ付き
  • 最寄り駅から徒歩20分以内
  • インターネット個別契約可能

解説

 在宅勤務なので仕事部屋ともう一部屋がほしいと思い、2部屋を必須要件にしています。また、インターネット回線は仕事でも使うため、物件で共有の回線ではなく個別に契約したいです。(現在は個別契約できないインターネット無料物件に住んでおり、回線速度が低速で苦労しています...)


優先度高(8割以上満たしてほしい)

  • 家賃+管理費8.5万円以下
  • 専有面積40㎡以上
  • 鉄筋コンクリート造(頑丈・防音)
  • ベランダ付き
  • 温水洗浄機能付き便座
  • 敷地内ゴミ置き場
  • ロードバイクを室内に保管可能
  • スーパーまで徒歩5分以内
  • 会社の最寄り駅まで90分以内
  • 礼金なし

解説

 専有面積にこだわっているのは、ただ2部屋であれば良いのではなく単純に各部屋の広さも欲しいからです。通勤がほとんどないため、最寄り駅までの距離や会社までの距離はかなりゆるくしています。趣味でロードバイクに乗るので、室内に保管できるかどうかを重視します。(外に置いておくのは防犯上怖い)


優先度中(5割以上満たしてほしい)

  • 築10年以内
  • 宅配ボックス
  • 2階以上
  • NURO光と契約可能
  • 病院(内科)が徒歩10分以内
  • ドラッグストアまで徒歩10分以内
  • 24時間ゴミ出し可能

解説

身体が不調になったときに駆け込めるよう、内科は近いほうが良いかなと思います。今の家が24時間ゴミ出し可能で快適ですので、続けたいです。


優先度低(3割以上満たしてほしい)

  • 角部屋
  • 東北新幹線停車駅まで60分以内
  • 東北新幹線停車駅まで乗り換え1回以内
  • 日当たりが良い(南向きに窓がある)
  • 郵便局まで徒歩10分以内
  • 歯医者が徒歩10分以内
  • 病院(消化器科)が徒歩15分以内
  • 図書館まで徒歩30分以内
  • 散歩コースが徒歩15分以内
  • 大きめの公園が徒歩10分以内
  • 駐輪場付き

解説

 実家が東北ですので、東北新幹線の停車駅へのアクセスを気にしています。帰省は荷物が多くなりがちですので、苦労せずにたどり着きたいです。運動不足解消も兼ねてよく散歩をするので、散歩コースや公園を考慮しています。

おわりに

 今回作成した物件条件リストは、条件やその分類の基準も含めて完全に私の自己流です。  ただ、このリストのように自分が何を重視するのかを決めてメモしておくと、ネットで物件を探す場合や不動産屋で物件をオススメされた場合に、その良し悪しを判断する指針にできると思います。