5 pontos por GN⁺ 2025-05-02 | 1 comentários | Compartilhar no WhatsApp
  • Ao criar o hn.unlurker.com, adicionei ao cliente da API do HN uma função scan para receber todos os items em ordem e baixei localmente todos os dados do Hacker News
  • Durante a execução de hn scan --no-cache --asc -c- -o full.json, o download travou algumas vezes, mas graças ao scan com retomada consegui obter, algumas horas depois, um arquivo JSON de 20 GiB
  • Depois de transformar o JSON em tabela com read_json_auto do DuckDB, agreguei com SQL usando text ILIKE e média móvel de 12 semanas a proporção de menções a Python, JavaScript, Java, Ruby e Rust
  • Mesmo só com grep, confirmei que a expressão “correct horse battery staple” apareceu 231 vezes no Hacker News, e o DuckDB parece se encaixar muito bem nesse tipo de análise pontual nessa escala
  • Com uma cópia local de todos os dados, dá para analisar o conteúdo histórico do Hacker News de várias formas, mas este projeto termina aqui e o próximo passo fica para outra pessoa continuar

Baixando todos os items do Hacker News

  • Para criar o hn.unlurker.com, escrevi um cliente da API do HN
    • Já existiam vários clientes, mas eu queria experimentar recursos mais recentes do Go e linters em um projeto novo
    • Na API do HN, comentários e histórias são chamados de items
  • O cliente consegue buscar items ativos e listas de items, entre outras coisas
    • No projeto real eu só precisava dos items recentes, mas adicionei a função scan para deixá-lo mais completo
    • O scan baixa os items em sequência, do 0 até o mais recente ou no sentido inverso
  • Como o download completo parecia ser da ordem de dezenas de GiB em JSON, e não de muitos milhares de GiB, resolvi tentar
hn scan --no-cache --asc -c- -o full.json
  • O download travou algumas vezes e eu interrompi com CTRL-C, mas como o scan é retomável, ele terminou algumas horas depois
  • O resultado é um arquivo JSON de 20 GiB contendo tudo o que já aconteceu no Hacker News
  • Se rodar o mesmo comando de novo, dá para preenchê-lo novamente com os dados mais recentes

Analisando os dados locais com DuckDB

  • No começo, fiz buscas simples com grep
    • A expressão “correct horse battery staple” apareceu 231 vezes no Hacker News
    • A ocorrência mais recente, no momento da escrita, era um item publicado “hoje”
  • Depois tentei analisar com DuckDB
    • O DuckDB é um motor de execução analítica rápido e embarcável, também disponível como ferramenta de linha de comando
    • A nova UI tornou o uso mais fácil até para iniciantes, e um LLM ajudou a escrever as consultas SQL
  • Os dados em JSON foram carregados no DuckDB da seguinte forma
CREATE TABLE items AS
SELECT *
FROM read_json_auto('/home/jason/full.json', format='nd', sample_size=-1);
  • A consulta de exemplo agrupa os items por semana e calcula a proporção de items que incluem determinadas palavras em relação ao total
    • python, javascript, java, ruby, rust são buscados com text ILIKE
    • Para cada proporção, é calculada uma média móvel de 12 semanas
  • Da mesma forma, também foram visualizados termos relacionados a bancos de dados
    • O gráfico de exemplo inclui a proporção média móvel de 12 semanas das menções a mysql, postgres, mongo, redis, sqlite
  • O DuckDB pareceu muito bom para analisar um conjunto de dados desse porte
  • Embora eu agora tenha uma cópia local de todo o conteúdo do Hacker News, decidi encerrar o projeto aqui

1 comentários

 
GN⁺ 2025-05-02
Comentários no Hacker News
  • Conheço dois bancos de dados com tabelas atualizadas do Hacker News que permitem rodar análises sem precisar baixar os dados antes
    BigQuery exige uma conta do Google Cloud, e as consultas provavelmente podem ser feitas no nível gratuito; basta usar bigquery-public-data.hacker_news.full
    ClickHouse não exige cadastro e permite executar consultas direto no navegador: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...

  • Fiz algo parecido tempos atrás com a conta @fesshole no Twitter/Bluesky. Baixei o arquivo inteiro e ajustei um modelo para criar confissões ainda mais malucas
    Fiquei bem orgulhoso, mas no fim percebi que eu só tinha ensinado masturbação e divórcio a uma máquina inocente
    Parecia uma daquelas cenas de filme de ficção científica em que alienígenas ou uma IA superinteligente veem a história da humanidade em velocidade altíssima e concluem que não vale a pena nos salvar

    • Sobre a parte de “masturbação e divórcio a uma máquina inocente”: imagine que alguém encontre um pendrive de uma civilização desaparecida há muito tempo e treine um modelo com aqueles dados de texto
      Se não houver nenhuma conexão com o mundo externo para esses dados, como uma pessoa ou um modelo saberia que aquele pendrive contém dados sobre masturbação e divórcio?
    • Não vejo qual é o problema com masturbação e divórcio. Cada um é uma forma de permitir que as pessoas vivam de modo mais feliz e independente, e de sair de situações incompatíveis
      Vejo ambos como positivos no geral, e sou grato por viver em uma sociedade em que essas coisas foram normalizadas
  • A consulta por Java também inclui todos os casos de JavaScript, então Java fica superamostrado

    • Da mesma forma, a consulta por Rust também acaba incluindo um monte de palavras como trust, antitrust e frustration
    • Verdade… nesse caso, talvez seja ainda mais inesperado ver uma tendência de queda
  • É surpreendente que houvesse um arquivo JSON de 20 GiB com tudo o que aconteceu no Hacker News, considerando que é um site só de texto
    Isso quer dizer que, ao longo dos 18 anos de existência do HN, as pessoas publicaram mais de 20 bilhões de bytes de texto? Dá uma média de mais de 2 MB por dia, cerca de 7,5 KB por segundo

    • 2 MB por dia não parece tanto assim. Especialmente depois do episódio do Reddit, com o “setembro sem fim” mais recente e maior chegando, é bem possível que o número de posts tenha crescido exponencialmente ao longo de alguns anos
      Além disso, uma boa parte disso provavelmente não é humana. O /newest é cheio de spam de bots
    • 7,5 KB/s, ou seja, 7.500 caracteres por segundo, não soa realista; fui calcular[0] e, na verdade, fica mais perto de 34 bytes por segundo, ou 0,03 KB/s
      Como isso inclui os metadados e a sintaxe do JSON, a quantidade real de texto deve ser ainda menor. O cálculo de “mais de 2 MB por dia” estava correto
      [0] Na verdade, quem fez a conta foi o ChatGPT, mas parece correta: https://chatgpt.com/share/68124afc-c914-800b-8647-74e7dc4f21...
    • O arquivo completo do Reddit tinha cerca de 4 TB comprimido pouco antes de removerem a API. Antes ele ficava hospedado no the-eye e, se você quiser, ainda há lugares onde dá para baixar os arquivos por torrent
      Boa parte daquilo é lixo, mas os dados iniciais, especialmente antes de 2018–2019, quando bots mais espertos apareceram, parecem valer a pena investigar
    • 20 GB em JSON é surpreendente. Tenho um arquivo SQLite com todos os dados do HN e ele tem 20 GB, então eu imaginaria que em JSON seria muito maior
    • O tamanho total, na verdade, parece pequeno. É o resultado de contribuições de centenas de milhares de membros ativos e de milhões de pessoas no total ao longo de quase 20 anos
      Pelos padrões anteriores ao Facebook, o HN provavelmente teria sido uma rede social bem grande; por ter um tamanho adequado e ser gerenciado ativamente, também é bastante valioso
      Em 2019, quando o Google+ foi encerrado, modelei a quantidade de dados de texto contribuídos naquele site
      Aqui, dados de texto exclui mídias como imagens, áudio e vídeo, além de elementos auxiliares da página como a estrutura HTML, CSS e JS
      Considerando que a taxa de participação era muito baixa e que a média dos posts era de cerca de 120 caracteres, o histórico de 7 anos de dezenas de milhões de contas ativas somava apenas alguns GiB. Havia mais de 4 bilhões de perfis registrados, mas a atividade real era muito menor
      A Archive Team fez um trabalho de preservação do Google+ em cooperação com o Internet Archive, mas de forma separada, e os resultados foram mistos. Muito conteúdo foi preservado, mas muito mais ficou de fora; quase não sobraram comentários, as threads foram cortadas em algo como os 10 itens mais recentes, e a falta de busca tornou o material em geral pouco útil. As “vanity accounts”, que usavam nomes de conta escolhidos em vez de hashes aleatórios, eram ainda menos acessíveis
      Além disso, ao tentar fazer scraping das páginas inteiras para reproduzir a forma como apareciam online, o trabalho aumentou muito a necessidade de armazenamento, ao mesmo tempo em que deixou passar muitos dos elementos que realmente tornavam o site interessante
      Mesmo quando se quer armazenar contribuições textuais de uma grande população, a necessidade de armazenamento é bastante modesta. Por exemplo, supondo uma média de 45 minutos online por dia, velocidade de digitação de 45 wpm e metade do tempo online escrevendo em vez de lendo, isso dá cerca de 1.000 palavras por pessoa por dia, ou aproximadamente 6 KiB. São 6 MiB por 1.000 pessoas, 6 GiB por 1 milhão de pessoas e cerca de 6 PiB por 1 bilhão de pessoas
      O valor real é quase certamente menor. O tempo de escrita foi superestimado e, na prática, deve ficar mais perto de 10%; além disso, a velocidade de entrada em dispositivos móveis provavelmente fica em torno de 20–30 wpm. Por exemplo, no Facebook são publicados cerca de 2,45 bilhões de “pedaços de conteúdo” por dia, e metade disso é vídeo. Assumindo 120 caracteres por post, os dados de texto somam muito menos de 300 GiB por dia, uma quantidade surpreendentemente pequena
      A maior parte dos sistemas atuais de coleta de dados e de capitalismo de vigilância é composta por dados que as pessoas não inserem diretamente, como localização, vídeo, interações online e comércio
  • Qual é a netiqueta para baixar o HN? Devo perguntar ao dang antes de gerar carga no servidor?
    Ou dá para assumir que empresas de tecnologia de bilhões de dólares já estão fazendo isso várias vezes e que nem vai chamar atenção?

    • Como o artigo também diz, o HN tem uma API e, inclusive, sem limite de velocidade. Todos os dados ficam hospedados no Firebase, uma empresa da YC, então está tudo bem
    • Existe literalmente um banco de dados público
      https://console.cloud.google.com/marketplace/product/y-combi...
    • Não dá para descartar a possibilidade de que agências de três letras estejam associando aliases do HN a nomes reais
    • O nome é Hacker News, então pelo menos hackear no bom sentido faz parte do jogo
    • Se está na web pública, milhares de bots já estão fazendo scraping
  • Já fiz algo parecido. Usei um truque com o dataset do BigQuery; por algum motivo ele continuava sendo atualizado, então exportei os dados para Parquet, baixei e fiz consultas com DuckDB

    • Isso não é um truque, é só uma escolha prática
  • “Agora que baixei localmente todo o conteúdo do Hacker News, posso treinar centenas de bots baseados em LLM para atuarem como colaboradores e, lenta e inevitavelmente, substituir todo texto humano pela saída de um vibrador de sala chinesa que ecoa e recicla o passado para sempre” — é uma piada, mas tenho medo de que um dia alguém tente fazer isso.
    Espero que isso não aconteça, mas, se acontecer, será que daria para impedir?

    • Cada vez mais acredito em uma ideia antiga que fica mais importante com o tempo: criar uma rede de confiança entre humanos, em que uma conta seja verificada por um caminho do tipo: alguém que eu não conheço confia nela, esse alguém é confiado por uma pessoa que eu conheço, e essa pessoa é confiada por mim.
      Há muitos problemas a resolver, e privacidade é um deles. Não é preciso expor as conexões aos usuários, mas, em uma implementação ingênua, elas ainda ficariam no servidor.
      Também seria possível adicionar caminhos de desconfiança com pesos negativos. Se eu desconfio de alguém direta ou indiretamente, o valor da cadeia de confiança que me liga a essa pessoa diminui.
      Por ser uma rede, o sistema poderia se ajustar sozinho contra tentativas de manipulação, mas o quão robusto ele seria continua sendo uma questão.
    • Como sabemos que isso já não está acontecendo?
      Comentários longos e substanciais geralmente ainda dá para distinguir, mas ficou muito mais difícil do que há 1 ou 2 anos. Para comentários curtos, de uma ou duas frases, acho que os LLMs já ficaram bons o suficiente para passar por humanos.
    • Nossos LLMs só conseguem dar resultados confirmados em várias fontes, então acabam produzindo apenas a resposta média de um humano.
      Em contraste, muitos comentários no HN trazem insights bastante únicos que destoam do pensamento popular médio. Se um LLM tentar imitar isso, só vai produzir bobagem.
      Se você colocar um filtro que só deixe passar respostas razoáveis e coerentes em cima dessa bobagem, as respostas ficarão entediantes e ainda assim próximas de bobagem.
      Para que as respostas sejam corretas, precisas e únicas, é preciso usar algo que não seja um LLM.
    • O HN já tem um sistema imunológico razoavelmente bom contra esse tipo de coisa. Comentários repetitivos e de baixo esforço recebem downvote, são denunciados e sofrem limitação de taxa rapidamente.
      As heurísticas de karma e velocidade do site são grosseiras em comparação com machine learning sofisticado, mas funcionam porque a comunidade é menor que a do Reddit ou do Twitter e a moderação intervém diretamente.
      Para que um bando de contas falsas de LLM “substitua” textos humanos, elas teriam que continuar postando coisas que as pessoas realmente achem interessantes. Caso contrário, seriam limitadas ou removidas silenciosamente muito antes disso.
      Mesmo mantendo algumas contas de IA vivas, o custo marginal é alto. Rodar inferência 24 horas por dia em dezenas de novos threads não é grátis, e manter a saída sem escorregar para lixo comum de SEO é surpreendentemente difícil.
      Também praticamente não há receita. Não dá para monetizar o tráfego do HN, e karma é uma moeda péssima para operadores de bots.
      Se dá para impedir um agente malicioso persistente e com recursos? Provavelmente sim, mas as contramedidas seriam as mesmas de hoje: limitação de taxa forte, limites mais rígidos para contas novas, revisão por moderadores humanos e talvez alguma análise de estilo.
      Isso seria incômodo para novos usuários legítimos, mas não fatal. No fim, o HN sobrevive porque os humanos aqui querem ler textos de outros humanos. Se os comentários começarem a soar como papagaios probabilísticos, os leitores vão ignorá-los ou denunciá-los, e os bots acabarão falando entre si.
      Escrito pelo GPT-3o.
    • A franquia Metal Gear[0], a teoria da internet morta[1] e outras coisas já previram esse rumo.
      “Em Metal Gear Solid 2, o roteiro ambicioso de Hideo Kojima foi considerado por alguns como o primeiro exemplo de videogame pós-moderno, e também recebeu avaliações de que antecipou conceitos como política da pós-verdade, fake news, câmaras de eco e fatos alternativos.”
      [0] https://en.wikipedia.org/wiki/Metal_Gear
      [1] https://en.wikipedia.org/wiki/Dead_Internet_theory
  • Acho que, nos próximos anos, muitas APIs vão começar a oferecer a opção de simplesmente retornar um arquivo DuckDB.
    Se de qualquer forma você vai carregar o JSON em um banco de dados, não há motivo para não receber um banco de dados como resposta.

    • zstd Parquet exportado de um arquivo DuckDB 1.2 comprime de 2 a 3 vezes melhor.
  • Gostaria que não usassem gráficos acumulados. Acho quase impossível não distorcer a impressão do leitor.
    É muito difícil estimar a altura de um ponto específico dos dados no meio do ruído, e eles sugerem dependências que provavelmente não existem.

    • Esse também foi meu primeiro pensamento. O autor do uPlot tem uma demo que mostra bem a armadilha: https://leeoniya.github.io/uPlot/demos/stacked-series.html
    • É verdade :( Mas, ao desenhar os mesmos dados como gráfico de linhas, havia tanta sobreposição que ficou difícil enxergar qualquer coisa.
      Na próxima vez, estou pensando em empilhar vários gráficos de linhas alinhados, cada um com uma única série por região.
    • É aí que uma abordagem 3D resolve esse problema. Se você empilhar com um pequeno deslocamento, não há nada melhor para entender grandes volumes de dados de uma vez usando tecnologia de engines de jogos em business intelligence real.
      Veja o trabalho em https://flowimmersive.com/.
    • O que acha de um gráfico acumulado com eixo y logarítmico? Alguns experimentos físicos sempre fazem assim[1], mas acho bem pouco intuitivo.
      [1]: https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PUBNOTES/ATL-...
  • Eu fiz um desses tempos atrás, e https://github.com/ashish01/hn-data-dumps foi bem divertido
    Um recurso que seria legal implementar é refletir o fato de que itens mais recentes são atualizados com mais frequência com o passar do tempo, então itens baixados recentemente viram cache obsoleto mais rápido do que itens antigos

    • É muito bom que o HN ofereça uma API assim, sem bloquear como muitos outros sites
      Eu usei uma função baseada na idade para determinar a obsolescência. No começo, ela considera obsoleto a partir de 1–2 minutos após a criação; atualiza com frequência por alguns dias; depois reduz rapidamente após a primeira semana, até tratar como imutável depois de cerca de 2 semanas
      // 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...