webcrawlerapi-js 1.1.7 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/api.d.ts +4 -5
- package/dist/@types/model.d.ts +23 -12
- package/dist/api.js +49 -42
- package/package.json +1 -1
package/dist/@types/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, Action } from "./model";
|
|
1
|
+
import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, ScrapeResponseError, ScrapeId, Action } from "./model";
|
|
2
2
|
import { JobStatus } from "./constants";
|
|
3
3
|
import { WebcrawlerApiError } from "./errors";
|
|
4
4
|
export { WebcrawlerApiError, JobStatus };
|
|
@@ -8,10 +8,9 @@ export declare class WebcrawlerClient {
|
|
|
8
8
|
protected apiKey: string;
|
|
9
9
|
protected basePath: string;
|
|
10
10
|
constructor(apiKey: string, basePath?: string, apiVersion?: string);
|
|
11
|
-
scrapeAsync(
|
|
12
|
-
|
|
13
|
-
scrape(
|
|
14
|
-
getScrapeResult(scrapeID: string): Promise<ScrapeResponse>;
|
|
11
|
+
scrapeAsync(request: ScrapeRequest): Promise<ScrapeId>;
|
|
12
|
+
getScrape(scrapeId: string): Promise<ScrapeResponse | ScrapeResponseError>;
|
|
13
|
+
scrape(request: ScrapeRequest, maxPolls?: number): Promise<ScrapeResponse | ScrapeResponseError>;
|
|
15
14
|
crawl(crawlRequest: CrawlRequest, actions?: Action | Action[]): Promise<Job>;
|
|
16
15
|
crawlAsync(crawlRequest: CrawlRequest, actions?: Action | Action[]): Promise<JobId>;
|
|
17
16
|
getJob(jobID: string): Promise<Job>;
|
package/dist/@types/model.d.ts
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
export interface ScrapeRequest {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
url: string;
|
|
3
|
+
output_format: string;
|
|
4
|
+
webhook_url?: string;
|
|
5
|
+
clean_selectors?: string;
|
|
6
|
+
actions?: Action[];
|
|
7
|
+
prompt?: string;
|
|
7
8
|
}
|
|
8
|
-
export interface
|
|
9
|
+
export interface ScrapeId {
|
|
9
10
|
id: string;
|
|
10
11
|
}
|
|
11
12
|
export interface ScrapeResponse {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
success: boolean;
|
|
14
|
+
status?: string;
|
|
15
|
+
markdown?: string;
|
|
16
|
+
cleaned_content?: string;
|
|
17
|
+
raw_content?: string;
|
|
15
18
|
page_status_code: number;
|
|
16
|
-
|
|
17
|
-
structured_data
|
|
18
|
-
|
|
19
|
+
page_title?: string;
|
|
20
|
+
structured_data?: any;
|
|
21
|
+
}
|
|
22
|
+
export interface ScrapeResponseError {
|
|
23
|
+
success: boolean;
|
|
24
|
+
error_code: string;
|
|
25
|
+
error_message: string;
|
|
26
|
+
status?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface JobId {
|
|
29
|
+
id: string;
|
|
19
30
|
}
|
|
20
31
|
export interface CrawlRequest {
|
|
21
32
|
url?: string;
|
package/dist/api.js
CHANGED
|
@@ -22,8 +22,9 @@ Object.defineProperty(exports, "WebcrawlerApiError", { enumerable: true, get: fu
|
|
|
22
22
|
const BASE_PATH = "https://api.webcrawlerapi.com";
|
|
23
23
|
const initialPullDelayMs = 2000;
|
|
24
24
|
const MaxPullRetries = 100;
|
|
25
|
+
const DEFAULT_POLL_DELAY_SECONDS = 2;
|
|
25
26
|
__exportStar(require("./model"), exports);
|
|
26
|
-
|
|
27
|
+
const SCRAPE_VERSION = "v2";
|
|
27
28
|
function addGetContentMethod(job) {
|
|
28
29
|
// Transform each job item to include getContent method
|
|
29
30
|
job.job_items = job.job_items.map(item => ({
|
|
@@ -68,8 +69,8 @@ class WebcrawlerClient {
|
|
|
68
69
|
this.basePath = basePath;
|
|
69
70
|
this.apiVersion = apiVersion;
|
|
70
71
|
}
|
|
71
|
-
async scrapeAsync(
|
|
72
|
-
const
|
|
72
|
+
async scrapeAsync(request) {
|
|
73
|
+
const apiUrl = `${this.basePath}/${SCRAPE_VERSION}/scrape?async=true`;
|
|
73
74
|
const requestOptions = {
|
|
74
75
|
'method': 'POST',
|
|
75
76
|
'headers': {
|
|
@@ -77,46 +78,13 @@ class WebcrawlerClient {
|
|
|
77
78
|
'Authorization': `Bearer ${this.apiKey}`,
|
|
78
79
|
"User-Agent": "WebcrawlerAPI-NodeJS-Client"
|
|
79
80
|
},
|
|
80
|
-
'body': JSON.stringify(
|
|
81
|
+
'body': JSON.stringify(request),
|
|
81
82
|
};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
async scrapeWithMeta(scrapeRequest, maxPollingRetries = MaxPullRetries) {
|
|
85
|
-
const url = `${this.basePath}/${this.apiVersion}/scrape`;
|
|
86
|
-
const requestOptions = {
|
|
87
|
-
'method': 'POST',
|
|
88
|
-
'headers': {
|
|
89
|
-
'Content-Type': 'application/json',
|
|
90
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
91
|
-
},
|
|
92
|
-
'body': JSON.stringify(scrapeRequest),
|
|
93
|
-
};
|
|
94
|
-
const jobIdResponse = await this.sendRequest(url, requestOptions);
|
|
95
|
-
if (jobIdResponse.id === '') {
|
|
96
|
-
throw new errors_1.WebcrawlerApiError('invalid_response', 'Failed to fetch job status', 0);
|
|
97
|
-
}
|
|
98
|
-
let delayIntervalMs = initialPullDelayMs;
|
|
99
|
-
for (let i = 0; i < maxPollingRetries; i++) {
|
|
100
|
-
await new Promise(resolve => setTimeout(resolve, delayIntervalMs));
|
|
101
|
-
const scrapeResult = await this.getScrapeResult(jobIdResponse.id);
|
|
102
|
-
if (scrapeRequest.debug) {
|
|
103
|
-
console.log(`Scrape result: ${JSON.stringify(scrapeResult)}`);
|
|
104
|
-
}
|
|
105
|
-
if (scrapeResult.status !== constants_1.JobStatus.IN_PROGRESS && scrapeResult.status !== constants_1.JobStatus.NEW) {
|
|
106
|
-
return scrapeResult;
|
|
107
|
-
}
|
|
108
|
-
if (scrapeResult.recommended_pull_delay_ms > 0) {
|
|
109
|
-
delayIntervalMs = scrapeResult.recommended_pull_delay_ms;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
throw new errors_1.WebcrawlerApiError('timeout', 'Scraping took too long, please retry or increase the number of polling retries', 0);
|
|
113
|
-
}
|
|
114
|
-
async scrape(scrapeRequest, maxPollingRetries = MaxPullRetries) {
|
|
115
|
-
const scrapeResult = await this.scrapeWithMeta(scrapeRequest, maxPollingRetries);
|
|
116
|
-
return scrapeResult.structured_data;
|
|
83
|
+
const response = await this.sendRequest(apiUrl, requestOptions);
|
|
84
|
+
return { id: response.id };
|
|
117
85
|
}
|
|
118
|
-
async
|
|
119
|
-
const url = `${this.basePath}/${
|
|
86
|
+
async getScrape(scrapeId) {
|
|
87
|
+
const url = `${this.basePath}/${SCRAPE_VERSION}/scrape/${scrapeId}`;
|
|
120
88
|
const requestOptions = {
|
|
121
89
|
'method': 'GET',
|
|
122
90
|
'headers': {
|
|
@@ -128,7 +96,46 @@ class WebcrawlerClient {
|
|
|
128
96
|
'Expires': '0'
|
|
129
97
|
},
|
|
130
98
|
};
|
|
131
|
-
|
|
99
|
+
const responseData = await this.sendRequest(url, requestOptions);
|
|
100
|
+
const status = responseData.status;
|
|
101
|
+
if (status === "done") {
|
|
102
|
+
return responseData;
|
|
103
|
+
}
|
|
104
|
+
else if (status === "error") {
|
|
105
|
+
return responseData;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// in_progress or any other status
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
status: status,
|
|
112
|
+
page_status_code: 0
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async scrape(request, maxPolls = 100) {
|
|
117
|
+
// Start the scraping job
|
|
118
|
+
const scrapeIdResponse = await this.scrapeAsync(request);
|
|
119
|
+
const scrapeId = scrapeIdResponse.id;
|
|
120
|
+
let polls = 0;
|
|
121
|
+
let result;
|
|
122
|
+
while (polls < maxPolls) {
|
|
123
|
+
result = await this.getScrape(scrapeId);
|
|
124
|
+
// Return immediately if scrape is done
|
|
125
|
+
if ('status' in result && result.status === "done") {
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
// Return immediately if there's an error
|
|
129
|
+
if ('error_code' in result) {
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
// Continue polling if status is in_progress or any other non-terminal status
|
|
133
|
+
// Wait before next poll
|
|
134
|
+
await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_DELAY_SECONDS * 1000));
|
|
135
|
+
polls++;
|
|
136
|
+
}
|
|
137
|
+
// Return the last known state if maxPolls is reached
|
|
138
|
+
return result;
|
|
132
139
|
}
|
|
133
140
|
async crawl(crawlRequest, actions) {
|
|
134
141
|
const url = `${this.basePath}/${this.apiVersion}/crawl`;
|