De volta ao blog

Exportar JSON de Pesquisa do Google para CSV para Análise

Michael Lee
Michael Lee

Expert Network Defense Engineer

15-Sep-2026

TL;DR:

  • Um CSV de resultados de pesquisa do Google precisa do contexto da consulta ao lado de suas linhas. Preserve os tempos de solicitação e observação para que cada resultado permaneça interpretável após a exportação.
  • CSV é uma projeção de JSON. Mantenha a captura bruta, diferencie valores ausentes e nulos, e registre o significado das células transformadas.
  • Um arquivo apenas com cabeçalho precisa de um registro de execução. Capturas pendentes, falhadas, não mapeadas e presentes-vazias podem não produzir linhas orgânicas por razões diferentes.

Uma planilha pode preservar cada título e ainda perder o significado da busca que a produziu. Sem a consulta, o contexto submetido e o tempo de observação, uma linha se torna difícil de comparar ou rastrear. Uma célula em branco cria outra ambiguidade: o valor estava ausente, nulo ou foi rejeitado pela transformação?

API de Pesquisa do Google Scrapeless fornece dados de pesquisa estruturados a montante. Este guia cria um CSV de resultados de pesquisa do Google a partir de uma captura salva usando um exportador local em Python. A geração de CSV, o manuseio de planilhas e o armazenamento de arquivos são funções do programa de exemplo, não uma afirmação de que a API retorna diretamente esse formato de exportação.

Pré-requisitos e o Envelope da Captura

O exportador precisa do Python e de uma captura JSON salva com request, http_status e response. Inclua run_id, requested_at e received_at quando o coletor os registrar. Esses campos externos pertencem à aplicação de coleta, não ao wrapper de resposta nativo da API.

O fluxo de trabalho da solicitação Google Search distingue os dados de tarefa HTTP 200 de trabalhos pendentes HTTP 201. Preserve o resultado HTTP com a resposta antes de achatar qualquer coisa. Ler um campo orgânico ausente de uma resposta pendente e substituir por uma lista vazia apagaria essa distinção.

Nenhuma chave de API ou pacote de terceiros é necessária para a transformação local. Produzir uma captura de conta é uma etapa autenticada separada, que não foi realizada para este artigo. As verificações locais usam capturas sintéticas para testar tipos de dados, estados vazios, Unicode e texto sensível a planilhas.

O modelo de valor JSON preserva arrays, objetos, nulos e strings que não mapeiam diretamente para células planas. Mantenha a captura original disponível após a exportação para que analistas posteriores possam recuperar módulos omitidos e valores originais exatos.

Decida Quais Colunas Carregam Contexto e Significado

Repita o identificador da execução, os tempos de solicitação e recebimento, a consulta exata quando disponível e a solicitação serializada em cada linha de resultado. A solicitação completa preserva configurações além das colunas de conveniência fixas e torna a exportação mais fácil de auditar.

Os parâmetros de pesquisa do Google incluem configurações de país e idioma, mas o modo de URL completo pode carregar configuração dentro de url. Portanto, uma coluna q em branco não indica necessariamente uma consulta submetida ausente. Inspecione request_json; não reconstrua uma consulta eficaz adivinhando a partir de um campo de conveniência vazio.

A ordem do array orgânico e a posição retornada são colunas separadas. ordinal registra a ordem de origem baseada em zero do item. position é retido apenas quando é um inteiro positivo, com booleanos rejeitados explicitamente. O exportador não fabrica uma classificação a partir da ordem do array.

Os campos de texto e a posição possuem cada um uma coluna de estado acompanhante. missing, null e value explicam os casos comuns. invalid marca uma posição inutilizável; unexpected_type marca um valor de campo de texto não-string que é retido como JSON serializado em vez de descartado silenciosamente.

Separe a Citação CSV da Interpretação da Planilha

Um escritor de CSV lida com delimitadores e texto entre aspas; ele não decide como uma planilha avalia uma célula. Use o writter CSV do Python para vírgulas, aspas e quebras de linha incorporadas, em vez de unir strings manualmente.

O programa abre sua saída com newline="" e utf-8-sig. A primeira configuração permite que o módulo CSV gerencie os limites dos registros. A assinatura UTF-8 pode ajudar uma planilha a reconhecer texto acentuado ou não latino, mas o comportamento de importação do aplicativo de destino ainda precisa de inspeção.
Um valor que começa com um caractere de fórmula pode ser interpretado como uma expressão quando aberto em uma planilha. A orientação sobre injeção de CSV descreve por que um CSV sintaticamente correto não é suficiente para tornar um texto não confiável inerte.

Este exportador adiciona um apóstrofo para caracteres com fórmula selecionados, incluindo variantes de largura total, e para abas ou quebras de linha iniciais. Ele aplica a política ao contexto da solicitação, bem como ao texto de resultado. As posições numéricas usam uma regra de validação separada.

Comece a Raspar com Scrapeless

Potencialize seu trabalho de raspagem da web e automação com Scrapeless!
Inscreva-se hoje e receba $5 em crédito gratuitosem necessidade de cartão de crédito.

Reivindique seu crédito gratuito agora no Painel do Scrapeless.

Execute o Exportador Local de JSON para CSV

Salve o programa como serp_csv.py, em seguida, execute python3 serp_csv.py capture.json organic.csv. Ele lê a captura e escreve organic.csv além do organic.csv.run.json acompanhante. Os arquivos de saída existentes são substituídos; escolha um diretório de exportação dedicado ou nomes únicos ao reter várias versões.

O programa recusa caminhos de saída que sobreescreveriam a captura de entrada. Ele não altera o JSON original, não envia solicitações de API e não recupera tarefas pendentes.

python Copy
import argparse
import csv
import json
from pathlib import Path

FIELDS = ["run_id", "requested_at", "received_at", "q", "request_json", "ordinal",
          "position", "position_state", "title", "title_state", "link", "link_state",
          "snippet", "snippet_state"]

def spreadsheet_text(value):
    text = "" if value is None else str(value)
    stripped = text.lstrip()
    if (stripped.startswith(("=", "+", "-", "@", "=", "+", "-", "@"))
            or text.startswith(("\t", "\r", "\n"))):
        return "'" + text
    return text

def field(row, name):
    if name not in row:
        return "", "missing"
    value = row[name]
    if value is None:
        return "", "null"
    if name == "position":
        return (value, "value") if type(value) is int and value > 0 else ("", "invalid")
    if isinstance(value, str):
        return spreadsheet_text(value), "value"
    return spreadsheet_text(json.dumps(value, ensure_ascii=False)), "unexpected_type"

def export(source, target):
    source, target = Path(source), Path(target)
    sidecar = target.with_suffix(target.suffix + ".run.json")
    if source.resolve() in (target.resolve(), sidecar.resolve()):
        raise ValueError("Output paths must differ from input")
    record = json.loads(source.read_text(encoding="utf-8"))
    request = record.get("request")
    if not isinstance(request, dict) or not isinstance(request.get("input"), dict):
        raise ValueError("Expected a capture record with request.input")
    payload = record.get("response")
    rows = payload.get("organic_results") if isinstance(payload, dict) else None
    status = record.get("http_status")
    if status == 201:
        state, rows = "pending", []
    elif status != 200:
        state, rows = ("transport_error" if status is None else "http_error"), []
    elif not isinstance(rows, list) or any(not isinstance(x, dict) for x in rows):
        state, rows = "unmapped", []
    else:
        state = "observed" if rows else "empty"
    context = {
        "run_id": spreadsheet_text(record.get("run_id")),
        "requested_at": spreadsheet_text(record.get("requested_at")),
        "received_at": spreadsheet_text(record.get("received_at")),
        "q": spreadsheet_text(request["input"].get("q")),
        "request_json": spreadsheet_text(json.dumps(request, ensure_ascii=False, sort_keys=True)),
    }
    with target.open("w", encoding="utf-8-sig", newline="") as handle:
        writer = csv.DictWriter(handle, fieldnames=FIELDS)
        writer.writeheader()
        for ordinal, item in enumerate(rows):
            output = dict(context, ordinal=ordinal)
            for name in ("position", "title", "link", "snippet"):
                output[name], output[name + "_state"] = field(item, name)
            writer.writerow(output)
    sidecar.write_text(json.dumps({"source": str(source), "run_id": record.get("run_id"),
        "state": state, "rows": len(rows), "request": request,
        "requested_at": record.get("requested_at"), "received_at": record.get("received_at"),
        "export_policy": "spreadsheet_text_prefix_v1; original values remain in source JSON"},
        ensure_ascii=False, indent=2), encoding="utf-8")
    print(f"Exported {len(rows)} organic rows; state={state}; metadata={sidecar}")
    return state, len(rows)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("source")
    parser.add_argument("target")
    args = parser.parse_args()
    export(args.source, args.target)

O sidecar registra o estado da coleção, a contagem de linhas projetadas, o caminho de origem, a solicitação, os timestamps e a política de exportação. Um CSV apenas com cabeçalho permanece explicável desde que esse registro permaneça com ele. Mantenha ambos os arquivos de saída juntos ao entregar a exportação a outra pessoa.

Inspecione Nulos e Dados Orgânicos Malformados

Um array orgânico vazio presente produz state=empty. HTTP 201 produz pending, um status HTTP ausente torna-se transport_error, e outro status diferente de 200 torna-se http_error no modelo de estado desta aplicação. Esses resultados podem compartilhar uma contagem de zero linhas sem compartilhar um significado.

Se o campo orgânico estiver ausente, não for um array, ou contiver um item não-objeto, toda a projeção se torna unmapped. O programa não exporta linhas orgânicas para essa execução. Isso evita simplesmente descartar itens malformados enquanto descreve as linhas restantes como uma projeção completa.

Campos opcionais são tratados de forma mais restrita. Um trecho ausente deixa uma célula em branco e um estado de campo explícito sem descartar o item orgânico. Um valor complexo inesperado permanece representado como texto JSON, para que o valor incomum ainda possa ser inspecionado.

Essas são políticas da aplicação. Documente-as ao lado da exportação e revise-as deliberadamente se o consumidor precisar de um esquema diferente. Uma coluna de estado de campo é útil exatamente porque outro analista não deveria ter que inferir a transformação a partir de algumas células visíveis.

Verifique a Transferência da Planilha

Leia a saída com um parser CSV e compare registros lógicos, não linhas físicas. Um trecho entre aspas pode conter uma nova linha sem criar um novo resultado de busca. Confirme que a contagem do sidecar corresponda às linhas analisadas e que cada linha carregue seu contexto de solicitação.

Verifique valores sensíveis a Unicode e fórmulas na aplicação que a equipe realmente usa. A política de apóstrofo altera intencionalmente a representação exportada e pode ser visível em alguns visualizadores. Não é uma garantia universal em todas as configurações de importação e aplicativos de planilha.

Inclua o comportamento de salvar e reabrir no teste. A discussão sobre importação de planilhas ilustra por que o manuseio de escapes merece uma revisão específica da aplicação. Importe colunas relevantes como texto e use o JSON original sempre que cadeias de origem exatas forem necessárias.

Uma viagem local bem-sucedida confirma a consistência desta projeção. Não estabelece que a amostra de busca a montante seja exaustiva, representativa ou adequada para uma conclusão de classificação sem uma análise adicional.

Conclusão

Exporte o contexto da solicitação com os resultados, mantenha os estados dos campos onde espaços em branco esconderiam significado e conserve o JSON bruto. Um CSV mais um registro de execução fornece ao próximo analista informações suficientes para distinguir uma fatia vazia medida de uma coleção indisponível.

Um fluxo de trabalho de pesquisa de conteúdo SERP pode usar as observações exportadas para construir uma lista de leitura revisável antes de elaborar um resumo de conteúdo.

Construa Sua Próxima Observação de Busca

Use Scrapeless Google Search API para os dados de busca neste fluxo de trabalho. Revise Scrapeless pricing ao planejar a coleta e mantenha os parâmetros de pesquisa do Google ao lado de sua configuração.

Discuta sua implementação com a comunidade no Discord ou Telegram.

FAQ

Q: A API de Pesquisa do Google cria diretamente este CSV?

Não. O exportador demonstrado transforma o JSON salvo localmente. A geração de arquivos e o esquema auxiliar pertencem ao programa Python.

Q: Por que manter request_json quando a consulta já tem uma coluna?

A solicitação completa preserva configurações opcionais e entradas de URL completos que uma coluna de consulta sozinha não pode representar.

Q: As aspas CSV impedem a interpretação de fórmulas?

Não. O manuseio de delimitadores e a avaliação de planilhas são separados. Aplique uma política de texto documentada e verifique o fluxo de importação pretendido.

Q: Um CSV vazio significa que a pesquisa não retornou resultados?

Não necessariamente. Inspecione o estado do esquema auxiliar para distinguir um array vazio presente de uma coleção pendente, falhada ou não mapeada.

Q: Os valores originais podem ser recuperados?

Sim, a partir da captura de entrada retida. O CSV é uma projeção e transforma intencionalmente algumas representações de texto para uso em planilhas.

Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo