Qiitaトレンドをまとめて電子書籍化する

過去記事[Qiita記事を電子書籍化する](https://qiita.com/u1and0/items/dcdd33bde9472aa5b905), [Qiitaアドベントカレンダーをまとめて電子書籍化する](https://qiita.com/u1and0/items/5919447ba965c0e2a60a) のシリーズです。

次はQiitaトレンドページの記事をスクレイピングします。

# スクレイピング

## 対象の記事を抜き出す
手始めにGo言語の先週いいねの多かった記事(トレンド)`https://qiita.com/tags/go`のページを開発ツールで見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/97d6e4bb-cb25-c4df-baa4-64cdcba40c04.png)


h2タグでくくられているところを抜き出せばいいでしょうか。

```sh
URL="https://qiita.com/tags/go"
curl -fsSL ${URL} |
    grep -oP '<h2.*?h2>'
```



```結果
<h2 class="style-cmyzn8"><span class="material-symbols-outlined style-oes20n" aria-hidden="true">book</span>About</h2>
<h2 class="style-1t4fpk1"><a href="https://qiita.com/s_w_high/items/1c11e43aca02265c52c2" class="style-2p454n">Azure App Service と Azure AD で OAuth 2.0 の認可コードフローを実装してみる</a></h2>
<h2 class="style-1t4fpk1"><a href="https://qiita.com/bikun_bikun/items/03b04e599694e68777fc" class="style-2p454n">Goのnet/http Requestでヘッダーの大文字小文字を厳密にしたい</a></h2>
<h2 class="style-1t4fpk1"><a href="https://qiita.com/oba_atsushi/items/7f9249ff22424543638f" class="style-2p454n">Goのポインタ渡しは値渡しよりパフォーマンスが良いという誤解</a></h2>
<h2 class="style-1t4fpk1"><a href="https://qiita.com/lostfind/items/ba108f48b9f2a1ecc4a9" class="style-2p454n">1年半の新サービスBackend開発の振り返り (失敗とその先)</a></h2>
<h2 class="style-1t4fpk1"><a href="https://qiita.com/tenntenn/items/d8db61720a5ce7fbdeb6" class="style-2p454n">Goのinternalパッケージを使いこなそう</a></h2>
```

簡単でしたね。


## URLだけ抜き取り
`sed -r s//\1/`のマッチパターンが使えます。

:::note info
`sed`の区切りはたいてい`/`が使われていますが、スクレイピングする上では`/`がパスセパレータによく使われていて都合が悪いです。
`sed`の区切りは`/`に限らず同じ記号が使われていれさえすればいいそうなので、ここでは`_`を使用しています。
:::

```sh
URL="https://qiita.com/tags/go"
curl -fsSL ${URL} |
    grep -oP '<h2.*?h2>' |
    sed -r 's_.*href="(https?[^"]+)".*_\1_'
```

```結果
<h2 class="style-cmyzn8"><span class="material-symbols-outlined style-oes20n" aria-hidden="true">book</span>About</h2>
https://qiita.com/s_w_high/items/1c11e43aca02265c52c2
https://qiita.com/bikun_bikun/items/03b04e599694e68777fc
https://qiita.com/oba_atsushi/items/7f9249ff22424543638f
https://qiita.com/lostfind/items/ba108f48b9f2a1ecc4a9
https://qiita.com/tenntenn/items/d8db61720a5ce7fbdeb6
```

余計なh2が一個含まれているのに気が付きませんでした。
幸いaタグやhrefやhttpといった重要ワードが含まれている行ではないので、簡単にフィルターできそうです。


```diff
URL="https://qiita.com/tags/go"
curl -fsSL ${URL} |
+   grep -oP '<h2.*?href.*?h2>' |
-   grep -oP '<h2.*?h2>' |
    sed -r 's_.*href="(https?[^"]+)".*_\1_'
```

```結果
https://qiita.com/s_w_high/items/1c11e43aca02265c52c2
https://qiita.com/bikun_bikun/items/03b04e599694e68777fc
https://qiita.com/oba_atsushi/items/7f9249ff22424543638f
https://qiita.com/lostfind/items/ba108f48b9f2a1ecc4a9
https://qiita.com/tenntenn/items/d8db61720a5ce7fbdeb6
```

無事、5行のURLを抜き出せました。

# 電子書籍化

過去記事[Qiita記事を電子書籍化する](https://qiita.com/u1and0/items/dcdd33bde9472aa5b905)でも言及したとおり、Qiita記事は末尾に`.md`をつけるとmarkdownとして表示できます。
また、過去記事[Qiitaアドベントカレンダーをまとめて電子書籍化する](https://qiita.com/u1and0/items/5919447ba965c0e2a60a)で使った技`xargs ... | curl ...` を取り混ぜ、その出力を`pandoc -f markdown ...`へとつなげますと、epubが出力されます。

```sh
THEME="Go"
TITLE="Qiitaトレンド_$(date +%Y-%m-%d)_${THEME}.epub"
# Qiitaトレンド_2022-12-25_Go.epub

curl -fsSL "https://qiita.com/tags/${THEME}" |
    grep -oP '<h2.*?href.*?h2>' |  # hrefを含んだh2タグを抜き取り
    sed -r 's_.*href="(https?[^"]+)".*_\1_' |  # URLのみ抜き取り
    xargs -I@ -n1 curl -fsSL @.md |  # Markdownの一括ダウンロード
    pandoc -s -f markdown -t epub3 --toc --toc-depth=3 -o ${TITLE}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/3d14a35e-41a2-b087-12c1-b7292a3f6b0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/6e17575d-c73a-2dbd-4c77-8b2765271045.png)

画像付き、シンタックスハイライト付きの見やすいepubですね。

:::note info
EPUBリーダーとして[Foriate](https://johnfactotum.github.io/foliate/)を使っています。
:::

:::note info
なんか上に赤字で`curl`だか`pandoc`が元っぽいエラーメッセージ出てますが、すべてのページに対してではないので、とりあえず無視します。
:::


## ShellScriptとして実行

```sh:Markdownとしてダウンロードしてepub変換
THEME=$1
TITLE="Qiitaトレンド_$(date +%Y-%m-%d)_${THEME}.epub"
# Qiitaトレンド_2022-12-25_Go.epub

curl -fsSL "https://qiita.com/tags/${THEME}" |
    grep -oP '<h2.*?href.*?h2>' |  # hrefを含んだh2タグを抜き取り
    sed -r 's_.*href="(https?[^"]+)".*_\1_' |  # URLのみ抜き取り
    xargs -I@ -n1 curl -fsSL @.md |  # Markdownの一括ダウンロード
    pandoc -s -f markdown -t epub3 --toc --toc-depth=3 -o ${TITLE}
```

```shell-session
$ ./scrape-trend.sh Python
```

実行してみたら、[あれあれ？ CPU 増やしたのに速くならないぞ？](https://qiita.com/megmogmog1965/items/6bdebc9a0a1ce168caf7)の記事が途中で切れていました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/eb41fa19-4010-6014-ae1e-e13d8b8e5af2.png)

epub化した記事。CPUの画像を最後に、次の記事が続く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/89913bbd-a0cd-9255-5489-376dae1a115b.png)

元記事。マルチコアCPUの話が続いている。

過去記事[Qiita記事を電子書籍化する](https://qiita.com/u1and0/items/dcdd33bde9472aa5b905)でも言及したとおり、Markdownからの変換はやや不安定のようです。


```sh:HTMLとしてダウンロードしてepub変換
THEME=$1
TITLE="Qiitaトレンド_$(date +%Y-%m-%d)_${THEME}"
# Qiitaトレンド_2022-12-25_Go.epub

curl -fsSL "https://qiita.com/tags/${THEME}" |
    grep -oP '<h2.*?href.*?h2>' |  # hrefを含んだh2タグを抜き取り
    sed -r 's_.*href="(https?[^"]+)".*_\1_' |  # URLのみ抜き取り
    xargs -n1 curl -fsSL |  # HTMLの一括ダウンロード
    pandoc -s -f html -t epub3 --toc --toc-depth=3 -o ${TITLE}.epub
```

話の続きが書き足されましたが、こんどは画像がすべて吹っ飛びました。


先程のpandocが吐き出しているらしいエラーのところをどうにかすればできるんじゃないでしょうか。
時間がなくなってしまったので、今できるのはここまで、乞うご期待です。