返回资讯中心
外部精选
软件工程
#开发者实时流

Retrace: Find the Origin of Any Image

document.documentElement.classList.toggle('dark', mode === 'dark');

Hacker News 最新archivarix2026/10/28 · 2 天前30 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

') : svg(''); }; const setTheme = (mode, remember) => { document.documentElement.classList.toggle('dark', mode === 'dark'); document.documentElement.style.colorScheme = mode; if (remember) { try { localStorage.setItem('theme', mode); } catch { } } showTheme(); }; showTheme(); themeBtn.onclick = () => setTheme(document.documentElement.classList.contains('dark') ? 'light' : 'dark', true); media.addEventListener('change', (e) => { let chosen = null; try { chosen = localStorage.getItem('theme'); } catch { } if (chosen !== 'light' && chosen !== 'dark') setTheme(e.matches ? 'dark' : 'light', false); });

const langSel = document.getElementById('lang'); const LANG = document.documentElement.lang || 'en'; document.getElementById('lang-code').textContent = LANG.toUpperCase(); const LANG_NAMES = { en: 'English', ru: 'Русский', es: 'Español', de: 'Deutsch', pt: 'Português', fr: 'Français' }; langSel.onclick = (ev) => { ev.stopPropagation(); const open = document.getElementById('lang-menu'); for (const x of document.querySelectorAll('.corner .menu')) x.remove(); if (open) return; const m = document.createElement('div'); m.className = 'menu lang-menu'; m.id = 'lang-menu'; m.setAttribute('role', 'menu'); m.innerHTML = Object.entries(LANG_NAMES).map(([code, name]) => ${code === LANG ? '' : ''}${name}).join(''); langSel.parentElement.appendChild(m); const c = langSel.parentElement.getBoundingClientRect(); m.style.right = ${Math.max(0, c.right - langSel.getBoundingClientRect().right)}px; m.onclick = (e) => { const x = e.target.closest('[data-lang]'); if (x && x.dataset.lang !== LANG) switchLang(x.dataset.lang); else m.remove(); }; }; document.addEventListener('click', (e) => { const lm = document.getElementById('lang-menu'); if (lm && !lm.contains(e.target) && !langSel.contains(e.target)) lm.remove(); }); document.addEventListener('keydown', (e) => { if (e.key !== 'Escape') return; for (const x of document.querySelectorAll('.corner .menu')) x.remove(); }); const switchLang = (to) => { const rest = location.pathname.replace(/^/(ru|es|de|pt|fr)(?=/|$)/, '') || '/'; location.assign((to === 'en' ? '' : '/' + to) + rest

  • (to === 'en' ? '?lang=en' : '') + location.hash); }; if (new URLSearchParams(location.search).has('lang')) { const q = new URLSearchParams(location.search); q.delete('lang'); history.replaceState({}, '', location.pathname
  • (q.size ? '?' + q : '') + location.hash); }

const nForm = LANG === 'ru' ? (n) => { const a = Math.abs(n) % 100; const b = a % 10; return a > 10 && a 1 && b (Math.abs(n) (Math.abs(n) === 1 ? 0 : 1); const tp = (key, n, params) => { const forms = T[key]; if (!Array.isArray(forms)) return t(key, { n, ...params }); let s = forms[Math.min(nForm(n), forms.length - 1)] ?? ''; for (const [k, v] of Object.entries({ n, ...params })) { s = s.split({${k}}).join(String(v)); } return s; };

if (HAS_DICT) { if (!document.getElementById('doc').firstChild) document.title = t('page_title'); const tagline = document.getElementById('tagline'); if (tagline) tagline.textContent = t('tagline'); for (const el of [themeBtn, langSel]) { const key = el === langSel ? 'lang_btn' : 'theme_btn'; el.title = t(key); el.setAttribute('aria-label', t(key)); } document.getElementById('go').textContent = t('check_btn'); document.getElementById('drop').innerHTML = `${t('drop_zone')}${t('drop_hint')}

`; document.getElementById('shoot-t').textContent = t('btn_shoot'); document.getElementById('pick-t').textContent = t('btn_pick'); document.getElementById('f-guide').textContent = t('footer_guide'); document.getElementById('f-pricing').textContent = t('footer_pricing'); document.getElementById('f-tube').textContent = t('footer_tube'); document.getElementById('f-echo').textContent = t('footer_echo'); document.getElementById('f-about').textContent = t('footer_about'); document.getElementById('f-privacy').textContent = t('footer_privacy'); document.getElementById('f-terms').textContent = t('footer_terms'); document.getElementById('f-contact').textContent = t('footer_contact'); document.getElementById('f-copy').textContent = t('footer_copyright', { year: new Date().getFullYear() }); }

const openToAnchor = () => { const id = location.hash.slice(1); if (!id) return; const el = document.getElementById(id); for (let p = el; p; p = p.parentElement) { if (p.tagName === 'DETAILS') p.open = true; } if (el) el.scrollIntoView(); }; addEventListener('hashchange', openToAnchor); const esc = (s) => String(s ?? '').replace(/[<>&"]/g, (c) => ({ '': '>', '&': '&', '"': '"' }[c])); const host = (u) => { try { return new URL(u).host.replace(/^www./, ''); } catch { return u; } }; const pageLink = (u) => { try { const p = new URL(String(u)); return /^https?:$/.test(p.protocol) && ((p.pathname && p.pathname !== '/') || p.search) ? String(u) : ''; } catch { return ''; } }; const skipText = (o) => { const k = (o || {}).skip_key; return k && T['skip_' + k] ? t('skip_' + k, o.skip_args || {}) : String((o || {}).skipped || ''); }; const basisText = (bs) => { if (!bs || bs.n_sources === undefined) return String((bs || {}).note || ''); let s = bs.kind === 'hash' ? t('basis_note_hash', { n: bs.copies, sources: bs.n_sources === 1 ? t('basis_src_one') : t('basis_src_n', { n: bs.n_sources }) }) : bs.kind === 'words' ? t('basis_note_words', { named: (bs.named_by || []) .map((k) => T['named_' + k] || k).join(', ') }) : t('basis_note_frame'); if (bs.judged_same_shot) { s += ' ' + t('basis_tail_judged', { n: bs.judged_same_shot }); } const missing = (bs.missing || []).join(', '); if (bs.verify_ran === false) { s += ' ' + (missing ? t('basis_tail_not_searched_missing', { names: missing }) : t('basis_tail_not_searched')); } else if (missing) { s += ' ' + t('basis_tail_partial', { names: missing })

  • ' ' + ((bs.searched_by || []).length ? t('basis_tail_searched_by', { had: bs.searched_by.join(', ') }) : t('basis_tail_no_second'))
  • ' ' + t('basis_tail_words_note'); } return s; }; const panoUrl = (lat, lon) => https://www.google.com/maps/place/${lat},${lon}/@${lat},${lon},17z/data=!5m1!1e5;

const outward = (root) => { const fix = (a) => { const h = a.getAttribute('href') || ''; if (!/^https?:/i.test(h) && !/^/api//.test(h)) return; a.target = '_blank'; if (!/noopener/.test(a.rel || '')) { a.rel = ((a.rel ? a.rel + ' ' : '') + 'noopener noreferrer').trim(); } }; if (root.matches && root.matches('a[href]')) fix(root); for (const a of (root.querySelectorAll ? root.querySelectorAll('a[href]') : [])) fix(a); }; new MutationObserver((recs) => { for (const rec of recs) { for (const n of rec.addedNodes) if (n.nodeType === 1) outward(n); } }).observe(document.body, { childList: true, subtree: true });

const wordyName = (n) => { const parts = String(n || '').replace(/.[a-z0-9]{2,5}$/i, '') .split(/[^0-9A-Za-zА-Яа-яЁё]+/) .map((w) => ({ raw: w, core: w.replace(/\d+/g, '') })) .filter(({ raw, core }) => core.length >= 3 && raw.length core.toLowerCase())).size >= 2; }; const fileLine = (row) => (row && row.file ? `↳ ${t('file_label')} ${esc(row.file)}

`

  • (row.name && wordyName(row.name) ? `${t('file_name_note', { name: esc(row.name) })}

` : '') : '');

function engines(f, queryEngine) { const set = new Set(); for (const s of f.sources || []) { const x = String(s).toLowerCase(); if (x.startsWith('web_text_search')) { set.add(queryEngine || 'vlm'); continue; } if (x.includes('names_repeated') || x.includes('names_standing')) { set.add('yandex'); continue; } if (x.startsWith('google_lens')) { set.add('google'); continue; } const e = ['yandex', 'google', 'vlm', 'commons', 'registry'] .find((p) => x.startsWith(p)); set.add(e || s); } return [...set].sort(); }

const SLD2 = new Set(['co', 'com', 'net', 'org', 'ac', 'gov', 'edu', 'or', 'ne']); const regDomain = (d) => { const parts = String(d || '').toLowerCase().replace(/^.+|.+$/g, '') .split('.').filter(Boolean); if (parts.length { const x = k.trim().toLowerCase(); return !TRACK_KEYS.has(x) && !TRACK_PREFIX.some((p) => x.startsWith(p)); }; const sameLangPage = (u) => { try { const x = new URL(u); const segs = x.pathname.split('/').filter(Boolean); if (segs.length > 1 && LANG_SEG.test(segs[0].toLowerCase())) segs.shift(); const q = x.search.replace(/^?/, '').split('&') .filter((pair) => pair && keepParam(pair.split('=')[0])).join('&'); return ${regDomain(x.hostname)}/${segs.join('/')}${q ? '?' + q : ''}; } catch { return String(u); } }; const dropLangMirrors = (urls) => { const best = new Map(); for (const u of urls || []) { const k = sameLangPage(u); const cur = best.get(k); if (cur === undefined) { best.set(k, u); continue; } const plain = (x) => { try { const h = new URL(x); const seg = h.pathname.split('/').filter(Boolean)[0] || ''; return (LANG_SEG.test(seg.toLowerCase()) ? 1 : 0)

  • (LANG_SEG.test(h.hostname.split('.')[0].toLowerCase()) ? 1 : 0); } catch { return 9; } }; if (plain(u) thumbOfSite(rank ? (sites || [])[rank - 1] : null); const thumbOfSite = (s) => { const u = s && (s.thumb_url || s.image_url); if (!u) return ''; const img = ``; return s.image_url ? ${img} : img; };

const CAPTION_FIELD = 'handles_written_under_the_found_image'; const CAPTION_NAMES = 'names_written_under_the_found_image_on_several_domains'; const captioned = (c) => (c.fields || []).some( (f) => f === CAPTION_FIELD || f === CAPTION_NAMES); const byEvidence = (c) => [ (c.anchor_urls || []).length ? 0 : 1, captioned(c) ? 0 : 1, -(c.n_domains || 0), -((c.support_urls || []).length), ]; const sortedCands = (idn) => [...((idn || {}).candidates || [])].sort((a, b) => { const x = byEvidence(a); const y = byEvidence(b); for (let i = 0; i { if (h.only_source_kind) return h.only_source_kind; const s = String(h.only_source || '').toLowerCase(); const one = (x) => (/ocr|visible_text|watermark/.test(x) ? 'text' : /file_name|filename/.test(x) ? 'filenames' : /sites|pages|commons|registry|serp|lens|handles|publisher/.test(x) ? 'pages' : /vlm|ai_summary|ai_overview/.test(x) ? 'model' : 'tags'); const order = ['text', 'filenames', 'pages', 'tags', 'model']; return s.split(/[,;+/]| and /).map(one) .sort((a, b) => order.indexOf(a) - order.indexOf(b))[0] || 'tags'; };

const CODE_LINE = { tags: 'lost_tags', filenames: 'lost_file_words' }; const codeKey = (h) => { const k = h.claim_key || (h.added_by === 'code' ? CODE_LINE[kindOf(h)] : ''); return k && T['code_' + k] ? k : ''; }; const codeItems = (h) => (Array.isArray(h.items) ? h.items : (String(h.claim || '').match(/«([^»]+)»/g) || []).map((x) => x.replace(/[«»]/g, ''))); const claimOf = (h) => { const k = codeKey(h); return k ? t('code_' + k, { items: codeItems(h) .map((x) => t('quote_item', { x: esc(x) })).join(', ') }) : esc(h.claim); }; const verifyOf = (h) => { const k = codeKey(h); return k ? t('code_' + k + '_verify') : esc(h.how_to_verify || ''); }; const reasonText = (fam, text, key) => { const name = key ? ${fam}_${key.k} : ''; if (!name || !T[name]) return esc(text || ''); return t(name, Object.fromEntries(Object.entries(key.a || {}) .map(([k, v]) => [k, esc(v)]))); }; const reasonList = (fam, texts, keys) => (texts || []) .map((x, i) => reasonText(fam, x, (keys || [])[i])).join('; ');

const anchorD = (x) => ((x.points || {}).tier === 'refuted' && x.d ((ph || {}).numbers || []).map((p) => ${esc(p.number)}${ p.carrier ? (${esc(p.carrier)}) : ''}).join(', '); let dByPage = null; const standsOn = (r, c) => { if (!dByPage) { dByPage = new Map(); for (const x of r.verify || []) { if (!x.page || typeof x.d !== 'number') continue; const k = sameLangPage(x.page); dByPage.set(k, Math.min(anchorD(x), dByPage.get(k) ?? 99)); } } const ds = [...(c.anchor_urls || []), ...(c.support_urls || [])] .map((u) => dByPage.get(sameLangPage(u))) .filter((d) => typeof d === 'number')

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →