Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.depromeet.piki.extractor.domain.ProductLink;
import com.depromeet.piki.extractor.domain.ProductSnapshot;
import com.depromeet.piki.extractor.domain.ProductSnapshotException;
import com.depromeet.piki.extractor.extraction.headless.HeadlessRenderException;
import com.depromeet.piki.extractor.extraction.headless.HeadlessRenderer;
import com.depromeet.piki.extractor.extraction.headless.RenderedHop;
Expand Down Expand Up @@ -40,7 +41,7 @@ public class HeadlessProductLinkExtractor implements LinkExtractionStrategy {
private record Candidate(RenderedHop hop, String html) {
}

private record Chosen(PageContent page, StructuredExtraction result) {
private record Chosen(Candidate candidate, PageContent page, StructuredExtraction result) {
}

@Override
Expand Down Expand Up @@ -72,15 +73,15 @@ public ProductSnapshot extract(ProductLink link, boolean authorized, String mode
continue;
}
if (first == null) {
first = new Chosen(page, result);
first = new Chosen(candidate, page, result);
}
if (fallback == null && !LlmInputGate.hasNothingForLlm(page.document())) {
fallback = new Chosen(page, result);
fallback = new Chosen(candidate, page, result);
}
}
Chosen chosen = fallback != null ? fallback : first;
if (chosen != null) {
return htmlSnapshotPipeline.extract(chosen.page(), chosen.result(), timing, model);
return extractChosen(chosen, link, hops, timing, model);
}
if (blocked) {
log.warn("headless hops unusable blocked=true hops={} url={}", hops.size(), link.safeLogString());
Expand All @@ -94,6 +95,33 @@ public ProductSnapshot extract(ProductLink link, boolean authorized, String mode
throw HeadlessRenderException.upstream("렌더 HTML 이 없다", null);
}

/** title 은 페이지 본문이라 남기지 않는다. */
private ProductSnapshot extractChosen(
Chosen chosen,
ProductLink link,
List<RenderedHop> hops,
String timing,
String model
) {
try {
return htmlSnapshotPipeline.extract(chosen.page(), chosen.result(), timing, model);
} catch (ProductSnapshotException e) {
RenderedHop hop = chosen.candidate().hop();
log.info(
"headless chosen hop failed code={} hop={}/{} status={} source={} html={}chars hopUrl={} url={}",
e.code(),
hops.indexOf(hop) + 1,
hops.size(),
hop.status(),
chosen.candidate().html().equals(hop.dom()) ? "dom" : "body",
chosen.page().retainedChars(),
chosen.page().finalUrl().safeLogString(),
link.safeLogString()
);
throw e;
}
}

private static List<Candidate> candidates(List<RenderedHop> hops) {
List<Candidate> candidates = new ArrayList<>();
for (RenderedHop hop : hops.reversed()) {
Expand Down
Loading