30分で簡単な検索ボットを構築する方法

特にモントリオールでは、アパート探しは最悪です。このガイドでは、ハントの上にとどまるボットを構築する方法を説明します。これにより、検索を何度も更新する必要がなくなります。

環境

他の都市とは異なり、モントリオールでアパートを借りるほとんどの人は同じリース期間です。新しいリースは、過去12か月の7月に開始し、6月30日に終了します。これにより、可用性や期待など、多くのことが単純化されると主張することもできますが、これは競争が激しいことも意味します。

毎日目を覚まし、開いているKijijiの10ページを更新し、すべての新しい広告について問い合わせるメールを送信していました。私はこれを昼食、夕食、そして就寝前にもう一度やります。私の回答率は低く、10%をはるかに下回っていました。誰かが返事をしたとき、彼らの答えはたいてい厳しいものでした。

私の次のステップは、アンティを上げて実際に電話を取ることでした。電話をかけることで、私のチャンスは少し良くなりました。家主の方が反応が良く、今回は通常10人未満でした。しかし、間違いなくまだ5を超えています。製図板に戻ります。

ある日、同僚にこのアパートの狩りにいつも食べられていると不平を言っていると、それは私に夜明けを告げました。私は自分のコンピューターでこの問題を解決することができました。

家に帰ったとき、Kijijiが変​​更を検索するのを監視する小さなプログラムを書きました。それらを見ると、関連情報を含むショートメッセージサービス(SMS)テキストを私の電話に送信します。この記事の残りの部分では、私がそれをどのように行ったかについて説明します。

注:チュートリアルを気にしない人のために、Kijijiスクレーパーをオープンソースリポジトリとしてここに配置しました:?

ビルディングパッド-パトロール

仕事から家に帰ったとき、ラップトップを取り出して端末を起動しました。私は24時間年中無休で、または少なくともアパートが見つかるまでプログラムを実行するので、プログラムは軽量でなければならないことを知っていました。ターミナルから実行できる単純なノードスクリプトを作成することにしました。

セットアップ

nodenpmインストールしてインストールしたとすると、ノードプロジェクトの最初のステップは、プロジェクトディレクトリ内でnpmを初期化することです。

次に、srcコードが存在するディレクトリを作成しましょう。

srcディレクトリ内に、index.jsスクリプトを配置するファイルを作成します。

あなたはそのようにそれをすることができます:

$ npm init // this will ask a few questions$ mkdir src$ cd src && touch index.js

スクリプトを書く

ソロプロジェクトを作るとき、私はフリースタイルをする傾向があります—ものを壊してからそれを修正します(おそらく学ぶための最良の方法)。私は次の指示で私の最初の思考プロセスを模倣しようとしますが、それらがいたるところにあるように見えるかどうか私に知らせてください。

私たちが最初にやらなければならないことは、Kijijiにリクエストを成功させることです。適切な応答を確実に取得できるようにするために、非常に基本的なフェッチを行いましょう。

そのためには、リクエストライブラリをインストールする必要があります。

$ npm install request-promise

次に、以下を追加しますindex.js

保存すると、実行できるように$ node src/index.jsなり、コンソールにHTMLマークアップが表示されます。ステップ1完了—簡単!

コンテンツが変更されたときにのみ気にするので、応答の簡単なハッシュを作成しましょう。このようにして、応答を比較し、ハッシュを比較できます。結果をログに記録する必要がある場合、これは生のマークアップよりもはるかに面倒ではありません。

これを行うには、次のようなハッシュツールを使用できますchecksum

$ yarn add checksum

その後:

かっこいい、これはうまくいった!1500行のHTMLが32桁に削減されました。それでは、再利用可能な関数でラップしましょう。

上記のコードは、フェッチされた値からハッシュを作成します。次に、次のフェッチで、元のハッシュと新しいハッシュを比較します。

それらが異なる場合は、を返しtrueます。これはうまくいきました…少し大きすぎました。ご覧のとおり、true毎回戻りますか?

フェッチからの応答をさらに調べると、Kijijiのヘッダーにタイムスタンプがあることがわかります。これは、ハッシュがフェッチごとに異なることを意味します。これは、ローテーション広告やその他の動的コンテンツが原因で発生した可能性があることに注意することが重要です。

上記の見落としからのポイントは、作成していないAPIを処理するときに、応答を常に注意深く検査することです。

つまり、マークアップの細かい部分にアクセスする必要があるので、応答の解析に役立つサードパーティのパッケージをインストールしましょう。Cheerioは、HTMLマークアップを取り込んで、アクセス可能なJavaScriptAPIに変換できるライブラリです。意図された目的は、jQuery開発者が使用しないようjQueryにすることでしたが、意図は過大評価されています。

私たちにとって、これはChromeデベロッパーツールの偽のセットになります。

As a pre-requisite to using Cheerio in this way, we need to know what to look for in our markup. So let’s bust open Chrome and inspect our URL.

If we inspect at the ads, we can see all search responses have the classes .search-item and .regular-ad. Perfect!

We can select those with Cheerio like so:

Just like we had planned, this spits out an array of neatly organized objects. According to Cheerio’s documentation, all attributes of an element are nested in a key called attribs. If we go back to the Chrome Developer Tools, we can see that each ad has a unique data-attribute called ID. Let’s target that — replace the code inside your checkURL function with the following:

rp(siteToCheck).then(response => { const $ = co.load(HTMLresponse); let apartmentString = "";
 // use cheerio to parse HTML response and find all search results $(".search-item.regular-ad").each((i, element) => { console.log(element.attribs["data-ad-id"]); });});

Ok great, we’re getting a list of unique ID numbers. These ID’s are the only information we care about on the page.

So let’s go back to our original plan of comparing hashes, except we’ll only hash the unique IDs:

Perfect! It’s working exactly as intended. When someone posts a new ad (or removes an old ad, a caveat of watching the order of IDs) we print true in our console. All that’s left to do it set up our SMS tool.

Sending SMS from the Terminal

This is actually much easier than it seems. To do this we’ll use a third party software called Twilio. It does a lot, but one of it’s core features is to send SMS. As a bonus, it also has great JavaScript API! To finish the tutorial, you’ll need one of their accounts — a free trial will be more than enough to play around — and maybe even get a new apartment.

Ok, so to start we need to run:

$ yarn add twilio

from there, in index.js lets add Twilio and define a new function called SMS:

const twilio = require(twilio);
// you'll need to get your own credentials for this oneconst client = new Twilio("accountID", "authKey");
function SMS({ body, to, from }) { client.messages .create({ body, to, from }) .then(() => { console.log(`? Success! Message has been sent to ${to}`); }) .catch(err => { console.log(err); });} 

This simple function takes two phone numbers (to and from) and a message (body). Instead of console logging the result of our checkURL function, we can call SMS with whatever message we want:

There you have it! Every time our script sees a change between the site hashes, it will send a text message with the URL right to your phone ?.

Happy Hunting!

The actual script that I’ve built is a little more complicated than the above example — I’ve put it up as an open source repo on GitHub.

Eventually, I’d like to make some additions to it — the first of which will be making it more generic and not just a Kijiji scraper. It’s pretty basic, so it will be a great first-time project for new contributors.

Feel free to contribute in any way you see fit ?

Also, in case anyone was wondering, I just signed a lease last Sunday. The apartment I ended up renting was from the very first update pad-patrol sent me — it was destiny ✨

I’m currently working as a software developer at luxury fashion company in Montreal. I’ve been doing that for about a year, after finishing a web dev bootcamp last summer. I spend my free time learning hot new tech and, up until a few days ago, hunting for apartments.