webcrawlerapi-js 1.1.6 → 1.1.7

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.
Files changed (3) hide show
  1. package/README.md +40 -78
  2. package/dist/api.js +40 -35
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -20,34 +20,36 @@ The package is regularly updated with new features and improvements to ensure th
20
20
  ## JavaScript Examples
21
21
 
22
22
  ### Synchronous Job
23
- In this mode, the promise will be resolved when all data is ready. Synchronous jobs are perfect for quick scraping tasks where you need immediate results and don't want to handle polling logic.
23
+ In this mode, the promise will be resolved when all data is ready. Synchronous jobs are perfect for quick scraping tasks where you need immediate results and don't want to handle polling logic. However, for long running jobs we recommend to use async crawling or the webhook.
24
24
 
25
25
  ```javascript
26
26
  import webcrawlerapi from "webcrawlerapi-js"
27
27
 
28
28
  async function main() {
29
- const client = new WebcrawlerClient(
30
- "YOUR API ACCESS KEY HERE",
31
- )
29
+ const client = new WebcrawlerClient("YOUR API ACCESS KEY HERE")
32
30
 
33
31
  try {
34
- const syncJob = await client.crawl({
32
+ const crawlJob = await client.crawl({
35
33
  "items_limit": 10,
36
- "url": "https://stripe.com/",
34
+ "url": "https://books.toscrape.com/",
37
35
  "scrape_type": "markdown"
38
36
  })
39
37
 
40
- for (const item of syncJob.job_items) {
38
+ // Get job details
39
+ const job = await client.getJob(crawlJob.id);
40
+ console.log("Job status:", job.status);
41
+
42
+ // Output item content
43
+ for (const item of job.job_items) {
41
44
  const content = await item.getContent()
45
+ console.log("---- Title: " + item.title + "----")
42
46
  console.log(content.slice(0, 100))
43
47
  }
44
- console.log(syncJob)
45
-
46
48
  } catch (error) {
47
49
  if (error instanceof webcrawlerapi.WebcrawlerApiError) {
48
50
  console.error("Webcrawler error:", error.message)
49
51
  }
50
- return
52
+ console.error(error)
51
53
  }
52
54
  }
53
55
 
@@ -61,27 +63,32 @@ In this mode, you get a job ID immediately and can poll for results. Asynchronou
61
63
  import webcrawlerapi from "webcrawlerapi-js"
62
64
 
63
65
  async function main() {
64
- const client = new WebcrawlerClient(
65
- "YOUR API ACCESS KEY HERE",
66
- )
66
+ const client = new WebcrawlerClient("YOUR API ACCESS KEY HERE")
67
67
 
68
68
  try {
69
- // Get job ID immediately
69
+ try {
70
70
  const jobWithId = await client.crawlAsync({
71
71
  "items_limit": 10,
72
- "url": "https://stripe.com/",
72
+ "url": "https://books.toscrape.com/",
73
73
  "scrape_type": "markdown"
74
74
  })
75
-
75
+
76
76
  // Poll for job completion
77
77
  const jobId = jobWithId.id
78
78
  let asyncJob = await client.getJob(jobId)
79
-
79
+
80
80
  // Check job status
81
- console.log("Job status:", asyncJob.status)
82
-
81
+ console.log("Job id:", asyncJob.id)
82
+ console.log("Dashboard link:", `https://dash.webcrawlerapi.com/jobs/job/${asyncJob.id}`)
83
+
84
+ //wait until job is done
85
+ while (asyncJob.status !== "done") {
86
+ await new Promise(resolve => setTimeout(resolve, 1000));
87
+ asyncJob = await client.getJob(jobId)
88
+ }
89
+
83
90
  // Once complete, access results
84
- if (asyncJob.status === "completed") {
91
+ if (asyncJob.status === "done") {
85
92
  for (const item of asyncJob.job_items) {
86
93
  const content = await item.getContent()
87
94
  console.log(content.slice(0, 100))
@@ -91,6 +98,8 @@ async function main() {
91
98
  if (error instanceof webcrawlerapi.WebcrawlerApiError) {
92
99
  console.error("Webcrawler error:", error.message)
93
100
  }
101
+ console.error(error)
102
+ return
94
103
  }
95
104
  }
96
105
 
@@ -102,87 +111,40 @@ main().catch(console.error)
102
111
  The SDK provides full TypeScript support with type safety and error handling. Our TypeScript integration ensures you catch potential issues at compile-time and provides excellent IDE support with autocompletion and inline documentation.
103
112
 
104
113
  ```typescript
105
- import { WebcrawlerClient, WebcrawlerApiError } from "webcrawlerapi-js"
114
+ import {WebcrawlerClient, WebcrawlerApiError} from "webcrawlerapi-js";
106
115
 
107
116
  async function main() {
108
- const client = new WebcrawlerClient(
109
- "YOUR_API_KEY",
110
- // Optional base URL, defaults to production API
111
- "http://localhost:8080"
112
- )
117
+ const client = new WebcrawlerClient("YOUR_API_KEY")
113
118
 
114
119
  try {
115
120
  // Basic crawl with markdown
116
121
  const syncJob = await client.crawl({
117
- "items_limit": 2,
122
+ "items_limit": 10,
118
123
  "url": "https://books.toscrape.com/",
119
- "scrape_type": "markdown"
120
- })
121
-
122
- // Type-safe status check
123
- if (syncJob.status === "done") {
124
- for (const item of syncJob.job_items) {
125
- if (item.markdown_content_url) {
126
- // Access typed properties
127
- console.log("Status code:", item.page_status_code)
128
- console.log("Content URL:", item.markdown_content_url)
129
- }
130
- }
124
+ "scrape_type": "markdown",
131
125
  }
132
-
133
- // Using specialized scraper
134
- const scrapeJob = await client.scrape({
135
- "crawler_id": "webcrawler/url-to-md",
136
- "input": {
137
- "url": "https://books.toscrape.com/"
138
- }
139
- })
140
-
141
- if (scrapeJob.status === "done") {
142
- const content = scrapeJob.getContent()
143
- console.log("Scraped content:", content)
126
+ )
127
+ // Type-safe status check
128
+ for (const item of syncJob.job_items) {
129
+ const content = await item.getContent()
130
+ console.log(content.slice(0,100))
144
131
  }
145
-
146
132
  } catch (error) {
147
- // Type-safe error handling
148
133
  if (error instanceof WebcrawlerApiError) {
149
134
  console.error("API Error:", error.errorCode, error.message)
150
- // errorCode is typed and can be used for specific error handling
151
- if (error.errorCode === "invalid_request") {
152
- // Handle invalid request
153
- }
154
135
  }
136
+ console.log(error)
155
137
  }
156
138
  }
157
139
 
158
140
  main().catch(console.error)
159
141
  ```
160
142
 
161
- ### Error Handling
162
-
163
- The SDK provides typed error handling through the `WebcrawlerApiError` class. Our error handling system is designed to provide detailed, actionable feedback that helps you quickly identify and resolve issues in your scraping pipeline.
164
-
165
- ```typescript
166
- try {
167
- const syncJob = await client.crawl({
168
- "items_limit": 2,
169
- "url": "https://books.toscrape.com/",
170
- // This will cause an error due to missing scrape_type
171
- })
172
- } catch (error) {
173
- if (error instanceof WebcrawlerApiError) {
174
- // Typed error properties
175
- console.error("Error code:", error.errorCode)
176
- console.error("Error message:", error.message)
177
- }
178
- }
179
- ```
180
-
181
143
  ## Response Structure
182
144
 
183
145
  Example of a job response. The response structure is carefully designed to provide comprehensive information about your scraping job, including detailed status updates, timing information, and resource usage metrics.
184
146
 
185
- ```json
147
+ ```js
186
148
  {
187
149
  id: '49c4942b-b7d9-4d62-94b5-b54a3016ac51',
188
150
  url: 'https://stripe.com/',
package/dist/api.js CHANGED
@@ -23,6 +23,44 @@ const BASE_PATH = "https://api.webcrawlerapi.com";
23
23
  const initialPullDelayMs = 2000;
24
24
  const MaxPullRetries = 100;
25
25
  __exportStar(require("./model"), exports);
26
+ // Helper function to add getContent method to job items
27
+ function addGetContentMethod(job) {
28
+ // Transform each job item to include getContent method
29
+ job.job_items = job.job_items.map(item => ({
30
+ ...item,
31
+ getContent: async function () {
32
+ if (job.status !== constants_1.JobStatus.DONE || this.status !== constants_1.JobStatus.DONE) {
33
+ return null;
34
+ }
35
+ let contentUrl;
36
+ switch (job.scrape_type) {
37
+ case 'html':
38
+ contentUrl = this.raw_content_url;
39
+ break;
40
+ case 'cleaned':
41
+ contentUrl = this.cleaned_content_url;
42
+ break;
43
+ case 'markdown':
44
+ contentUrl = this.markdown_content_url;
45
+ break;
46
+ }
47
+ if (!contentUrl) {
48
+ return null;
49
+ }
50
+ const response = await fetch(contentUrl, {
51
+ headers: {
52
+ 'Accept-Encoding': 'gzip, deflate, br',
53
+ 'Accept': '*/*'
54
+ }
55
+ });
56
+ if (!response.ok) {
57
+ throw new Error(`Failed to fetch content: ${response.statusText}`);
58
+ }
59
+ return await response.text();
60
+ }
61
+ }));
62
+ return job;
63
+ }
26
64
  class WebcrawlerClient {
27
65
  constructor(apiKey, basePath = BASE_PATH, apiVersion = "v1") {
28
66
  this.apiVersion = "v1";
@@ -120,40 +158,6 @@ class WebcrawlerClient {
120
158
  const timestamp = new Date().getTime();
121
159
  const job = await this.getJob(`${jobIdResponse.id}?t=${timestamp}`);
122
160
  if (job.status !== constants_1.JobStatus.IN_PROGRESS && job.status !== constants_1.JobStatus.NEW) {
123
- // Transform each job item to include getContent method
124
- job.job_items = job.job_items.map(item => ({
125
- ...item,
126
- getContent: async function () {
127
- if (job.status !== constants_1.JobStatus.DONE || this.status !== constants_1.JobStatus.DONE) {
128
- return null;
129
- }
130
- let contentUrl;
131
- switch (job.scrape_type) {
132
- case 'html':
133
- contentUrl = this.raw_content_url;
134
- break;
135
- case 'cleaned':
136
- contentUrl = this.cleaned_content_url;
137
- break;
138
- case 'markdown':
139
- contentUrl = this.markdown_content_url;
140
- break;
141
- }
142
- if (!contentUrl) {
143
- return null;
144
- }
145
- const response = await fetch(contentUrl, {
146
- headers: {
147
- 'Accept-Encoding': 'gzip, deflate, br',
148
- 'Accept': '*/*'
149
- }
150
- });
151
- if (!response.ok) {
152
- throw new Error(`Failed to fetch content: ${response.statusText}`);
153
- }
154
- return await response.text();
155
- }
156
- }));
157
161
  return job;
158
162
  }
159
163
  if (job.recommended_pull_delay_ms > 0) {
@@ -191,7 +195,8 @@ class WebcrawlerClient {
191
195
  'Expires': '0'
192
196
  }
193
197
  };
194
- return await this.sendRequest(url, requestOptions);
198
+ const job = await this.sendRequest(url, requestOptions);
199
+ return addGetContentMethod(job);
195
200
  }
196
201
  async sendRequest(url, requestOptions) {
197
202
  let response;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcrawlerapi-js",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
 
5
5
  "description": "JS client for WebcrawlerAPI",
6
6
  "main": "./dist/api.js",