chore: import gti-maquina-comercial history via subtree
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> git-subtree-dir: gti-maquina-comercial git-subtree-mainline:93ca82979egit-subtree-split:b77484946f
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { cleanText } from '../lead-engine.mjs';
|
||||
import { UA_HEADERS, buildLeadFromPlace } from './common.mjs';
|
||||
import { escapeOverpassRegex } from './overpass.mjs';
|
||||
|
||||
async function findWikidataCityId(city) {
|
||||
// Busca por rotulo exato em SPARQL falha para nomes sem acento (base usa
|
||||
// "Santo Antonio", Wikidata registra "Santo Antônio"). wbsearchentities
|
||||
// e tolerante a acentos.
|
||||
try {
|
||||
const url = new URL('https://www.wikidata.org/w/api.php');
|
||||
url.searchParams.set('action', 'wbsearchentities');
|
||||
url.searchParams.set('search', city);
|
||||
url.searchParams.set('language', 'pt');
|
||||
url.searchParams.set('type', 'item');
|
||||
url.searchParams.set('format', 'json');
|
||||
|
||||
const response = await fetch(url, { headers: UA_HEADERS });
|
||||
if (!response.ok) return '';
|
||||
const data = await response.json();
|
||||
|
||||
const match = (data.search || []).find((item) => {
|
||||
const description = cleanText(item.description || '');
|
||||
return description.includes('municipality') || description.includes('municipio') || description.includes('munic');
|
||||
});
|
||||
|
||||
return match?.id || '';
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Fonte wikidata: empresas registradas no Wikidata por municipio (SPARQL).
|
||||
// Volume baixo, mas gratuito e util para achar empresas com website.
|
||||
export async function* collect(params, ctx) {
|
||||
const { uf, cities, segments, limits } = params;
|
||||
let executedQueries = 0;
|
||||
|
||||
for (const city of cities || []) {
|
||||
if (ctx.isCancelled()) return;
|
||||
|
||||
const cityId = await findWikidataCityId(city);
|
||||
if (!cityId) {
|
||||
ctx.log(`wikidata: municipio nao encontrado para ${city} — pulando`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const label = `${city} ${uf}`;
|
||||
const cityLeads = [];
|
||||
|
||||
for (const segment of segments) {
|
||||
if (ctx.isCancelled()) return;
|
||||
if (limits.queryLimit > 0 && executedQueries >= limits.queryLimit) break;
|
||||
|
||||
const regex = (segment.queries || [])
|
||||
.filter((term) => term.length >= 4)
|
||||
.slice(0, 10)
|
||||
.map(escapeOverpassRegex)
|
||||
.join('|');
|
||||
if (!regex) continue;
|
||||
|
||||
const sparql = `
|
||||
SELECT ?item ?itemLabel ?website WHERE {
|
||||
?item wdt:P31/wdt:P279* wd:Q4830453.
|
||||
{ ?item wdt:P131 wd:${cityId}. } UNION { ?item wdt:P159/wdt:P131* wd:${cityId}. }
|
||||
OPTIONAL { ?item wdt:P856 ?website. }
|
||||
SERVICE wikibase:label { bd:serviceParam wikibase:language "pt,en". }
|
||||
FILTER(REGEX(?itemLabel, "${regex}", "i"))
|
||||
}
|
||||
LIMIT ${limits.maxPerQuery || 10}
|
||||
`;
|
||||
|
||||
ctx.emit({ phase: 'wikidata', message: `${segment.name} em ${label}` });
|
||||
executedQueries += 1;
|
||||
|
||||
try {
|
||||
const url = new URL(ctx.endpoints.wikidataUrl);
|
||||
url.searchParams.set('query', sparql);
|
||||
url.searchParams.set('format', 'json');
|
||||
const response = await fetch(url, {
|
||||
headers: { ...UA_HEADERS, accept: 'application/sparql-results+json' }
|
||||
});
|
||||
if (!response.ok) throw new Error(`Wikidata HTTP ${response.status}`);
|
||||
const data = await response.json();
|
||||
|
||||
for (const result of data.results?.bindings || []) {
|
||||
const place = {
|
||||
name: result.itemLabel?.value || '',
|
||||
city,
|
||||
state: uf,
|
||||
segment: segment.name,
|
||||
website: result.website?.value || '',
|
||||
query: `wikidata ${segment.name} em ${label}`,
|
||||
place_id: result.item?.value || ''
|
||||
};
|
||||
if (place.name) cityLeads.push(buildLeadFromPlace(place, segment, city, uf, 'wikidata'));
|
||||
}
|
||||
} catch (error) {
|
||||
ctx.log(`wikidata falhou em ${segment.name} ${label}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (cityLeads.length) yield { origin: 'wikidata', label, leads: cityLeads };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user