feat: Pass along script tag attributes to JS extractor for configurable rejection.

This commit is contained in:
Adam Miller
2025-10-07 11:04:12 -07:00
parent 29d2d7919b
commit 8d09cc4e50
3 changed files with 59 additions and 3 deletions
@@ -126,7 +126,31 @@ public class ConfigurableExtractorJS extends ExtractorJS {
public void addRejectRelativeIgnoreList(String ignoreString) {
rejectRelativeIgnoreSet.add(ignoreString);
}
/**
* List of regular expressions that will block extraction if matched against a script tag attribute.
* When script blocks are extracted from HTML, the tag attributes are passed as the attributeContext parameter
* to considerStrings. If any of the patterns on this list match the attributeContext, then the script block is not
* processed.
* This can be used to block processing of script blocks
*/
private List<String> rejectScriptAttributeRegexList = new ArrayList<>();
private List<Pattern> rejectScriptAttributeRegexListPatterns = new ArrayList<>();
public List<String> getRejectScriptAttributeRegexList() {
return rejectScriptAttributeRegexList;
}
public void setRejectScriptAttributeRegexList(List<String> patterns) {
rejectScriptAttributeRegexList = patterns;
rejectScriptAttributeRegexListPatterns = new ArrayList<>();
for (String p : patterns) {
rejectScriptAttributeRegexListPatterns.add(Pattern.compile(p, Pattern.CASE_INSENSITIVE));
}
}
public void addRejectScriptAttributeRegex(String pattern) {
rejectScriptAttributeRegexListPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
}
@Override
protected boolean shouldAddUri(CrawlURI curi, String candidate) {
@@ -181,5 +205,14 @@ public class ConfigurableExtractorJS extends ExtractorJS {
return false;
}
public long considerStrings(Extractor ext,
CrawlURI curi, CharSequence cs, String attributeContext) {
if(!attributeContext.isEmpty())
for(Pattern p : rejectScriptAttributeRegexListPatterns) {
if(p.matcher(attributeContext).matches()) {
return 0;
}
}
return super.considerStrings(ext, curi, cs, attributeContext);
}
}
@@ -721,7 +721,6 @@ public class ExtractorHTML extends ContentExtractor implements InitializingBean
}
}
/**
* Extract the (java)script source in the given CharSequence.
*
@@ -735,6 +734,21 @@ public class ExtractorHTML extends ContentExtractor implements InitializingBean
}
}
/**
* Extract the (java)script source in the given CharSequence.
*
* @param curi source CrawlURI
* @param cs CharSequence of javascript code
* @param attributeContext attributes of the tag from which the script
* was extracted (e.g. "onload", "onclick", "data-", etc.)
*/
protected void processScriptCode(CrawlURI curi, CharSequence cs, String attributeContext) {
if (getExtractorJS() != null && getExtractJavascript()) {
numberOfLinksExtracted.addAndGet(
getExtractorJS().considerStrings(this, curi, cs, attributeContext));
}
}
static final String JAVASCRIPT = "(?i)^javascript:.*";
/**
@@ -1041,6 +1055,11 @@ public class ExtractorHTML extends ContentExtractor implements InitializingBean
// then, apply best-effort string-analysis heuristics
// against any code present (false positives are OK)
if(endOfOpenTag > 6) {
String attributes = sequence.subSequence(6, endOfOpenTag).toString().strip();
processScriptCode(
curi, sequence.subSequence(endOfOpenTag, sequence.length()), attributes);
}
processScriptCode(
curi, sequence.subSequence(endOfOpenTag, sequence.length()));
}
@@ -137,6 +137,10 @@ public class ExtractorJS extends ContentExtractor {
CrawlURI curi, CharSequence cs) {
return considerStrings(ext, curi, cs, false);
}
public long considerStrings(Extractor ext,
CrawlURI curi, CharSequence cs, String attributeContext) {
return considerStrings(ext, curi, cs, false);
}
public long considerStrings(Extractor ext,
CrawlURI curi, CharSequence cs, boolean handlingJSFile) {