Windowsの再インストールをした

最近、なんだかWindowsが不穏な動きをすることが多かったので、数年ぶりにWindowsの再インストールをしてきれいにしたのでその時のメモ。

ブラウザ設定などは一通り退避しておき、書き戻した。

そのうえで、色々消えて再設定が面倒だったものをメモしておく。

ブラウザExtensions

ブラウザ設定を書き戻してみたが、Extensionsだけクリアされてしまったので、インストールしてあるExtensionsのリストを作っておくとよい。

タブなども復元できたのにExtensionsは復元されなかったのはよくわからない。

googleなどは自動ログアウトされてしまったが、セッションcookieだけで認証してそうなものたちは軒並みログイン状態も維持されていた。

Firewall設定

WindowsFirewallのoutboundをblockする運用にしているため、ブラウザやオンラインゲームなどを許可するルールを作成していたが、 これらの設定をexportするの忘れたため、アプリケーションを起動するたびに、ネットワーク接続が必要なものを個別設定するのが面倒だった。

レジストリ情報が必須のアプリケーション

OSとは別のドライブにインストールしていたが、レジストリ情報がないため、再インストールする必要が出てしまったものがいくつかあった。

これらは、レジストリのexportをしておくとよさそう。

その他

パスワードマネージャーにログインするためのパスワードがとても複雑だと入力が大変なので、一時的に入力しやすくて長いパスワードに変えるとよさそうだった。

まとめ

Windwosを再インストールすることでクリーンな環境を手に入れることができた。

もともと出ていた不穏な動きはおさまった。

半日程度の時間で終わらせられた。

次回のための知見が得られた。

crawleeでクローラを作る

最近Typescript/Playwright を利用しているので、 Playwrightを利用すると簡単にクローラが作れそう。

というところから技術調査をしたところcrawleeが見つかったので試しに利用してクローラをつくってみた話。

以下に手順を記す。

プロジェクトの作成

https://crawlee.dev/docs/introduction/setting-up

setupを参考に

npx crawlee create my-crawler

を実行する。

crawleeがインストールされていないと

Need to install the following packages:
  crawlee@3.3.1
Ok to proceed? (y)

のようにcrawleeをインストールするか聞いてくるので y でインストールする。

その後

? Please select the template for your new Crawlee project
  Getting started example [TypeScript]
  Getting started example [JavaScript]
  CheerioCrawler template project [TypeScript]
❯ PlaywrightCrawler template project [TypeScript]
  PuppeteerCrawler template project [TypeScript]
  CheerioCrawler template project [JavaScript]
  PlaywrightCrawler template project [JavaScript]

のように、どのテンプレートを利用するか聞いてくるので、上下キーで PlaywrightCrawler template project [TypeScript] を選択する。

これで、 my-crawler ディレクトリにテンプレートが作成される。

クローラの作成

クローラ本体は、 src/routes.ts に登録していく。

ファイルを見ると addDefaultHandleraddHandler 'detail' がすでに登録されている。

defaultHandler

DefaultHandlerの中身が、クローラの開始時に呼ばれる。

router.addDefaultHandler(async ({ enqueueLinks, log }) => {
    log.info(`enqueueing new URLs`);
    await enqueueLinks({
        globs: ['https://crawlee.dev/**'],
        label: 'detail',
    });
});

globs, label の組みで、 実行するクローラを変えられる。 globにマッチしたURLはこのlabelでキューイングされ、クローリング対象となる。

enqueueLinksすると、現在のページの linkを全部見てくれるので、自分でリンクを探してキューイングしなくてよいのがとても楽。

ただし、動的ページで、後でlinkが生えてくるような場合は、 playwrightを利用して、linkが生えてくるのを待ってからenqueuLinksする必要がある。

たとえば

  await page.locator("#page-1").waitFor({ state: "attached" });

などで 読み込みをまったりしている。

別のクローラを利用したければ、 enqueueLinksを複数書いて、それぞれURLパターンを登録していく。

handler for label

router.addHandler('detail', async ({ request, page, log }) => {
    const title = await page.title();
    log.info(`${title}`, { url: request.loadedUrl });

    await Dataset.pushData({
        url: request.loadedUrl,
        title,
    });
});

こちらが、 enqueueLinksで label: 'detail' としてキューイングしたURLが渡ってくるクローラ本体。

この中で好きにスクレイピングするコードを書くと良い。

もちろん、この中でも enqueueLinksでキューイングできる。 何度もキューイングしても、同一URLは2度はクローリングしないように制御されているので安心。

好きなlabelでenqueueLinksして、 addHandlerでlabelを指定してあげれば、いくらでもnestしたり、URLタイプごとに処理を分けたりできる。

開始URLの設定

src/main.ts に startsUrlsという配列が定義されているので、 そこにクローリング対象のトップURLを並べればよい。 コマンドライン引数からURLを組み立てるなどすると、汎用性が上がる。

実行

npm run start:dev

で実行できる。コンパイルしたものを利用したい場合は

npm run build

でビルドしておき、

npm run start:prod

でビルドしたものを実行できる。

終わりに

playwrightを利用すればseleniumのようにweb driverとbrowserのバージョン不一致問題など、面倒ごとなくクローラが作成できると思っていたら、crawleeというとても便利なライブラリが見つかり、

とても簡単にクローラが書けることがわかった。

わずか20行ほどコードを書くだけでクローリングできて、とても楽だった。

今後はメモリに余裕のある環境では積極的にcrawleeを使っていきたい。

controller spec から request spec へ

最近、 Rails の Controller spec を request spec に置き換えていっています。

ずっと古くから使われていたcontroller specのまま続けてきていたのを、今更ながらようやく移行し始めた。という状態です。

やりたいしやるべきだ。とタスクに積んでいたものが、ようやく実現されていっています。

なぜcontroller specからrequest specに置き換えるべきなのかという話は色々なところにあるので割愛するとして、

今いるチーム+プロダクトで書き換えるべきだと思っていた理由は2つあって、

  • controller spec だと get でも postでもなんとなく書いておけば動いてしまう。
  • committee-rails を利用してスキーマ駆動開発のようなことをしたい。

というものでした。

前者はなんとなくspecファイルを見てこれはPOSTなんだな。と思ってAPIリクエストするコードを書いていたら、じつはPUTだったため動かなった。

というようなことを経験したから。

後者は、openapi schema から逸脱したレスポンスを返してないかをチェックできるのですが、request specを前提としていた(controller specでも動くけれど、完全ではなかった)から。

まだ移行途中なので、特に後者はまだまだ途中です。

移行していく途中で、一つ、メリットに感じることも出てきました。

プロジェクトでは bullet という、DBリクエストのN+1を検出するgemを利用していますが、

controller spec だとこれが動かず、request specだと動く。というのがあり、ローカルでrspecを走らせる過程で見逃していたN+1を発見できるようになった。ということがあります。

初期実装時は存在しなかったrelationについて、増えてもincludesに追加しないまま動いており、結果的にN+1になる。といったケースは意外と見落としがちですが、それが可視化されるよになったのはおおきなメリットかなと感じています。

railsを使う上では、可能な限り、rails wayに乗るべきだと思っているので、今後も少しずつ改善を続けていきたい。