よくあるテーブル形式のコンテンツなどでデータを手元にダウンロードして使いたいとき、たいていはテーブル表示用のライブラリとCSVダウンロードがセットでありあまり困らない
ただ、データが表示だけされているがダウンロード機能がないときも存在する
仕事で施策を考える、検討するときにいったんスプレッドシートへ落としてごにょごにょやりたいことが結構あったので次のようなブックマークレットでCSV化してスプレッドシートに取り込んでいた
(() => { const downloadCsv = (filename, csvText) => { const a = document.createElement('a'); const bom = new Uint8Array([0xEF, 0xBB, 0xBF]); const blob = new Blob([bom, csvText], {type: 'text/csv'}); const url = window.URL; const blobUrl = url.createObjectURL(blob); a.download = `${filename}.csv`; a.target = '_blank'; a.href = blobUrl; document.body.appendChild(a); a.click(); document.body.removeChild(a); }; const rows = document.querySelectorAll('table.items-table > tbody > tr'); const data = Array.from(rows).map(row => { const column1 = row.querySelector(':scope > td:nth-child(1)').textContent.trim(); const column2 = row.querySelector(':scope > td:nth-child(2)').textContent.trim(); const column3 = row.querySelector(':scope > td:nth-child(3)').textContent.trim(); return [column1, column2, column3]; }); const csvData = data.map(row => row.join(",")).join("\n"); downloadCsv('hoge', csvData); })();
rows
に対象とする行をCSSセレクタで指定する(複数行)
対象の要素からさらにquerySelectorで対象とする列をそれぞれ指定する
CSSセレクタなのでクラス名やIDなどの指定でもOK(サンプルは掲載用にした)
この辺はページによって毎回変えてブックマークレットを登録して実行していた
データを取得する部分の処理
上記のブックマークレットを使うにあたり要素特定のためにCSSセレクタを使用する必要がある
- 自身のNodeからquerySelectorを使う
今回の要件だと特定の行以下に対してCSSセレクタで要素を探したいっていう感じになる
調べたら下記がヒットした
javascript - Using querySelectorAll to retrieve direct children - Stack Overflow
:scope > hgoe
なるほど、これを使えばよいのね
- 両端の空白を削除
おまけとして
特定の要素以下のtextContent
を取得すると中にタグが入ってたりとかして空白や改行が含まれていることが多い
そういうのをtrim()
で取り除く
String.prototype.trim() - JavaScript | MDN
- 子要素の順序指定
row.querySelector(':scope > td:nth-child(2)')
tr以下のtd要素の2番目を指定する
対象要素に特定可能なクラス名やIDがなかった場合でも特定することは可能
要素の確認
devtoolsで$('div.hoge')
とか打ちながら確認することが多い
自分はこんな感じで対象要素を確認しながらやっている
実行前にすでにハイライト付けてくれるのでかなり便利
おわり
こういうのがどうしてもないと困るときがちょいちょいあり、よい機会だったのでまとめた
この記事を書いていたらセレクタだけ指定する感じでChrome拡張にできそうかも? と思ったので次やってみる