= {};
$('table tr').each((_, tr) => {
const tds = $(tr).find('td');
if (tds.length < 2) return;
const label = clean($(tds[0]).text());
if (!label) return;
rows[label] = clean($(tds[1]).text());
const href = $(tds[1]).find('a[href]').first().attr('href');
if (href) links[label] = href;
});
if (!title || !rows['Grade']) return null;
const images = [...new Set($('img[alt*="enlarge" i], img[src*="/pcgs/cert/"]').toArray().map((e) => $(e).attr('src') ?? '').filter((u) => /^https?:\/\//.test(u)))];
return { title, cert, rows, links, images };
}
export class PcgsCertConnector extends CertLookupConnector {
readonly version = '1.0.0';
readonly parserVersion = PARSER_VERSION;
readonly grader = 'pcgs';
readonly idKey = 'pcgs_cert';
readonly format = 'html' as const;
override readonly urlPatterns = PATTERNS;
certUrl(cert: string): string {
return certUrl(cert);
}
certFromUrl(url: string): string | null {
return certFromUrl(url);
}
classify(doc: string): PageStatus {
const $ = H.load(doc);
const hasGradeRow = $('table tr td')
.toArray()
.some((td) => /^grade$/i.test(clean($(td).text())));
if ($('.text-display5').length && hasGradeRow) return 'found';
const text = clean($('body').text() || $.root().text());
if (/not found|no record|invalid cert|does not exist|could not be found|unable to (find|locate)|no results|not in our|we were unable|isn.t in the pcgs/i.test(text)) return 'not_found';
return 'unknown';
}
trim(doc: string): string {
const $ = H.load(doc);
$('script, style, noscript, iframe, svg, header, footer, nav, form').remove();
let node = $('.text-display5').first();
if (!node.length) {
const body = $('body');
return `${clean(body.text()).slice(0, 4000)}
`;
}
for (let i = 0; i < 10 && node.length; i++) {
if (node.find('table').length) break;
node = node.parent();
}
return $.html(node.length ? node : $('body'));
}
parse(snapshot: string, info: { cert: string; url: string }): ParsedCert | null {
const page = parsePcgsPage(snapshot);
if (!page) return null;
const r = page.rows;
const cert = page.cert ?? info.cert;
const g = parseCoinGrade(r['Grade']);
const pcgsNo = clean(r['PCGS #'] ?? '').replace(/\D/g, '') || null;
const region = r['Region'] ?? null;
const isNote = /note|banknote|currency/i.test(`${page.title} ${r['Denomination'] ?? ''} ${r['Holder Type'] ?? ''}`) && !/coin/i.test(r['Holder Type'] ?? '');
const identifiers: Record = {};
if (pcgsNo) identifiers.pcgs_number = pcgsNo;
const population = toInt(r['Population']);
return {
title: `${page.title} PCGS ${r['Grade']}`.trim(),
attributes: {
categorySlug: isNote ? 'banknotes' : 'coins',
name: page.title,
year: yearOf(r['Date, Mintmark'] ?? page.title),
country: /united states/i.test(region ?? '') ? 'US' : null,
region,
variant: r['Variety'] ?? r['Designation'] ?? null,
productionQuantity: toInt(r['Mintage']),
identifiers,
metadata: {
pcgs_cert: cert,
date_mintmark: r['Date, Mintmark'] ?? null,
denomination: r['Denomination'] ?? null,
price_guide_value_usd: money(r['Price Guide Value']),
holder_type: r['Holder Type'] ?? null,
security: r['Security'] ?? null,
coinfacts_url: page.links['PCGS #'] ?? null,
population_url: page.links['Population'] ?? null,
fields: r,
},
},
grade: g.grade,
qualifier: g.qualifier,
gradeLabel: g.label || null,
images: page.images,
population: population !== null ? { gradeKey: g.grade ?? g.label, atGrade: population, higher: toInt(r['Pop Higher']), url: page.links['Population'] ?? null } : null,
confidence: pcgsNo ? 0.95 : 0.85,
};
}
}
export default (meta: ConnectorMeta) => new PcgsCertConnector(meta);