\r\n\r\n
Redditは、各SubRedditのJSONフィードを提供しています。ここでは、任意のsubredditから投稿のリストをダウンロードして解析するBashスクリプトを作成する方法を紹介します。これは、RedditのJSONフィードができることのひとつです。
curlを使ってRedditとjqからJSONフィードを取得し、JSONデータをパースして、結果から必要なフィールドを抽出することにします。Ubuntuやその他のDebianベースのLinuxディストリビューションでは、apt-getを使用してこれら2つの依存関係をインストールします。他のLinuxディストリビューションでは、代わりにディストリビューションのパッケージ管理ツールを使用してください。
sudo apt-get install curl jqデータフィードがどのようなものかを見てみましょう。でcurlを使ってMildlyInteresting subredditの最新投稿を取得します。
curl -s -A “reddit scraper example” https://www.reddit.com/r/MildlyInteresting.jsonURL:-sの前のオプションはcurlをサイレントモードで実行させ、Redditサーバーのデータ以外の出力を見せないようにすることに注意してください。次のオプションとそれに続く引数、-A "reddit scraper example "は、redditがそのデータにアクセスするサービスを識別するのに役立つ、カスタムのユーザーエージェント文字列を設定します。カスタム値を設定することで、Redditが我々のレートリミットを他の呼び出し元から分離し、http429レートリミット超過エラーの可能性を低減させることができます。
以下のようにターミナルウィンドウいっぱいに出力されるはずです。
出力データには多くのフィールドがありますが、ここではタイトル、パーマリンク、URLのみに注目します。 タイプとそのフィールドの網羅的なリストは、RedditのAPIドキュメントページで見ることができます: https://github.com/reddit-archive/reddit/wiki/JSON
出力されたデータからTitle、Permalink、URLを抽出して、タブ区切りファイルに保存したいのですが、どうすればいいですか?sedやgrepなどのテキスト処理ツールも使えますが、jqというJSONデータ構造を理解できるツールもあります。 最初の試みとして、このツールを使って出力を美しく表示し、カラーコード化してみましょう。先ほどと同じ呼び出しを使いますが、今回は出力をjqにパイプし、JSONデータをパースして表示するように指示します。
curl -s -A “reddit scraper example” https://www.reddit.com/r/MildlyInteresting.json | jq .コマンドの後のピリオドに注意.この式は単に入力を解析してそのまま出力する.出力は次のようにきれいに整形され,色づけされる.
Redditから返されたJSONデータの構造を見てみましょう。後者はchildrenというプロパティを持っており、この子redditを指す投稿の配列が含まれています。
配列の各項目はオブジェクトであり、kindとdataという2つのフィールドも含んでいます。取得したいプロパティはデータオブジェクトの中にあります。jqは、入力データに適用して必要な出力を生成できる式を必要としています。コンテンツの階層構造、配列のメンバシップ、データの変換方法などを記述する必要があります。もう一度、正しい表現でコマンド全体を実行してみましょう。
curl -s -A “reddit scraper example” https://www.reddit.com/r/MildlyInteresting.json | jq ‘.data.children | .[] | .data.title, .data.url, .data.permalink’出力には、タイトル、URL、パーマネントリンクがそれぞれの行に表示されます。
jqと呼ぶコマンドについて、さらに深く掘り下げてみましょう。
jq ‘.data.children | .[] | .data.title, .data.url, .data.permalink’このコマンドには3つの式があり、2つのパイプ記号で区切られています。各式の結果は、次の式に渡され、さらに計算される。最初の式は、Reddit リスト配列以外のすべてのコンテンツをフィルタリングします。この出力は2番目の式にパイプされ、配列に強制的に取り込まれます。3番目の式は,配列の各要素に対して作用し,3つの属性を抽出する.jqとその式の構文についての詳細は、jqの公式マニュアルに記載されています。
APIコールとJSONの後処理をスクリプトに記述して、欲しいポストを含むファイルを生成してみよう。r/MildlyInterestingだけでなく、あらゆるsubredditからの投稿を取得するサポートを追加する予定です。
エディタを開いて、このコードスニペットの内容をscrape - reddit.shというファイルにコピーしてください。
#!/bin/bash if [ -z "$1" ] then echo "Please specify a subreddit" exit 1 fi SUBREDDIT=$1 NOW=$(date +"%m_%d_%y-%H_%M") OUTPUT_FILE="${SUBREDDIT}_${NOW}.txt" curl -s -A "bash-scrape-topics" https://www.reddit.com/r/${SUBREDDIT}.json | \ jq '.data.children | .[] | .data.title, .data.url, .data.permalink' | \ while read -r TITLE; do read -r URL read -r PERMALINK echo -e "${TITLE}\t${URL}\t${PERMALINK}" | tr --delete \" >> ${OUTPUT_FILE} doneこのスクリプトは、まずユーザーがサブレディット名を提供したかどうかをチェックします。そうでない場合は終了し、エラーメッセージと0以外のリターンコードを返す。
次に、第一引数をsubreddit名として保存し、出力を保存するために日付スタンプ付きのファイル名を作成します。
カスタムヘッダとスクレイピングするsubredditのURLを指定してcurlを呼び出すと、動作が開始されます。出力はjqに送られ、そこでパースされ、タイトル、URL、パーマリンクの3つのフィールドにまとめられます。これらの行は一度に一つずつ読まれ、readコマンドを使って変数に保存されます。内部whileブロックの最終行は、タブで区切られた3つのフィールドを返し、それをtrコマンドに通して、二重引用符を削除できるようにしています。そして、その出力はファイルに追記されます。
このスクリプトを実行する前に、実行権限が付与されていることを確認する必要があります。この権限をファイルに適用するには、chmodコマンドを使用します。
chmod u+x scrape-reddit.sh最後に、subredditの名前を使ってスクリプトを実行します。
./scrape-reddit.sh MildlyInteresting出力ファイルは同じディレクトリに生成され、その内容は以下のとおりです。
各行には、探している3つのフィールドがタブで区切られています。
Redditは興味深いコンテンツやメディアの宝庫で、そのjsonapiを使って簡単にアクセスできます。このデータにアクセスし、結果を処理する方法ができたので、次の操作を行うことができます。
これらはすべて、提供されたデータとシステム上で利用可能なツールを使って可能なことなのです。