Esse sistema pesquisa notícias em fontes globais, extrai o conteúdo completo do artigo (ignorando os paywalls), detecta a parcialidade da cobertura e gera uma análise inteligente com base em eventos noticiosos reais.
Você aprenderá:
- Como criar ferramentas de pesquisa de notícias usando o Bright Data SDK para Scraping de dados da Web
- Como aproveitar o Vercel IA SDK para análise inteligente de notícias e conversação
- Como contornar paywalls e proteção anti-bot para acessar qualquer fonte de notícias
- Como detectar viés comparando a cobertura em vários meios de comunicação
- Como criar um pipeline automatizado desde a descoberta de notícias até a verificação de fatos
Vamos começar!
Pré-requisitos
Para seguir este tutorial, você precisa de:
- Conhecimento básico de React e Next.js
- Node.js 20.18.1+ instalado em seu ambiente de desenvolvimento local
- Uma conta da Bright Data com acesso à API (nível gratuito disponível)
- Uma chave de API da OpenAI com acesso GPT-4
- Familiaridade com TypeScript e JavaScript moderno
- Conhecimento básico de como trabalhar com APIs e variáveis de ambiente
Desafios no consumo convencional de notícias
As formas tradicionais de acessar informações e notícias têm várias limitações importantes:
- Sobrecarga de informações: Você encontra centenas de manchetes diariamente. Isso torna difícil descobrir o que é importante ou o que está relacionado aos seus interesses.
- Preconceito e lacunas de perspectiva: A maioria das pessoas recebe notícias de um pequeno número de fontes. Você perde pontos de vista importantes e frequentemente vê uma cobertura unilateral de questões complexas.
- Barreiras de acesso pago: O jornalismo de qualidade geralmente está por trás de paywalls. Você acha difícil acessar artigos completos de várias fontes para fazer uma pesquisa completa.
- Carga de verificação de fatos: Para verificar as afirmações, você precisa pesquisar várias fontes, cruzar informações e avaliar a credibilidade da fonte. A maioria das pessoas não tem tempo para isso.
- Falta de contexto: As notícias de última hora geralmente não têm contexto histórico ou eventos relacionados. Você tem dificuldade para ver o quadro completo das histórias em desenvolvimento.
O NewsIQ aborda esses desafios. Ele combina a análise baseada em IA com o Scraping de dados da Web de nível empresarial. O sistema acessa qualquer fonte de notícias (ignorando a proteção anti-bot), analisa a cobertura em vários veículos e fornece insights inteligentes com a atribuição adequada da fonte.
Criação do assistente de pesquisa de notícias
Criaremos o NewsIQ, um assistente completo de pesquisa de notícias com IA usando o Bright Data e o Vercel IA SDK. Criaremos uma solução para processar notícias de qualquer fonte e fornecer análises inteligentes por meio de uma interface de conversação.
Etapa 1: Configuração do projeto
Primeiro, configure seu ambiente de desenvolvimento Next.js. Crie um novo diretório para o projeto:
npx create-next-app@latest ai-news-assistant
Quando solicitado, selecione a seguinte opção:

Navegue até o diretório do projeto e instale os pacotes necessários:
cd ai-news-assistant &&
npm install @brightdata/sdk ai zod @ai-sdk/openai
Esses pacotes fornecem tudo o que você precisa: Bright Data SDK para scraping de dados da Web, Vercel IA SDK para análise inteligente, Zod para validação de esquema com segurança de tipo e OpenIA para geração de texto LLM.

Em seguida, crie um arquivo .env.local para armazenar suas credenciais de API:
BRIGHTDATA_API_KEY=sua_chave_de_api_de_brightdata_aqui
OPENAI_API_KEY=sua_openai_api_key_here
Você precisa de:
- Token da API da Bright Data: Gerado a partir de seu painel de controle da Bright Data
- Chave da API da OpenAI: Para geração de texto do LLM
Etapa 2: definir as ferramentas de pesquisa de notícias
Crie a funcionalidade central de pesquisa de notícias definindo três ferramentas para aproveitar o Scraping de dados da Bright Data. No diretório do projeto, crie um novo arquivo chamado lib/brightdata-tools.ts:
import { tool, type Tool } from "IA";
import { z } from "zod";
import { bdclient } from "@brightdata/sdk";
type NewsTools = "searchNews" | "scrapeArticle" | "searchWeb";
interface NewsToolsConfig {
apiKey: string;
excludeTools?: NewsTools[];
}
export const newsTools = (
config: NewsToolsConfig
): Partial<Record<NewsTools, Tool>> => {
const client = new bdclient({
apiKey: config.apiKey,
autoCreateZones: true,
});
const tools: Partial<Record<NewsTools, Tool>> = {
searchNews: tool({
description:
"Pesquise artigos de notícias sobre qualquer tópico usando o Google News. Retorna artigos de notícias recentes com títulos, trechos, fontes e datas de publicação. Use essa ferramenta para encontrar cobertura de notícias atuais sobre tópicos específicos.",
inputSchema: z.object({
query: z
.string()
.describe(
'A consulta de pesquisa de notícias (por exemplo, "inteligência artificial", "política de mudança climática", "ganhos tecnológicos")'
),
país: z
.string()
.comprimento(2)
.opcional()
.describe(
'Código de país de duas letras para notícias localizadas (por exemplo, "us", "gb", "de", "fr", "jp")'
),
}),
execute: async ({
query,
country,
}: {
query: string;
country?: string;
}) => {
try {
const newsQuery = `${query} news`;
const result = await client.search(newsQuery, {
searchEngine: "google",
dataFormat: "markdown",
format: "raw",
country: country?.toLowerCase() || "us",
});
return result;
} catch (error) {
return `Error searching for news on "${query}": ${String(error)}`;
}
},
}),
scrapeArticle: tool({
description:
"Extraia o conteúdo completo de um artigo de notícias de qualquer URL. Retorna o texto completo do artigo em formato markdown limpo, ignorando paywalls e proteção anti-bot. Use isso para ler artigos completos depois de encontrá-los com o searchNews.",
inputSchema: z.object({
url: z.string().url().describe("A URL do artigo de notícias a ser extraído"),
country: z
.string()
.length(2)
.opcional()
.describe("Código de país de duas letras para a localização do Proxy"),
}),
execute: async ({ url, country }: { url: string; country?: string }) => {
try {
const result = await client.scrape(url, {
dataFormat: "markdown",
format: "raw",
country: country?.toLowerCase(),
});
return result;
} catch (error) {
return `Error scraping article at ${url}: ${String(error)}`;
}
},
}),
searchWeb: tool({
description:
"Pesquisa geral na Web usando o Google, o Bing ou o Yandex. Use-a para pesquisa de fundo, verificação de fatos ou para encontrar contexto adicional além dos artigos de notícias.",
inputSchema: z.object({
query: z
.string()
.describe(
"A consulta de pesquisa para informações básicas ou verificação de fatos"
),
searchEngine: z
.enum(["google", "bing", "yandex"])
.opcional()
.padrão("google")
.describe("Mecanismo de pesquisa a ser usado"),
país: z
.string()
.comprimento(2)
.opcional()
.describe("Código de país de duas letras para resultados localizados"),
}),
execute: async ({
query,
searchEngine = "google",
country,
}: {
consulta: string;
searchEngine?: "google" | "bing" | "yandex";
country?: string;
}) => {
try {
const result = await client.search(query, {
searchEngine,
dataFormat: "markdown",
format: "raw",
country: country?.toLowerCase(),
});
return result;
} catch (error) {
return `Error searching web for "${query}": ${String(error)}`;
}
},
}),
};
for (const toolName in tools) {
if (config.excludeTools?.includes(toolName as NewsTools)) {
delete tools[toolName as NewsTools];
}
}
return tools;
};
Esse código define três ferramentas essenciais usando a interface de ferramentas do Vercel IA SDK. A ferramenta searchNews consulta o Google News em busca de artigos recentes. A ferramenta scrapeArticle extrai o conteúdo completo de qualquer URL de notícias (ignorando paywalls). A ferramenta searchWeb oferece pesquisa geral na Web para verificação de fatos. Cada ferramenta usa esquemas Zod para validação de entrada com segurança de tipo e retorna dados estruturados para a IA analisar. O cliente Bright Data lida automaticamente com toda a complexidade da proteção anti-bot e do gerenciamento de Proxy.
Etapa 3: criar a rota da API do IA Chat
Crie o endpoint da API para alimentar a interface de conversação. Crie app/api/chat/route.ts:
importar { openai } de "@ai-sdk/openai";
importar { streamText, convertToModelMessages, stepCountIs } de "IA";
import { newsTools } de "@/lib/brightdata-tools";
export const maxDuration = 60;
exportar função assíncrona POST(req: Request) {
const { messages } = await req.json();
const modelMessages = convertToModelMessages(messages);
const tools = newsTools({
apiKey: process.env.BRIGHTDATA_API_KEY!,
});
const result = streamText({
model: openai("gpt-4o"),
messages: modelMessages,
tools,
stopWhen: stepCountIs(5),
system: `Você é o NewsIQ, um assistente avançado de pesquisa de notícias por IA. Sua função é ajudar os usuários a se manterem informados, analisar a cobertura de notícias e entender eventos atuais complexos.
**Principais recursos:**
1. **Descoberta de notícias**: Pesquise notícias atuais sobre qualquer tópico usando o searchNews
2. **Leitura profunda**: Extraia artigos completos com scrapeArticle para fornecer um contexto completo
3. **Verificação de fatos**: Use a searchWeb para verificar afirmações e encontrar fontes adicionais
4. **Análise de viés**: Compare a cobertura de várias fontes e identifique possíveis vieses
5. **Análise de tendências**: Identificar histórias emergentes e acompanhar a evolução dos tópicos
**Diretrizes
- Sempre cite suas fontes com o nome e a data da publicação
- Ao analisar a parcialidade, seja objetivo e forneça evidências
- Para tópicos controversos, apresente várias perspectivas
- Faça uma distinção clara entre fatos e análises
- Se as informações estiverem desatualizadas, anote a data de publicação
- Ao extrair artigos, resuma os pontos principais antes da análise
- Para verificação de fatos, use várias fontes independentes
**Formato da resposta:**
- Comece com uma resposta clara e direta
- Forneça citações de fontes no contexto
- Use marcadores para várias fontes
- Termine com uma breve análise ou insight
- Ofereça-se para explorar aspectos específicos com mais detalhes
Lembre-se: seu objetivo é ajudar os usuários a se tornarem pensadores críticos e mais bem informados,
});
return result.toUIMessageStreamResponse();
}
Essa rota da API cria um endpoint de streaming para conectar suas ferramentas de pesquisa de notícias com o GPT-4 da OpenAI. O prompt abrangente do sistema orienta a IA a agir como um analista profissional de notícias. Ele enfatiza a citação de fontes, a objetividade e o pensamento crítico. A resposta de streaming mostra aos usuários a análise em tempo real à medida que ela é gerada, criando uma experiência de conversação responsiva.

Etapa 4: criar a interface de bate-papo
Crie a interface de usuário para interagir com o NewsIQ. Substitua o conteúdo de app/page.tsx por:
```typescript
"use client";
import { useChat } from "@ai-sdk/react";
importar { useState } de "react";
exportar função padrão NewsResearchAssistant() {
const { messages, sendMessage, status } = useChat();
const [input, setInput] = useState("");
const [exampleQueries] = useState([
"🌍 Quais são os últimos desenvolvimentos na política de mudança climática?",
"💻 Pesquisar notícias sobre regulamentação de inteligência artificial",
"📊 Como as diferentes fontes estão cobrindo a economia?",
"⚡ Quais são as histórias de tendências tecnológicas desta semana?",
"🔍 Verificação de fatos: A [afirmação específica] realmente aconteceu?",
]);
return (
<div className="flex flex-col h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50">
{/* Cabeçalho */}
<header className="bg-white shadow-md border-b border-gray-200">
<div className="max-w-5xl mx-auto px-6 py-5">
<div className="flex items-center gap-3">
<div className="bg-gradient-to-br from-blue-600 to-indigo-600 w-12 h-12 rounded-xl flex items-center justify-center shadow-lg">
<span className="text-2xl">📰</span>
</div>
<div>
<h1 className="text-2xl font-bold text-gray-900">NotíciasIQ</h1>
<p className="text-sm text-gray-600">
Pesquisa e análise de notícias com IA
</p>
</div>
</div>
</div>
</header>
{/* Área de bate-papo principal */}
<div className="flex-1 overflow-hidden max-w-5xl w-full mx-auto px-6 py-6">
<div className="h-full flex flex-col bg-white rounded-2xl shadow-xl border border-gray-200">
{/* Contêiner de mensagens */}
<div className="flex-1 overflow-y-auto p-6 space-y-6">
{messages.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-center px-4">
{/* Tela de boas-vindas */}
<div className="bg-gradient-to-br from-blue-500 to-indigo-600 w-20 h-20 rounded-2xl flex items-center justify-center mb-6 shadow-lg">
<span className="text-4xl">📰</span>
</div>
<h2 className="text-3xl font-bold text-gray-900 mb-3">
Bem-vindo ao NewsIQ
</h2>
<p className="text-gray-600 mb-8 max-w-2xl text-lg">
Seu assistente de pesquisa com IA para análise de notícias,
verificação de fatos e para se manter informado. Posso pesquisar em fontes de notícias
fontes de notícias, analisar preconceitos e ajudá-lo a entender histórias complexas.
histórias complexas.
</p>
{/* Feature Pills */}
<div className="flex flex-wrap gap-3 justify-center mb-8">
<div className="px-4 py-2 bg-blue-100 text-blue-700 rounded-full text-sm font-medium">
🔍 Pesquisa com várias fontes
</div>
<div className="px-4 py-2 bg-purple-100 text-purple-700 rounded-full text-sm font-medium">
🎯 Detecção de viés
</div>
<div className="px-4 py-2 bg-green-100 text-green-700 rounded-full text-sm font-medium">
✓ Verificação de fatos
</div>
<div className="px-4 py-2 bg-orange-100 text-orange-700 rounded-full text-sm font-medium">
📊 Análise de tendências
</div>
</div>
{/* Consultas de exemplo */}
<div className="w-full max-w-3xl">
<p className="text-sm font-semibold text-gray-700 mb-4">
Tente perguntar:
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{exampleQueries.map((query, i) => (
<button
key={i}
onClick={() => {
setInput(query);
}}
className="p-4 text-left bg-gradient-to-br from-gray-50 to-gray-100 hover:from-blue-50 hover:to-indigo-50 rounded-xl border border-gray-200 hover:border-blue-300 transition-all duration-200 text-sm text-gray-700 hover:text-gray-900 shadow-sm hover:shadow-md"
>
{query}
</button>
))}
</div>
</div>
</div>
) : (
// Exibição de mensagens
messages.map((m: any) => (
<div
key={m.id}
className={`flex ${
m.role === "user" ? "justify-end" : "justify-start"
}`}
>
<div
className={`max-w-[85%] rounded-2xl px-5 py-4 ${
m.role === "usuário"
? "bg-gradient-to-br from-blue-600 to-indigo-600 text-white shadow-lg"
: "bg-gray-100 text-gray-900 border border-gray-200"
}`}
>
<div className="flex items-center gap-2 mb-2">
<span className="text-lg">
{m.role === "user" ? "👤" : "📰"}
</span>
<span className="text-xs font-semibold opacity-90">
{m.role === "user" ? "Você" : "NewsIQ"}
</span>
</div>
<div className="prose prose-sm max-w-none prose-headings:font-bold prose-h3:text-lg prose-h3:mt-4 prose-h3:mb-2 prose-p:my-2 prose-ul:my-2 prose-li:my-1 prose-a:text-blue-600 prose-a:underline prose-strong:font-semibold">
<div
className="whitespace-pre-wrap"
dangerouslySetInnerHTML={{
__html:
m.parts
?.map((part: any) => {
if (part.type === "text") {
let html = part.text
// Cabeçalhos
.replace(/### (.*?)$/gm, "<h3>$1</h3>")
// Negrito
.replace(
/**(.*?)**/g,
"<strong>$1</strong>"
)
// Links
.replace(
/[(.*?)]((.*?))/g,
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
);
html = html.replace(
/(^- .*$n?)+/gm,
(match: string) => {
const items = match
.split("n")
.filter((line: string) => line.trim())
.map((line: string) =>
line.replace(/^- /, "")
)
.map((item: any) => `<li>${item}</li>`)
.join("");
retorna `<ul>${itens}</ul>`;
}
);
// Parágrafos
html = html
.split("nn")
.map((para: string) => {
if (
para.trim() &&
!para.startsWith("<")
) {
return `<p>${para}</p>`;
}
return para;
})
.join("");
retornar html;
}
return "";
})
.join("") || "",
}}
/>
</div>
</div>
</div>
))
)}
{/* Indicador de carregamento */}
{(status === "submitted" || status === "streaming") && (
<div className="flex justify-start">
<div className="bg-gray-100 rounded-2xl px-5 py-4 border border-gray-200">
<div className="flex items-center gap-3">
<div className="flex space-x-2">
<div className="w-2 h-2 bg-blue-500 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-blue-500 rounded-full animate-bounce delay-100"></div>
<div className="w-2 h-2 bg-blue-500 rounded-full animate-bounce delay-200"></div>
</div>
<span className="text-sm text-gray-600">
Pesquisando fontes de notícias...
</span>
</div>
</div>
</div>
)}
</div>
{/* Área de entrada */}
<div className="border-t border-gray-200 p-5 bg-gray-50">
<form
onSubmit={(e) => {
e.preventDefault();
Se (input.trim()) {
sendMessage({ text: input });
setInput("");
}
}}
className="flex gap-3"
>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Pergunte sobre qualquer tópico de notícias, solicite uma análise ou verifique uma afirmação..."
className="flex-1 px-5 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white shadow-sm text-gray-900 placeholder-gray-600"
disabled={status === "submitted" || status === "streaming"}
/>
<button
type="submit" (tipo = "enviar")
disabled={
status === "submetido" ||
status === "transmitindo" ||
!input.trim()
}
className="px-8 py-3 bg-gradient-to-r from-blue-600 to-indigo-600 text-white rounded-xl hover:from-blue-700 hover:to-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 font-semibold shadow-lg hover:shadow-xl"
>
{status === "submitted" || status === "streaming" ? (
<span className="flex items-center gap-2">
<svg className="animate-spin h-5 w-5" viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor" (traço = cor atual)
strokeWidth="4"
fill="none"
/>
<path
className="opacidade-75"
fill="currentColor" (preenchimento = "cor atual")
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
Análise
</span>
) : (
"Pesquisa"
)}
</button>
</form>
<div className="flex items-center justify-between mt-3">
<p className="text-xs text-gray-500">
Desenvolvido por Bright Data × Vercel IA SDK
</p>
<div className="flex gap-2">
<span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs font-medium">
✓ Tempo real
</span>
<span className="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs font-medium">
🌐 Fontes globais
</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
Essa interface cria uma experiência de conversação envolvente com o gancho useChat do Vercel IA SDK. A tela de boas-vindas apresenta exemplos de consultas para ajudá-lo a começar. A área principal do chat exibe mensagens com suporte a streaming. O design usa o Tailwind CSS para obter uma aparência moderna e profissional com fundos gradientes e animações suaves. O componente lida com os estados de carregamento de forma elegante e fornece feedback visual durante o processamento de IA.

Etapa 5: Atualizar o layout da raiz
Conclua a configuração do aplicativo atualizando app/layout.tsx com os metadados adequados:
importar tipo { Metadata } de 'next'
importar { Inter } de 'next/font/google'
importar './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
título: 'NewsIQ - Assistente de pesquisa de notícias por IA',
description:
'Ferramenta de pesquisa, análise e verificação de fatos de notícias com IA. Pesquise em todas as fontes, detecte preconceitos e mantenha-se informado com insights inteligentes",
palavras-chave: [
'news',
'IA',
'research',
'fact-checking',
'detecção de viés',
'análise de notícias',
],
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
Essa configuração de layout define os metadados de SEO adequados e carrega a fonte Inter para obter uma tipografia limpa e profissional em todo o aplicativo.
Etapa 6: execução do aplicativo
Para executar o aplicativo, use este comando:
npm run dev
O aplicativo será iniciado em http://localhost. Para testar os recursos do NewsIQ, experimente esta consulta de exemplo:
Verificação de fatos: A Apple anunciou um novo produto na semana passada?
A IA usará automaticamente as ferramentas apropriadas com base em sua consulta. Quando você solicita notícias, ela pesquisa no Google News. Quando você solicita artigos completos, ela extrai o conteúdo. Para verificação de fatos, ela faz referências cruzadas de várias fontes. Você verá os resultados sendo transmitidos em tempo real à medida que a IA processa as informações.

Etapa 7: implantar no Vercel
Para implantar seu aplicativo na produção, primeiro envie seu código para o GitHub:
git init
git add .
git commit -m "Initial commit: Assistente de notícias do NewsIQ IA"
git branch -M main
git remote add origin https://github.com/yourusername/ai-news-assistant.git
git push -u origin main
Em seguida, faça a implantação no Vercel:
- Acesse vercel.com e faça login com o GitHub
- Clique em “Add New Project” (Adicionar novo projeto) e importe seu repositório
- Configure as variáveis de ambiente:
- Adicione
BRIGHTDATA_API_KEY - Adicionar
OPENAI_API_KEY
- Clique em “Deploy” (Implantar)
Seu aplicativo estará ativo em 2 a 3 minutos em um URL como https://ai-news-assistant.vercel.app.

Considerações finais
Esse assistente de pesquisa de notícias com IA mostra como a automação simplifica a coleta e a análise de notícias. Se você estiver interessado em abordagens alternativas para integrar a Bright Data com ferramentas de IA, explore nosso guia sobre Scraping de dados da Web com um servidor MCP. Para aprimorar ainda mais seus fluxos de trabalho de monitoramento de notícias, considere os produtos da Bright Data, como nossa API Web Scraper para acessar qualquer fonte de notícias, bem como outros Conjuntos de dados e ferramentas de automação criados para equipes de agregação de conteúdo e monitoramento de mídia.
Explore mais soluções na documentação da Bright Data.
Crie uma conta gratuita da Bright Data para começar a usar seus fluxos de trabalho automatizados de pesquisa de notícias.