apick-api 4.4.0 → 4.5.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/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 4.5.0
2
+
3
+ - Added `coupangProduct(urlOrProductId)`, `naverShoppingProduct(url)`, `linkedinProfile(url)`, `linkedinCompany(url)` and `linkedinJob(url)` with the matching result types (`CoupangProduct`, `NaverShoppingProduct`, `LinkedinProfile`, `LinkedinCompany`, `LinkedinJob`). Coupang takes a product number or `/vp/products/{id}` URL, Naver takes a brand store product URL (`brand.naver.com/{store}/products/{id}`), and LinkedIn takes profile (`/in/`), company (`/company/`) or job posting (`/jobs/view/`) URLs. Each call is synchronous; failed calls are not charged.
4
+ - 쿠팡 상품·네이버 브랜드스토어 상품·링크드인 프로필/회사/채용공고 조회 메서드 `coupangProduct()`·`naverShoppingProduct()`·`linkedinProfile()`·`linkedinCompany()`·`linkedinJob()` 과 결과 타입(`CoupangProduct`, `NaverShoppingProduct`, `LinkedinProfile`, `LinkedinCompany`, `LinkedinJob`)을 추가했습니다. 쿠팡은 상품 번호나 `/vp/products/{번호}` 주소, 네이버는 브랜드스토어 상품 주소(`brand.naver.com/{스토어}/products/{번호}`), 링크드인은 프로필(`/in/`)·회사(`/company/`)·채용공고(`/jobs/view/`) 주소를 받습니다. 모두 동기 응답이며 실패한 호출은 과금되지 않습니다.
5
+
1
6
  # 4.4.0
2
7
 
3
8
  - Removed the YouTube download methods `youtubeFormats()`, `downloadYoutubeVideo()` and `downloadYoutubeAudio()` and their result types (`YoutubeFormats`, `YoutubeVideoFormat`, `YoutubeAudioFormat`, `YoutubeDownloadLink`, `YoutubeVideoDownloadOptions`, `YoutubeAudioDownloadOptions`) — the matching endpoints are gone. `youtubeMetadata()`, `youtubeThumbnail()`, `youtubeSubtitleList()`, `youtubeSubtitle()`, `youtubeSearch()`, `youtubeChannel()`, `youtubePlaylist()`, `youtubeHashtag()` and `youtubeComments()` are unchanged.
package/README.md CHANGED
@@ -90,6 +90,11 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
90
90
  | `amazonProduct(urlOrAsin)` | 아마존 상품 정보 / Amazon product | JSON |
91
91
  | `xProfile(usernameOrUrl)` | X 공개 프로필·최근 게시물 / X public profile and recent posts | JSON |
92
92
  | `xPost(url)` | X 게시물 / X post | JSON |
93
+ | `coupangProduct(urlOrProductId)` | 쿠팡 상품 정보 / Coupang product | JSON |
94
+ | `naverShoppingProduct(url)` | 네이버 브랜드스토어 상품 정보 / Naver brand store product | JSON |
95
+ | `linkedinProfile(url)` | 링크드인 프로필 / LinkedIn profile | JSON |
96
+ | `linkedinCompany(url)` | 링크드인 회사 정보 / LinkedIn company | JSON |
97
+ | `linkedinJob(url)` | 링크드인 채용공고 / LinkedIn job posting | JSON |
93
98
  | `createInstagramPostsJob(usernameOrUrl, options)` | 인스타그램 게시물 목록 수집 접수(최대 100) / Instagram posts job | JSON |
94
99
  | `createInstagramCommentsJob(url, options)` | 인스타그램 댓글 수집 접수(최대 15) / Instagram comments job | JSON |
95
100
  | `createTiktokSearchJob(keyword, options)` | 틱톡 키워드 영상 검색 접수(최대 50) / TikTok keyword search job | JSON |
package/docs/guide.en.md CHANGED
@@ -84,8 +84,15 @@ const post = await client.instagramPost('https://www.instagram.com/p/DeHufcWDCjf
84
84
  const tiktok = await client.tiktokProfile('https://www.tiktok.com/@tiktok');
85
85
  const product = await client.amazonProduct('B0BDHWDR12');
86
86
  const x = await client.xProfile('NASA');
87
+ const coupang = await client.coupangProduct('https://www.coupang.com/vp/products/7812020679');
88
+ const naver = await client.naverShoppingProduct('https://brand.naver.com/pulmuonebynature/products/4995061380');
89
+ const profile = await client.linkedinProfile('https://www.linkedin.com/in/example/');
90
+ const company = await client.linkedinCompany('https://www.linkedin.com/company/example/');
91
+ const job = await client.linkedinJob('https://www.linkedin.com/jobs/view/4001234567/');
87
92
  ```
88
93
 
94
+ Coupang accepts a product number or a product URL (`/vp/products/{id}`), and Naver accepts a brand store product URL (`brand.naver.com/{store}/products/{id}`). LinkedIn accepts profile (`/in/`), company (`/company/`) and job posting (`/jobs/view/`) URLs.
95
+
89
96
  ### Collection jobs (lists, comments, search, reviews)
90
97
 
91
98
  Products that collect many items return a `job_id` immediately. Submitting reserves `maxResults` × unit price; when you read the result, only the results actually returned are charged and the rest is refunded. Failed jobs and missing targets are fully refunded, and results are kept for 72 hours. Comment and review authors are public usernames only.
package/docs/guide.ko.md CHANGED
@@ -84,8 +84,15 @@ const post = await client.instagramPost('https://www.instagram.com/p/DeHufcWDCjf
84
84
  const tiktok = await client.tiktokProfile('https://www.tiktok.com/@tiktok');
85
85
  const product = await client.amazonProduct('B0BDHWDR12');
86
86
  const x = await client.xProfile('NASA');
87
+ const coupang = await client.coupangProduct('https://www.coupang.com/vp/products/7812020679');
88
+ const naver = await client.naverShoppingProduct('https://brand.naver.com/pulmuonebynature/products/4995061380');
89
+ const profile = await client.linkedinProfile('https://www.linkedin.com/in/example/');
90
+ const company = await client.linkedinCompany('https://www.linkedin.com/company/example/');
91
+ const job = await client.linkedinJob('https://www.linkedin.com/jobs/view/4001234567/');
87
92
  ```
88
93
 
94
+ 쿠팡은 상품 번호나 상품 주소(`/vp/products/{번호}`)를, 네이버는 브랜드스토어 상품 주소(`brand.naver.com/{스토어}/products/{번호}`)를 받습니다. 링크드인은 프로필(`/in/`)·회사(`/company/`)·채용공고(`/jobs/view/`) 주소를 받습니다.
95
+
89
96
  ### 수집 작업(목록·댓글·검색·리뷰)
90
97
 
91
98
  여러 건을 모으는 상품은 접수 즉시 `job_id` 를 돌려줍니다. 접수 때 `maxResults` × 단가를 예약하고, 결과를 받을 때 실제 결과 건수만 차감한 뒤 나머지는 돌려드립니다. 실패하거나 대상이 없으면 전액 환불되며 결과는 72시간 보관합니다. 댓글·리뷰 작성자는 공개 사용자명만 제공합니다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apick-api",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "Official zero-dependency Node.js client for APICK data, AI, and image APIs. 에이픽 데이터·AI·이미지 API 공식 Node.js SDK.",
5
5
  "type": "module",
6
6
  "main": "./src/index.cjs",
package/src/index.cjs CHANGED
@@ -47,6 +47,11 @@ const SERVICE_DEFINITIONS = Object.freeze({
47
47
  amazonProduct: { endpoint: '/rest/amazon_product', timeoutMs: 110_000, output: 'json' },
48
48
  xProfile: { endpoint: '/rest/x_profile', timeoutMs: 110_000, output: 'json' },
49
49
  xPost: { endpoint: '/rest/x_post', timeoutMs: 110_000, output: 'json' },
50
+ coupangProduct: { endpoint: '/rest/coupang_product', timeoutMs: 110_000, output: 'json' },
51
+ naverShoppingProduct: { endpoint: '/rest/naver_shopping_product', timeoutMs: 110_000, output: 'json' },
52
+ linkedinProfile: { endpoint: '/rest/linkedin_profile', timeoutMs: 110_000, output: 'json' },
53
+ linkedinCompany: { endpoint: '/rest/linkedin_company', timeoutMs: 110_000, output: 'json' },
54
+ linkedinJob: { endpoint: '/rest/linkedin_job', timeoutMs: 110_000, output: 'json' },
50
55
  getScrapeJob: { endpoint: '/rest/scrape_jobs', timeoutMs: 35_000, output: 'json' },
51
56
  screenshot: { endpoint: '/rest/url_screenshot', timeoutMs: 75_000, output: 'binary', filename: 'screenshot.jpeg' },
52
57
  youtubeMetadata: { endpoint: '/rest/youtube_metadata', timeoutMs: 60_000, output: 'json' },
@@ -106,6 +111,22 @@ function amazonInput(value) {
106
111
  return /^https?:\/\//i.test(text) ? { url: text } : { asin: text.toUpperCase() };
107
112
  }
108
113
 
114
+ // 쿠팡 상품 입력: 주소면 url, 상품 번호면 product_id 로 보낸다.
115
+ function coupangInput(value) {
116
+ const text = requiredString('urlOrProductId', value, 2048);
117
+ return /^https?:\/\//i.test(text) ? { url: text } : { product_id: text };
118
+ }
119
+
120
+ // 네이버 브랜드스토어 상품 입력: 상품 주소만 받는다.
121
+ function naverInput(value) {
122
+ return { url: requiredString('url', value, 2048) };
123
+ }
124
+
125
+ // LinkedIn 입력: 프로필(/in/), 회사(/company/), 채용공고(/jobs/view/) 주소.
126
+ function linkedinInput(value) {
127
+ return { url: requiredString('url', value, 2048) };
128
+ }
129
+
109
130
  const SCRAPE_JOB_PRODUCTS = Object.freeze({ instagram_posts: 100, instagram_comments: 15, tiktok_search: 50, tiktok_video: 1, tiktok_comments: 100, amazon_reviews: 100, google_maps_place: 1 });
110
131
 
111
132
  // 수집 작업 공통 옵션: maxResults(상품별 상한), idempotencyKey(응답을 못 받아 다시 보낼 때 같은 접수로 처리).
@@ -674,6 +695,31 @@ class ApickClient {
674
695
  return this._call('xPost', { url: requiredString('url', url, 2048) });
675
696
  }
676
697
 
698
+ // 상품 주소(/vp/products/{번호}) 또는 상품 번호. 처리에 보통 25~40초가 걸린다.
699
+ coupangProduct(urlOrProductId) {
700
+ return this._call('coupangProduct', coupangInput(urlOrProductId));
701
+ }
702
+
703
+ // 네이버 브랜드스토어 상품 주소(/{스토어}/products/{번호}). 스마트스토어 직링크는 받지 않는다.
704
+ naverShoppingProduct(url) {
705
+ return this._call('naverShoppingProduct', naverInput(url));
706
+ }
707
+
708
+ // LinkedIn 프로필 주소(/in/{아이디}). 처리에 보통 20초 안팎이 걸린다.
709
+ linkedinProfile(url) {
710
+ return this._call('linkedinProfile', linkedinInput(url));
711
+ }
712
+
713
+ // LinkedIn 회사 주소(/company/{아이디}).
714
+ linkedinCompany(url) {
715
+ return this._call('linkedinCompany', linkedinInput(url));
716
+ }
717
+
718
+ // LinkedIn 채용공고 주소(/jobs/view/{번호}).
719
+ linkedinJob(url) {
720
+ return this._call('linkedinJob', linkedinInput(url));
721
+ }
722
+
677
723
  // 수집 작업: 접수 즉시 job_id 를 돌려준다. maxResults × 단가를 예약하고 결과를 받을 때 실제 건수만 차감한다.
678
724
  _createScrapeJob(product, payload, options) {
679
725
  return this._call('getScrapeJob', scrapeJobOptions(product, payload, options), null, { endpoint: '/rest/' + product + '/jobs', json: true });
package/src/index.d.ts CHANGED
@@ -153,6 +153,122 @@ export interface XPost {
153
153
  readonly author: { readonly followers: number | null; readonly is_verified: boolean };
154
154
  }
155
155
 
156
+ export interface CoupangProduct {
157
+ readonly product_id: string;
158
+ readonly url: string;
159
+ readonly title: string;
160
+ readonly rating: number | null;
161
+ readonly reviews: number | null;
162
+ readonly initial_price: string;
163
+ readonly final_price: string;
164
+ readonly discount_rate: number | null;
165
+ readonly currency: string;
166
+ readonly seller_name: string;
167
+ readonly shop_url: string;
168
+ readonly seller_rating: number | null;
169
+ readonly seller_reviews: number | null;
170
+ readonly images: readonly string[];
171
+ readonly main_image: string;
172
+ readonly categories: readonly { readonly name: string; readonly url: string }[];
173
+ readonly root_category: string;
174
+ readonly root_category_url: string;
175
+ readonly shipping_details: readonly string[];
176
+ readonly variations: readonly { readonly name: string; readonly variations: readonly string[] }[];
177
+ readonly is_in_stock: boolean;
178
+ }
179
+
180
+ /** 네이버 브랜드스토어 상품. 상품 주소는 `/{스토어}/products/{번호}` 형식만 받는다. */
181
+ export interface NaverShoppingProduct {
182
+ readonly product_id: string;
183
+ readonly url: string;
184
+ readonly title: string;
185
+ readonly original_price: string;
186
+ readonly final_price: number | null;
187
+ readonly discount_rate: number | null;
188
+ readonly currency: string;
189
+ readonly description: string;
190
+ readonly total_reviews: number | null;
191
+ readonly average_rating: number | null;
192
+ readonly sold_out: boolean;
193
+ readonly delivery_fee_type: string;
194
+ readonly arrival_guarantee: boolean;
195
+ readonly category_name: string;
196
+ readonly tags: readonly string[];
197
+ readonly breadcrumbs: readonly string[];
198
+ readonly images: readonly string[];
199
+ readonly sellers: readonly { readonly seller_name: string; readonly final_price: number | null; readonly currency: string; readonly seller_link: string }[];
200
+ readonly product_information: readonly { readonly label: string; readonly value: string }[];
201
+ }
202
+
203
+ export interface LinkedinProfile {
204
+ readonly linkedin_id: string;
205
+ readonly name: string;
206
+ readonly first_name: string;
207
+ readonly last_name: string;
208
+ readonly position: string;
209
+ readonly about: string;
210
+ readonly location: string;
211
+ readonly country_code: string;
212
+ readonly followers: number | null;
213
+ readonly connections: number | null;
214
+ readonly current_company_name: string;
215
+ readonly avatar: string;
216
+ readonly banner_image: string;
217
+ readonly url: string;
218
+ readonly is_influencer: boolean;
219
+ readonly experience: readonly { readonly company: string; readonly title: string; readonly start: string; readonly end: string; readonly location: string }[];
220
+ readonly education: readonly { readonly school: string; readonly degree: string; readonly start: string; readonly end: string }[];
221
+ readonly certifications: readonly string[];
222
+ readonly languages: readonly string[];
223
+ readonly posts: readonly { readonly title: string; readonly link: string; readonly created_at: string; readonly interaction: string }[];
224
+ }
225
+
226
+ export interface LinkedinCompany {
227
+ readonly company_id: string;
228
+ readonly name: string;
229
+ readonly about: string;
230
+ readonly description: string;
231
+ readonly slogan: string;
232
+ readonly website: string;
233
+ readonly industries: string;
234
+ readonly company_size: string;
235
+ readonly organization_type: string;
236
+ readonly founded: number | null;
237
+ readonly followers: number | null;
238
+ readonly employees_on_linkedin: number | null;
239
+ readonly headquarters: string;
240
+ readonly locations: readonly string[];
241
+ readonly specialties: string;
242
+ readonly logo: string;
243
+ readonly image: string;
244
+ readonly url: string;
245
+ readonly funding: Readonly<Record<string, unknown>> | null;
246
+ readonly updates: readonly { readonly title: string; readonly link: string; readonly date: string; readonly text: string }[];
247
+ }
248
+
249
+ export interface LinkedinJob {
250
+ readonly job_posting_id: string;
251
+ readonly title: string;
252
+ readonly company_name: string;
253
+ readonly company_id: string;
254
+ readonly company_url: string;
255
+ readonly company_logo: string;
256
+ readonly location: string;
257
+ readonly employment_type: string;
258
+ readonly seniority_level: string;
259
+ readonly industries: string;
260
+ readonly summary: string;
261
+ readonly description_html: string;
262
+ readonly posted_time: string;
263
+ readonly posted_date: string;
264
+ readonly applicants: number | null;
265
+ readonly apply_link: string;
266
+ readonly is_easy_apply: boolean;
267
+ readonly base_salary: Readonly<Record<string, unknown>> | null;
268
+ readonly salary_standards: string;
269
+ readonly url: string;
270
+ }
271
+
156
272
  export interface TiktokVideo {
157
273
  readonly video_id: string;
158
274
  readonly url: string;
@@ -633,6 +749,11 @@ export class ApickClient {
633
749
  amazonProduct(urlOrAsin: string): Promise<ApickResult<AmazonProduct>>;
634
750
  xProfile(usernameOrUrl: string): Promise<ApickResult<XProfile>>;
635
751
  xPost(url: string): Promise<ApickResult<XPost>>;
752
+ coupangProduct(urlOrProductId: string): Promise<ApickResult<CoupangProduct>>;
753
+ naverShoppingProduct(url: string): Promise<ApickResult<NaverShoppingProduct>>;
754
+ linkedinProfile(url: string): Promise<ApickResult<LinkedinProfile>>;
755
+ linkedinCompany(url: string): Promise<ApickResult<LinkedinCompany>>;
756
+ linkedinJob(url: string): Promise<ApickResult<LinkedinJob>>;
636
757
  createInstagramPostsJob(usernameOrUrl: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<InstagramPost>>>;
637
758
  createInstagramCommentsJob(url: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<SocialComment>>>;
638
759
  createTiktokSearchJob(keyword: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<TiktokVideo>>>;