public class PhantomJSDocumentFetcher extends Object implements IHttpDocumentFetcher, IXMLConfigurable
An alternative to the GenericDocumentFetcher
which relies on an
external PhantomJS installation
to fetch web pages. While less efficient, this implementation is meant
to provide some way to crawl sites making heavy use of JavaScript to render
their pages. This class tells the PhantomJS headless browser to wait a
certain amount of time for the page to load extra content via Ajax requests
before grabbing all loaded HTML.
Relying on an external software to fetch pages is slower and not as
scalable and may be less stable. The use of GenericDocumentFetcher
should be preferred whenever possible. Use at your own risk.
Use PhantomJS 2.1 (or possibly higher).
It is usually only useful to use PhantomJS for HTML pages with JavaScript.
Other types of documents are fetched using an instance of
GenericDocumentFetcher
To find out if we are dealing with an HTML
documents, this fetcher needs to know the content type first.
By default, the content type
of a document is not known before a physical copy is obtained.
This means PhantomJS has to first download the document and if it is not an
HTML document at that point, it will be re-downloaded again with the generic
document fetcher.
By default, these content-types are considered HTML:
text/html, application/xhtml+xml, application/vnd.wap.xhtml+xml, application/x-asp
Those can be overwritten with setContentTypePattern(String)
.
To avoid downloading the document twice as described above, you can
configure a metadata fetcher (such as GenericMetadataFetcher
). This
will attempt get the content type by first making an HTTP HEAD request.
Alternatively, if you have a URL pattern that identifies your HTML pages
(and only HTML pages), you can specify it using
setReferencePattern(String)
. Only URLs matching the provided
regular expression will be fetched by PhantomJS. By default there is no
pattern for discriminating on URL references.
Normally, the HTTP crawler is meant to be used with Apache HttpClient
which is usually configured using GenericHttpClientFactory
. Doing so
ensures HTTP sessions are maintained between each URL invocation. This is
necessary for web sites expecting cookies or session information to be
carried over each requests as part of HTTP headers.
Unfortunately, session information
is not maintained between requests when invoking PhantomJS for each URLs.
This means Apache HttpClient
is not used at all and configuring
IHttpClientFactory
has no effect for fetching documents. As a result,
you may have trouble with specific web sites.
If that's the case, you may want to try adding the
HttpClientProxyCollectorListener
to your collector configuration.
This will start an HTTP proxy and force PhantomJS to use it. That proxy
will use HttpClient
to fetch documents as you would normally expect
and you can full advantage of GenericHttpClientFactory
(or
your own implementation of IHttpClientFactory
). Using a proxy
with secure (https
) requests may not always give expected
results either (e.g., screenshots maybe broken). If you run into issues
with a given site, try both approaches and pick the one that works best for
you.
Thanks to PhantomJS, one can save images of pages being crawled, including those rendered with JavaScript!
Since 2.8.0, you have to explicitely enabled screenshots with
setScreenshotEnabled(boolean)
. Also screenshots now share the same
size by default.
In addition, you can now control how screenshots are resized and how
they are stored stored.
Storage options:
collector.featured-image-inline
field.
The string is ready to be
used inline, in a <img src="..."> tag.
collector.featured-image-path
field.
Since 2.8.0, it is possible to specify a resource timeout so that slow individual page resources do not cause PhantomJS to hang for a long time.
Since 2.9.1, it is possible to specify which PhantomJS exit values
are to be considered "valid". Use a comma-separated-list of integers using
the setValidExitCodes(int...)
method. By default, only zero is
considered valid.
XML configuration entries expecting millisecond durations
can be provided in human-readable format (English only), as per
DurationParser
(e.g., "5 minutes and 30 seconds" or "5m30s").
<documentFetcher class="com.norconex.collector.http.fetch.impl.PhantomJSDocumentFetcher" detectContentType="[false|true]" detectCharset="[false|true]" screenshotEnabled="[false|true]"> <exePath>(path to PhantomJS executable)</exePath> <scriptPath> (Optional path to a PhantomJS script. Defaults to scripts/phantom.js) </scriptPath> <renderWaitTime> (Milliseconds to wait for the entire page to load. Defaults to 3000, i.e., 3 seconds.) </renderWaitTime> <resourceTimeout> (Optional Milliseconds to wait for a page resource to load. Defaults is unspecified.) </resourceTimeout> <options> <opt>(optional extra PhantomJS command-line option)</opt> <!-- You can have multiple opt tags --> </options> <referencePattern> (Regular expression matching URLs for which to use the PhantomJS browser. Non-matching URLs will fallback to using GenericDocumentFetcher.) </referencePattern> <contentTypePattern> (Regular expression matching content types for which to use the PhantomJS browser. Non-matching content types will use the GenericDocumentFetcher.) </contentTypePattern> <validExitCodes>(defaults to 0)</validExitCodes> <validStatusCodes>(defaults to 200)</validStatusCodes> <notFoundStatusCodes>(defaults to 404)</notFoundStatusCodes> <headersPrefix>(string to prefix headers)</headersPrefix> <!-- Only applicable when screenshotEnabled is true: --> <screenshotDimensions> (Pixel size of the browser page area to capture: [width]x[height]. E.g., 800x600. Only used when a screenshot path is specified. Default is undefined. It will try to load all it can and may produce vertically long images.) </screenshotDimensions> <screenshotZoomFactor> (A decimal value to scale the screenshot image. E.g., 0.25 will make the image 25% its regular size, which is 25% of the above dimension if specified. Default is 1, i.e., 100%) </screenshotZoomFactor> <screenshotScaleDimensions> (Target pixel size the main image should be scaled to. Default is 300.) </screenshotScaleDimensions> <screenshotScaleStretch> [false|true] (Whether to stretch to match scale size. Default keeps aspect ratio.) </screenshotScaleStretch> <screenshotScaleQuality> [auto|low|medium|high|max] (Default is "auto", which tries the best balance between quality and speed based on image size. The lower the quality the faster it is to scale images.) </screenshotScaleQuality> <screenshotImageFormat> (Target format of stored image. E.g., "jpg", "png", "gif", "bmp", ... Default is "png") </screenshotImageFormat> <screenshotStorage> [disk|inline] (One or both, comma-separated. Default is "disk".) </screenshotStorage> <!-- Only applicable for "disk" storage: --> <screenshotStorageDiskDir structure="[url2path|date|datetime]"> (Path where to save screenshots.) </screenshotStorageDiskDir> <screenshotStorageDiskField> (Overwrite default field where to store the screenshot path.) </screenshotStorageDiskField> <!-- Only applicable for "inline" storage: --> <screenshotStorageInlineField> (Overwrite default field where to store the inline screenshot.) </screenshotStorageInlineField> </documentFetcher>
When specifying an image size, the format is [width]x[height]
or a single value. When a single value is used, that value represents both
the width and height (i.e., a square).
The "validStatusCodes" and "notFoundStatusCodes" elements expect a coma-separated list of HTTP response code. If a code is added in both elements, the valid list takes precedence.
The following configures HTTP Collector to use PhantomJS with a proxy to use HttpClient, only for URLs ending with ".html".
<httpcollector id="MyHttpCollector"> ... <crawlers> <crawler id="MyCrawler"> ... <documentFetcher class="com.norconex.collector.http.fetch.impl.PhantomJSDocumentFetcher"> <exePath>/path/to/phantomjs.exe</exePath> <renderWaitTime>5000</renderWaitTime> <referencePattern>^.*\.html$</referencePattern> </documentFetcher> ... </crawler> </crawlers> ... <!-- Only if you need to use the HttpClient proxy (see documentation): --> <collectorListeners> <listener class="com.norconex.collector.http.fetch.impl.HttpClientProxyCollectorListener" /> </collectorListeners> </httpcollector>
HttpClientProxyCollectorListener
Modifier and Type | Class and Description |
---|---|
static class |
PhantomJSDocumentFetcher.Quality |
static class |
PhantomJSDocumentFetcher.Storage |
static class |
PhantomJSDocumentFetcher.StorageDiskStructure |
Modifier and Type | Field and Description |
---|---|
static String |
COLLECTOR_PHANTOMJS_SCREENSHOT_INLINE |
static String |
COLLECTOR_PHANTOMJS_SCREENSHOT_PATH |
static String |
DEFAULT_CONTENT_TYPE_PATTERN |
static int |
DEFAULT_RENDER_WAIT_TIME |
static String |
DEFAULT_SCREENSHOT_IMAGE_FORMAT |
static Dimension |
DEFAULT_SCREENSHOT_SCALE_SIZE |
static PhantomJSDocumentFetcher.Storage |
DEFAULT_SCREENSHOT_STORAGE |
static String |
DEFAULT_SCREENSHOT_STORAGE_DISK_DIR |
static float |
DEFAULT_SCREENSHOT_ZOOM_FACTOR |
static String |
DEFAULT_SCRIPT_PATH |
Constructor and Description |
---|
PhantomJSDocumentFetcher() |
PhantomJSDocumentFetcher(int[] validStatusCodes) |
Modifier and Type | Method and Description |
---|---|
boolean |
equals(Object other) |
HttpFetchResponse |
fetchDocument(org.apache.http.client.HttpClient httpClient,
HttpDocument doc)
Fetches HTTP document and saves it to a local file
|
String |
getContentTypePattern() |
String |
getExePath() |
String |
getHeadersPrefix() |
int[] |
getNotFoundStatusCodes() |
String[] |
getOptions() |
String |
getReferencePattern() |
int |
getRenderWaitTime() |
int |
getResourceTimeout()
Gets the milliseconds timeout after which any resource requested will
stop trying and proceed with other parts of the page.
|
Dimension |
getScreenshotDimensions() |
String |
getScreenshotDir()
Deprecated.
Since 2.8.0, use
getScreenshotStorageDiskDir() |
String |
getScreenshotImageFormat()
Gets the screenshot image format (jpg, png, gif, bmp, etc.).
|
Dimension |
getScreenshotScaleDimensions()
Gets the pixel dimensions we want the stored screenshot to have.
|
PhantomJSDocumentFetcher.Quality |
getScreenshotScaleQuality()
Gets the screenshot scaling quality to use when when storage
is "disk" or "inline".
|
PhantomJSDocumentFetcher.Storage[] |
getScreenshotStorage()
Gets the screenshot storage mechanisms.
|
String |
getScreenshotStorageDiskDir()
Gets the directory where screenshots are saved when storage is "disk".
|
String |
getScreenshotStorageDiskField()
Gets the target document metadata field where to store the path
to thescreen shot image file when storage is "disk".
|
PhantomJSDocumentFetcher.StorageDiskStructure |
getScreenshotStorageDiskStructure()
Gets the screenshot directory structure to create when storage
is "disk".
|
String |
getScreenshotStorageInlineField()
Gets the target document metadata field where to store the inline
(Base64) screenshot image when storage is "inline".
|
float |
getScreenshotZoomFactor() |
String |
getScriptPath() |
int[] |
getValidExitCodes() |
int[] |
getValidStatusCodes() |
int |
hashCode() |
boolean |
isDetectCharset() |
boolean |
isDetectContentType() |
boolean |
isScreenshotEnabled()
Gets whether to enable taking screenshot of crawled web pages.
|
boolean |
isScreenshotScaleStretch()
Gets whether the screenshot should be stretch to to fill all
the scale dimensions.
|
void |
loadFromXML(Reader in) |
void |
saveToXML(Writer out) |
void |
setContentTypePattern(String contentTypePattern) |
void |
setDetectCharset(boolean detectCharset) |
void |
setDetectContentType(boolean detectContentType) |
void |
setExePath(String exePath) |
void |
setHeadersPrefix(String headersPrefix) |
void |
setNotFoundStatusCodes(int... notFoundStatusCodes) |
void |
setOptions(String... options) |
void |
setReferencePattern(String referencePattern) |
void |
setRenderWaitTime(int renderWaitTime) |
void |
setResourceTimeout(int resourceTimeout)
Sets the milliseconds timeout after which any resource requested will
stop trying and proceed with other parts of the page.
|
void |
setScreenshotDimensions(Dimension screenshotDimensions) |
void |
setScreenshotDimensions(int width,
int height) |
void |
setScreenshotDir(String screenshotDir)
Deprecated.
Since 2.8.0, use
setScreenshotStorageDiskDir(String) |
void |
setScreenshotEnabled(boolean screenshotEnabled)
Sets whether to enable taking screenshot of crawled web pages.
|
void |
setScreenshotImageFormat(String screenshotImageFormat)
Sets the screenshot image format (jpg, png, gif, bmp, etc.).
|
void |
setScreenshotScaleDimensions(Dimension screenshotScaleDimensions)
Sets the pixel dimensions we want the stored screenshot to have.
|
void |
setScreenshotScaleDimensions(int width,
int height)
Sets the pixel dimensions we want the stored screenshot to have.
|
void |
setScreenshotScaleQuality(PhantomJSDocumentFetcher.Quality screenshotScaleQuality)
Sets the screenshot scaling quality to use when when storage
is "disk" or "inline".
|
void |
setScreenshotScaleStretch(boolean screenshotScaleStretch)
Sets whether the screenshot should be stretch to to fill all
the scale dimensions.
|
void |
setScreenshotStorage(PhantomJSDocumentFetcher.Storage... screenshotStorage)
Sets the screenshot storage mechanisms.
|
void |
setScreenshotStorageDiskDir(String screenshotStorageDiskDir)
Sets the directory where screenshots are saved when storage is "disk".
|
void |
setScreenshotStorageDiskField(String screenshotStorageDiskField)
Sets the target document metadata field where to store the path
to thescreen shot image file when storage is "disk".
|
void |
setScreenshotStorageDiskStructure(PhantomJSDocumentFetcher.StorageDiskStructure screenshotStorageDiskStructure)
Sets the screenshot directory structure to create when storage
is "disk".
|
void |
setScreenshotStorageInlineField(String screenshotStorageInlineField)
Sets the target document metadata field where to store the inline
(Base64) screenshot image when storage is "inline".
|
void |
setScreenshotZoomFactor(float screenshotZoomFactor) |
void |
setScriptPath(String scriptPath) |
void |
setValidExitCodes(int... validExitCodes) |
void |
setValidStatusCodes(int... validStatusCodes) |
String |
toString() |
public static final String DEFAULT_SCRIPT_PATH
public static final int DEFAULT_RENDER_WAIT_TIME
public static final float DEFAULT_SCREENSHOT_ZOOM_FACTOR
public static final String DEFAULT_CONTENT_TYPE_PATTERN
public static final String DEFAULT_SCREENSHOT_STORAGE_DISK_DIR
public static final PhantomJSDocumentFetcher.Storage DEFAULT_SCREENSHOT_STORAGE
public static final String DEFAULT_SCREENSHOT_IMAGE_FORMAT
public static final Dimension DEFAULT_SCREENSHOT_SCALE_SIZE
public static final String COLLECTOR_PHANTOMJS_SCREENSHOT_PATH
public static final String COLLECTOR_PHANTOMJS_SCREENSHOT_INLINE
public PhantomJSDocumentFetcher()
public PhantomJSDocumentFetcher(int[] validStatusCodes)
public String getExePath()
public void setExePath(String exePath)
public String getScriptPath()
public void setScriptPath(String scriptPath)
public int getRenderWaitTime()
public void setRenderWaitTime(int renderWaitTime)
public String[] getOptions()
public void setOptions(String... options)
@Deprecated public String getScreenshotDir()
getScreenshotStorageDiskDir()
@Deprecated public void setScreenshotDir(String screenshotDir)
setScreenshotStorageDiskDir(String)
screenshotDir
- screenshot directorypublic String getScreenshotStorageDiskDir()
public void setScreenshotStorageDiskDir(String screenshotStorageDiskDir)
screenshotStorageDiskDir
- directorypublic String getScreenshotStorageDiskField()
public void setScreenshotStorageDiskField(String screenshotStorageDiskField)
screenshotStorageDiskField
- field namepublic String getScreenshotStorageInlineField()
public void setScreenshotStorageInlineField(String screenshotStorageInlineField)
screenshotStorageInlineField
- field namepublic boolean isScreenshotEnabled()
true
if enabledpublic void setScreenshotEnabled(boolean screenshotEnabled)
screenshotEnabled
- true
if enabledpublic Dimension getScreenshotDimensions()
public void setScreenshotDimensions(int width, int height)
public void setScreenshotDimensions(Dimension screenshotDimensions)
public float getScreenshotZoomFactor()
public void setScreenshotZoomFactor(float screenshotZoomFactor)
public int[] getValidExitCodes()
public final void setValidExitCodes(int... validExitCodes)
public int[] getValidStatusCodes()
public final void setValidStatusCodes(int... validStatusCodes)
public int[] getNotFoundStatusCodes()
public final void setNotFoundStatusCodes(int... notFoundStatusCodes)
public String getHeadersPrefix()
public void setHeadersPrefix(String headersPrefix)
public boolean isDetectContentType()
public void setDetectContentType(boolean detectContentType)
public boolean isDetectCharset()
public void setDetectCharset(boolean detectCharset)
public String getContentTypePattern()
public void setContentTypePattern(String contentTypePattern)
public String getReferencePattern()
public void setReferencePattern(String referencePattern)
public int getResourceTimeout()
-1
if undefinedpublic void setResourceTimeout(int resourceTimeout)
resourceTimeout
- the timeout value, or -1
for undefinedpublic Dimension getScreenshotScaleDimensions()
public void setScreenshotScaleDimensions(Dimension screenshotScaleDimensions)
screenshotScaleDimensions
- dimensionpublic void setScreenshotScaleDimensions(int width, int height)
width
- image widthheight
- image heightpublic boolean isScreenshotScaleStretch()
true
to stretchpublic void setScreenshotScaleStretch(boolean screenshotScaleStretch)
screenshotScaleStretch
- true
to stretchpublic String getScreenshotImageFormat()
public void setScreenshotImageFormat(String screenshotImageFormat)
screenshotImageFormat
- image formatpublic PhantomJSDocumentFetcher.Storage[] getScreenshotStorage()
public void setScreenshotStorage(PhantomJSDocumentFetcher.Storage... screenshotStorage)
screenshotStorage
- storage mechanismspublic PhantomJSDocumentFetcher.StorageDiskStructure getScreenshotStorageDiskStructure()
public void setScreenshotStorageDiskStructure(PhantomJSDocumentFetcher.StorageDiskStructure screenshotStorageDiskStructure)
screenshotStorageDiskStructure
- directory structurepublic PhantomJSDocumentFetcher.Quality getScreenshotScaleQuality()
PhantomJSDocumentFetcher.Quality.AUTO
public void setScreenshotScaleQuality(PhantomJSDocumentFetcher.Quality screenshotScaleQuality)
screenshotScaleQuality
- qualitypublic HttpFetchResponse fetchDocument(org.apache.http.client.HttpClient httpClient, HttpDocument doc)
IHttpDocumentFetcher
fetchDocument
in interface IHttpDocumentFetcher
httpClient
- the HTTP clientdoc
- the document to fetch and savepublic void loadFromXML(Reader in)
loadFromXML
in interface IXMLConfigurable
public void saveToXML(Writer out) throws IOException
saveToXML
in interface IXMLConfigurable
IOException
Copyright © 2009–2021 Norconex Inc.. All rights reserved.