webcrawlerapi-js 1.1.7 → 2.0.0
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 +50 -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,9 @@ 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`;
|
|
74
|
+
console.log(request);
|
|
73
75
|
const requestOptions = {
|
|
74
76
|
'method': 'POST',
|
|
75
77
|
'headers': {
|
|
@@ -77,46 +79,13 @@ class WebcrawlerClient {
|
|
|
77
79
|
'Authorization': `Bearer ${this.apiKey}`,
|
|
78
80
|
"User-Agent": "WebcrawlerAPI-NodeJS-Client"
|
|
79
81
|
},
|
|
80
|
-
'body': JSON.stringify(
|
|
82
|
+
'body': JSON.stringify(request),
|
|
81
83
|
};
|
|
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;
|
|
84
|
+
const response = await this.sendRequest(apiUrl, requestOptions);
|
|
85
|
+
return { id: response.id };
|
|
117
86
|
}
|
|
118
|
-
async
|
|
119
|
-
const url = `${this.basePath}/${
|
|
87
|
+
async getScrape(scrapeId) {
|
|
88
|
+
const url = `${this.basePath}/${SCRAPE_VERSION}/scrape/${scrapeId}`;
|
|
120
89
|
const requestOptions = {
|
|
121
90
|
'method': 'GET',
|
|
122
91
|
'headers': {
|
|
@@ -128,7 +97,46 @@ class WebcrawlerClient {
|
|
|
128
97
|
'Expires': '0'
|
|
129
98
|
},
|
|
130
99
|
};
|
|
131
|
-
|
|
100
|
+
const responseData = await this.sendRequest(url, requestOptions);
|
|
101
|
+
const status = responseData.status;
|
|
102
|
+
if (status === "done") {
|
|
103
|
+
return responseData;
|
|
104
|
+
}
|
|
105
|
+
else if (status === "error") {
|
|
106
|
+
return responseData;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// in_progress or any other status
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
status: status,
|
|
113
|
+
page_status_code: 0
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async scrape(request, maxPolls = 100) {
|
|
118
|
+
// Start the scraping job
|
|
119
|
+
const scrapeIdResponse = await this.scrapeAsync(request);
|
|
120
|
+
const scrapeId = scrapeIdResponse.id;
|
|
121
|
+
let polls = 0;
|
|
122
|
+
let result;
|
|
123
|
+
while (polls < maxPolls) {
|
|
124
|
+
result = await this.getScrape(scrapeId);
|
|
125
|
+
// Return immediately if scrape is done
|
|
126
|
+
if ('status' in result && result.status === "done") {
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
// Return immediately if there's an error
|
|
130
|
+
if ('error_code' in result) {
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
// Continue polling if status is in_progress or any other non-terminal status
|
|
134
|
+
// Wait before next poll
|
|
135
|
+
await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_DELAY_SECONDS * 1000));
|
|
136
|
+
polls++;
|
|
137
|
+
}
|
|
138
|
+
// Return the last known state if maxPolls is reached
|
|
139
|
+
return result;
|
|
132
140
|
}
|
|
133
141
|
async crawl(crawlRequest, actions) {
|
|
134
142
|
const url = `${this.basePath}/${this.apiVersion}/crawl`;
|