5 ポイント 投稿者 GN⁺ 2025-05-02 | 1件のコメント | WhatsAppで共有
  • hn.unlurker.com を作りながら書いた HN APIクライアント に、全 item を順番に取得する scan 機能を追加し、Hacker News の全データをローカルにダウンロード
  • hn scan --no-cache --asc -c- -o full.json の実行中にダウンロードが何度か止まったが、再開可能な scan のおかげで数時間後に 20 GiB の JSON ファイルを確保
  • DuckDB の read_json_auto で JSON をテーブル化したあと、text ILIKE12週移動平均 の SQL で Python、JavaScript、Java、Ruby、Rust の言及比率を集計
  • 単純な grep だけでも “correct horse battery staple” という文句が Hacker News に 231回 登場したことを確認でき、DuckDB はこの規模の単発分析にとても向いていそう
  • ローカルに全データができると Hacker News の過去コンテンツをさまざまな方法で分析できるが、このプロジェクトはここで区切りとし、次の段階は別の誰かが引き継ぐ余地として残される

Hacker News の全 item をダウンロード

  • hn.unlurker.com を作るために HN APIクライアント を作成
    • すでに複数のクライアントはあったが、新しいプロジェクトで最新の Go の機能 とリンターを試してみたかった
    • HN API ではコメントとストーリーは item と呼ばれる
  • クライアントはアクティブな item や item の一覧などを取得できる
    • 実際のプロジェクトでは最近の item だけあれば足りたが、完成度のために scan 機能を追加
    • scan は item を 0 から最新まで、または逆方向に順番にダウンロードする
  • 全件ダウンロードは数万 GiB ではなく、数十 GiB の JSON 程度だろうと見込んで試した
hn scan --no-cache --asc -c- -o full.json
  • ダウンロードが何度か止まり CTRL-C で中断したが、scan再開可能 なので数時間後に完了
  • 成果物は Hacker News で発生したあらゆる内容を含む 20 GiB の JSON ファイル
  • 同じコマンドをもう一度実行すれば、最新データで再び埋められる

DuckDB でローカルデータを分析する

  • 最初は単純に grep で検索した
    • correct horse battery staple” という文句は Hacker News に 231回 登場する
    • 最後の登場例は執筆時点で「今日」投稿された item だった
  • その後 DuckDB で分析を試した
    • DuckDB は埋め込み可能で高速な 分析実行エンジン であり、コマンドラインツールとしても提供される
    • 新しい UI のおかげで初心者でも使いやすく、LLM が SQL クエリ作成の助けになった
  • JSON データは DuckDB で次のように取り込む
CREATE TABLE items AS
SELECT *
FROM read_json_auto('/home/jason/full.json', format='nd', sample_size=-1);
  • 例のクエリでは item を週単位でまとめ、全 item のうち特定の単語を含む比率を計算する
    • pythonjavascriptjavarubyrusttext ILIKE で検索
    • 各比率について 12週移動平均 を計算
  • 同じ方法でデータベース関連の単語も可視化した
    • 例のグラフには mysqlpostgresmongoredissqlite の 12週移動平均の言及比率が含まれる
  • DuckDB はこの程度の規模のデータセットを分析するのにとても良さそうだった
  • Hacker News の全コンテンツのローカルコピーを手に入れたが、プロジェクトはここで終わりにすることにした

1件のコメント

 
GN⁺ 2025-05-02
Hacker Newsのコメント
  • まずダウンロードしなくても分析を実行できる、更新済みの Hacker News テーブルを持つデータベースを2つ知っている
    BigQuery は Google Cloud アカウントが必要で、クエリはおそらく無料枠で実行可能、bigquery-public-data.hacker_news.full を使えばよい
    ClickHouse は登録不要で、ブラウザからすぐにクエリを実行できる: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...

    • このコメントの clickhouse さえ見つけられる: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...
    • ClickHouse のリソース は本当に素晴らしい。履歴まである
      ClickHouse の HN データベースを知る前に、すでに全 JSON をダウンロードする作業を自分でやってみたことがあった
  • 以前、@fesshole の Twitter/Bluesky アカウントで似たようなことをやったことがある。アーカイブ全体をダウンロードしてモデルをファインチューニングし、さらに狂った告白を生成させた
    かなり誇らしく思っていたが、結局は無垢な機械に 自慰と離婚 を教えただけだと気づいた
    SF映画で、エイリアンや超知能 AI が人類の歴史を超高速で見て、私たちには救う価値がないと判断する場面みたいだった

    • 「無垢な機械に自慰と離婚を」という部分について、はるか昔に滅びた文明の USB メモリを見つけて、そのテキストデータでモデルを学習させるとしよう
      そのデータに 外部世界との接続 がまったくないなら、その USB メモリに自慰と離婚に関するデータが入っていると、人間やモデルはどうやって分かるのだろう?
    • 自慰や離婚の何が問題なのか分からない。どちらも人々がより幸せに、より自立して生きられるようにする方法であり、合わない状況から抜け出す方法だ
      どちらも全体としては前向きなものだと思うし、こうしたことが普通になっている社会に生きられることに感謝している
  • Java のクエリには JavaScript のすべての事例も含まれるので、Java が過大に集計される

    • 同様に Rust のクエリも trustantitrustfrustration のような単語を大量に含んでしまう
    • その通り……だとすると、減少傾向が見えるのはむしろなおさら予想外かもしれない
  • Hacker Newsで起きたあらゆる出来事を収めた20GiBのJSONファイルがあったというのは、テキストしかないサイトだと考えると意外に大きい
    HNが存在した18年間で、人々が200億バイトを超えるテキストを投稿したということか? 平均すると1日2MB超、毎秒約7.5KBになる

    • 1日2MBはそれほど多くは見えない。特にReddit騒動以降、最近かつ最大の「終わらない9月」が到来していて、投稿数がここ数年で指数関数的に増えていた可能性が高い
      しかもそのかなりの量は人間ではないはず。/newestはボットスパムだらけだ
    • 7.5KB/s、つまり毎秒7500文字というのは現実的に聞こえなかったので計算してみたところ[0]、実際には毎秒約34バイト、つまり0.03KB/sに近かった
      JSONのメタデータや構文まで含まれているので、実際のテキスト量はそれよりさらに少ないはず。「1日2MB超」という計算は合っていた
      [0] 実際の計算はChatGPTがやったけれど、正しそうではある: https://chatgpt.com/share/68124afc-c914-800b-8647-74e7dc4f21...
    • Reddit全体のアーカイブは、APIが削除される直前には圧縮済みで約4TBだった。昔はthe-eyeでホストされていて、望むなら今でもファイルをtorrentできる場所がある
      その多くはゴミだが、特により賢いボットが登場した2018〜2019年以前の初期データは見る価値がありそうだ
    • 20GBのJSONというのは驚きだ。全HNデータを収めたSQLiteファイルを持っているが、それが20GBなので、JSONならもっと大きいはずだと思う
    • 全体容量はむしろ小さく感じる。ほぼ20年にわたり、数十万人のアクティブ会員と累計数百万人の貢献の結果だ
      HNはFacebook以前の基準ではかなり大きなソーシャルネットワークだったはずで、規模がほどよく、活発に管理されていたおかげで価値も高い
      2019年にGoogle+が終了したとき、そのサイトに投稿されたテキストデータがどれくらいあるのかモデル化してみたことがある
      ここでいうテキストデータとは、画像・音声・動画のようなメディアや、HTMLの骨格、CSS、JSのような付随するページ要素を除いたものだ
      参加率が非常に低く、投稿の平均が約120文字だったことを考えると、数千万のアクティブアカウントの7年分の記録でも数GiBにすぎなかった。登録プロフィールは40億件を超えていたが、実際の活動ははるかに少なかった
      Archive TeamはInternet Archiveと協力しているが別組織としてGoogle+保存作業を行い、その成果は複雑だった。多くのコンテンツは保存されたが、さらに多くが失われ、コメントはほとんど残らず、スレッドは直近10件ほどで切られ、検索もなかったため概して使い物にならなかった。ランダムなハッシュではなく選んだアカウント名を使う「vanity accounts」はアクセス性がさらに悪かった
      しかもページ全体をスクレイピングして、オンラインで見えていた形を再現しようとしていたため、保存要件は大幅に増える一方で、実際にそのサイトを面白くしていた要素は多く取りこぼしていた
      大規模な人口集団のテキスト投稿を保存しようとする場合でも、保存要件はかなり控えめだ。たとえば1日の平均オンライン時間が45分、タイピング速度が45wpm、オンライン時間の半分だけが読むのではなく書く時間だとしても、1人あたり1日約1,000語、つまり約6KiBになる。1,000人あたり6MiB、100万人あたり6GiB、10億人あたり6PiBほどだ
      実際の値はほぼ確実にもっと低い。書く時間は過大評価されていて、実際には10%に近いだろうし、モバイル入力速度も20〜30wpm程度の可能性が高い。たとえばFacebookには1日あたり約24.5億個の「コンテンツ片」が投稿され、その半分は動画だ。1投稿120文字と見積もれば、テキストデータは1日300GiBを大きく下回る、意外なほど小さい量になる
      現在のデータ収集と監視資本主義システムの大半は、位置情報、動画、オンライン相互作用、商取引のような、人が直接入力していないデータが占めている
  • HNをダウンロードするときのネチケットは何だろう? サーバーに負荷をかける前にdangに先に聞くべきだろうか?
    それとも、もう何十億ドル規模のテック企業が何度もやっているだろうから、目立ちもしないと考えていいのか?

    • 記事にもあるようにHNにはAPIがあり、しかもレート制限すらない。全データはYC企業のFirebaseにホストされているので問題ない
    • 文字どおり公開データベースがある
      https://console.cloud.google.com/marketplace/product/y-combi...
    • 三文字機関がHNの別名に実名を結びつけている可能性も除外できない
    • 名前がHacker Newsなのだから、少なくとも良い意味でのハッキングはフェアゲームだ
    • 公開Webに載っているものなら、すでに何千ものボットがスクレイピングしている
  • 似たようなことをやったことがある。BigQueryデータセットを使うという抜け道を使ったのだが、なぜか継続的に更新されていて、データをParquetにエクスポートしてからダウンロードし、DuckDBでクエリした

    • それは抜け道ではなく、単に実用的な選択だ
  • 「これで Hacker News の全コンテンツをローカルにダウンロードできたので、何百もの LLM ベースのボットを訓練して投稿者として回し、過去を永遠に反響・再利用する中国語の部屋の振動子の出力で、あらゆる人間のテキストをゆっくりと、しかし必然的に置き換えられる」という冗談ではあるが、いつか誰かが試しそうで怖い。
    そうならないことを願うが、もし起きたら止められるだろうか?

    • 時間がたつほど重要になる古いアイデアを、ますます信じるようになっている。人間同士の信頼のネットワークを作り、あるアカウントが、私の知らない誰かに信頼され、その誰かは私の知っている人に信頼され、その人は私が信頼している、という経路で検証される仕組みだ。
      解決すべき問題は多く、プライバシーもその一つだ。つながりそのものをユーザーに公開する必要はないが、素朴な実装ではサーバーには残ってしまう。
      不信の経路を負の重みとして加えることもできる。直接または間接に誰かを信用しないなら、私とその人を結ぶ信頼の連鎖の値が下がる、という形だ。
      ネットワークなので、システムを操作しようとする試みに対して自己調整できる可能性はあるが、どれほど堅牢かは依然として未知数だ。
    • それがすでに起きていないと、どうして分かるのか?
      長くて中身のあるコメントならたいてい見分けられるが、1〜2年前よりはるかに難しくなっている。短い1、2文のコメントなら、LLM はもう人間として通るのに十分なくらいうまくなったと思う。
    • 私たち LLM は複数の出典で確認された結果しか出せないので、結局は人間の平均的な返答しか出力しない。
      一方で HN のコメントの多くは、平均的で大衆的な考えから外れた、かなりユニークな洞察だ。これを LLM に真似させようとすると、たわごとしか出てこないだろう。
      そのたわごとに、筋が通ってもっともらしい返答だけを通すフィルターを付ければ、答えは退屈になり、それでもなおたわごとに近いままだ。
      答えを正確かつ精密で、しかもユニークなものにするには、LLM ではない何かを使う必要がある。
    • HN にはすでに、この種のものに対してかなり優れた免疫システムがある。低労力で反復的なコメントは、すぐにダウンボートされ、通報され、レート制限を受ける。
      サイトのカルマや速度に関するヒューリスティクスは、派手な機械学習に比べれば粗いが、コミュニティが Reddit や Twitter より小さく、運営が直接介入するので機能している。
      LLM の偽アカウントの群れが人間のテキストを「置き換える」には、人々が本当に面白いと感じる投稿を出し続けなければならない。そうでなければ、そのはるか前に制限されるか、静かに排除されるだろう。
      AI アカウントをいくつか生かしておくだけでも限界費用は高い。24時間、新しいスレッド数十本に推論を回すのは無料ではないし、出力がありふれた SEO ゴミに滑り落ちないよう維持するのも驚くほど難しい。
      しかも収益は実質的にない。HN のトラフィックは現金化できず、カルマはボット運用者にとってはひどい通貨だ。
      資源を持つ執拗な悪意ある行為者を止められるかといえば、おそらく可能だろうが、対策は今と同じになるだろう。強いレート制限、新規アカウント上限の強化、人間のモデレーターによる審査、そして場合によっては文体分析といったところだ。
      正当な新規ユーザーには鬱陶しいだろうが、致命的ではない。結局のところ HN は、ここにいる人間がほかの人間の書いたものを読みたいから生き残っている。コメントが確率的オウムのように聞こえ始めたら、読者は無視するか通報するだろうし、ボット同士で会話するだけになるだろう。
      GPT-3o が作成
    • Metal Gear フランチャイズ[0] や、デッドインターネット理論[1] など、すでにこうした流れを予見していたものはある。
      「Metal Gear Solid 2 における Hideo Kojima の野心的な脚本は、ポストモダン・ビデオゲームの最初の事例として評価されることもあり、ポスト真実政治、フェイクニュース、エコーチェンバー、オルタナティブ・ファクトといった概念を予見していたとも評されている」
      [0] https://en.wikipedia.org/wiki/Metal_Gear
      [1] https://en.wikipedia.org/wiki/Dead_Internet_theory
  • 今後数年のうちに、多くの API が単に DuckDB ファイルを返すオプションを提供し始める気がする。
    どうせ JSON をデータベースにロードするのなら、レスポンスとしてデータベースを受け取れない理由はない。

    • DuckDB 1.2 ファイルからエクスポートした zstd Parquet は 2〜3倍うまく圧縮できる。
  • 積み上げチャートは使わないでほしい。読者の印象を歪めずに済ませるのがほとんど不可能だと思う。
    特定のデータ点の高さをノイズの中から見積もるのが非常に難しく、たぶん存在しない依存関係を示唆してしまうからだ。

    • 私も最初に思ったのはそれだった。uPlot の作者が落とし穴をよく示すデモを持っている: https://leeoniya.github.io/uPlot/demos/stacked-series.html
    • 本当だ :( でも同じデータを折れ線グラフで描くと、重なりすぎて何も見えなかった。
      次は、地域ごとに1系列だけを含む複数の折れ線グラフを並べて積むやり方を考えている。
    • この問題を解決するのは 3D アプローチだ。積み上げつつ少しオフセットを付ければ、大量データを一度に理解するために、ゲームエンジン技術を実際のビジネスインテリジェンスに使う以上に良い方法はない。
      https://flowimmersive.com/ の取り組みを見ればよい。
    • 対数 y 軸の積み上げプロットについてはどう思う? 物理実験ではいつもこうしているものもあるけれど[1]、かなり直感的ではないと感じる。
      [1]: https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PUBNOTES/ATL-...
  • 以前これを1つ作ったことがあり、https://github.com/ashish01/hn-data-dumps、かなり面白かった
    実装するとしたら格好いい機能は、最近の項目ほど時間の経過とともにより頻繁に更新されるので、最近ダウンロードした項目のほうが古い項目よりも早く古いキャッシュになる点を反映すること

    • HNが他の多くのサイトのように閉じずに、こうしたAPIを提供しているのは本当に素晴らしい
      私は古さを判断するのに経過時間ベースの関数を使っていた。最初は作成後1〜2分で古いとみなし、数日間は頻繁に更新し、その後は最初の1週間を過ぎると急速に頻度を下げて、約2週間後には不変として扱う
      // DefaultStaleIf marks stale at 60 seconds after creation, then frequently for the first few days after an item is
      // created, then quickly tapers after the first week to never again mark stale items more than a few weeks old.
      const DefaultStaleIf = "(:now-refreshed)>" +
      "(60.0*(log2(max(0.0,((:now-Time)/60.0))+1.0)+pow(((:now-Time)/(24.0*60.0*60.0)),3)))"
      https://github.com/jasonthorsness/unlurker/blob/main/hn/core...