takashiskiのブログ

覚書の殴り書き

aliexpressの注文一覧から追跡番号を抽出して17TrackのURLを生成するユーザスクリプトを組んだ

tampermonkeyでやりました。とりあえずの記録残しです。

ゴール

何かしらの手段で題のURLを手に入れることです。

方針

17trackはとても親切なことに、URL + /ja + #nums=にカンマ区切りでトラッキングナンバーを繋げれば追跡番号を登録したのと同じ扱いになります。 つまり、何とかして発送済みページから追跡番号を切り出してくることで目的はほとんど達成されたといえるでしょう。

ということで、まずは追跡番号を切り出すことを目標にします。

追跡番号が埋め込まれているところを探す

PCからアクセスした場合、各オーダーにあるtrack orderボタンにマウスオーバーすることでページ内で追跡番号を確認できます。 他には見当たらないので、まずここから取れないか探っていくのがよさそうです。

chromeのdeveloper toolでhtmlを追っていきます。

探っていった結果は以下。

div.container.me-body-container
div.row
div.col-xs-48
div.row
div.col-xs-60
5つ並んだdiv.grid-col-containerのうちの4つ目
div.me-ui-box
table#buyer-ordertable
tbody.order-item-wraper(注文ごと)
tr.order-bodyの先頭
td.order-action
button

結果としては、HTMLに埋め込まれるわけではないようでした。minimizeされたスクリプト追っていくのはやりたくなかったので、この方針は諦めました。

追跡番号を得るほかの方法を考える

次の手段として、注文番号の一覧を取得し、個別の注文ページのURLを生成、個別のページから追跡番号を取得するということを考えました。

まず注文番号を抜き出すことを考えます。

tr.order-head
td.order-info
p.first-row
span.info-body

ここら辺の材料を使って抽出すればよさそうです。

次に、個別の注文詳細ページから追跡番号を抜き取ることを考えます。

過程は省略しますが、div.logistics-numのtextContentが追跡番号のようです。具体的には、前後に謎の空白が大量にはいっているのでtrim()で削除する必要があります。

これで個別の注文詳細ページから追跡番号を抜き取ることができました。

別のURLを呼び出す

さて、ここまでで「注文一覧から注文番号を取り出す」「個別の注文ページから追跡番号を取り出す」の二つができました。 最終的には、「注文番号から生成した個別の注文ページにそれぞれアクセスし、追跡番号を取り出してURLとして結合する」をしないといけません。まずは、「注文番号から生成した個別の注文ページにアクセスする」が必要です。

幸いなことに、tampermonkeyにはGM_xmlhttpRequest()という関数が用意されていました。 どうやら、これを使ってresponseTypeにdocumentを指定すればURLのHTMLが取得できるようです。 このHTMLの中からdiv.logistics-numのtextContentを取り出せれば完了です。

まずどうやってHTMLの検索するかがわかりませんでした。適当にググったところ、innerHTMLとしてぶち込めばいいよ!という記事が見つかりました。当然、ページ全体のHTMLなのでそのまま差し込むとエラーで死にます。

適当な単語で色々検索したところ、DOMParserのparseFromString()を使えばdomとして取り扱えるようになるようです。 これで、個別の注文ページから追跡番号を取り出すことができました。

非同期との戦い

最後に問題になったのは、xmlhttpRequestが非同期処理であることです。 一度ははまったことがあるかと思いますが、非同期処理で配列に値を代入し、そのあとに非同期の外側で代入されてるはずの配列を使って何らかの処理をしようとすると、何も代入されていないので期待通りの処理が実行されないということになります。

これは当然Promiseを使うことになりますが、tampermonkeyで使えるかはわかりませんでした。chromeの制限で動かないかもよみたいな不穏なやりとりも見かけましたが、結果として特に問題なく終わりました。Promise.all()でまとめて処理して配列で受け取っておしまいです。

最後に、,で繋いでURLができました。 生成したURLを開いたところ、問題なく追跡できました。 どこかに埋め込むことも考えましたが、いいかんじの方法が浮かばなかったのでconsole.logで吐き出すにとどめています。F12でdeveloper console開いてみてください。

辛かったこと

とにかくtampermonkeyのチュートリアルとかサンプルコード的なものが見つからなかったことです。 公開されてるユーザースクリプト適当に読むしかなさそう。 たぶん基本的にはブラウザ上で動かすコードなら何でも動くんだろうなぁ、と予感はしています。

今回は以前boothの注文画面を開いたあとにclickpostで一見申し込みページを開いてペーストすると住所名前を埋めてくれるスクリプトを書いたことがあったのでなんでこれ動いているんだろう、と読みながら主にquerySelector()部分を参考にしました。 他はほぼ新規です。

ちょっとがんばったとこ

知っている人は知っていますが、aliexpressでは割と偽装発送があります*1。 これが発生すると超大量に注文したわけでもないのに複数荷物が登録されることになります。 たまたまそのケースが手元で発生したので、複数小口の荷物もすべて登録するようにしました。

課題

追跡記録の中で別の国の物流に委託されるときなどに「ここから先は別の番号な」と別の追跡番号が提示されることがあります。 これも追加したいな、と考えたのですが、aliexpress側に表示される物流情報では見れないことが多い*2ので、17track側で何とかしなければならなさそうです。あんまりないと思っていましたが、COVID-19関連ではちゃめちゃになっているのでぼちぼち起きてるので元気があればやりたいです。

この記事を読む人が欲しいもの

使い方

ソースコード

どういう形で公開するのがよいかわからなかったので、とりあえずgistに保存したのを貼ります。 必要ならMITあたりで使ってください。

gist.github.com

*1:すぐに発送できないときに、とりあえずダミーの追跡番号を登録して、あとから本来の追跡番号を登録する方式です。大体2,3日追跡確認しても見れなかったら偽装発送なので「早く正しい追跡番号おくれ」と連絡しています。

*2:特にaliexpress standard shippingなど物流業者が曖昧な場合