@microlink/google 0.0.0 → 0.1.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/README.md +192 -75
- package/package.json +9 -4
- package/src/index.d.ts +308 -0
- package/src/index.js +42 -23
- package/src/main.mjs +7 -0
package/README.md
CHANGED
|
@@ -4,7 +4,30 @@
|
|
|
4
4
|
[](https://coveralls.io/github/microlinkhq/microlink-google)
|
|
5
5
|
[](https://www.npmjs.org/package/@microlink/google)
|
|
6
6
|
|
|
7
|
-
> Google
|
|
7
|
+
> Turn Google into a structured API.
|
|
8
|
+
> Query Search, News, Images, Videos, Places, Maps, Shopping, Scholar, Patents, and Autocomplete — and get normalized data ready for code.
|
|
9
|
+
|
|
10
|
+
## Highlights
|
|
11
|
+
|
|
12
|
+
- **10 Google verticals in one API**
|
|
13
|
+
Search, News, Images, Videos, Places, Maps, Shopping, Scholar, Patents, and Autocomplete.
|
|
14
|
+
|
|
15
|
+
- **Normalized data**
|
|
16
|
+
Dates → ISO 8601
|
|
17
|
+
Prices → `{ symbol, amount }`
|
|
18
|
+
Ratings → `{ score, total, reviews }`
|
|
19
|
+
|
|
20
|
+
- **Lazy HTML fetching**
|
|
21
|
+
Any result with a `url` exposes `.html()` to fetch the page HTML on demand.
|
|
22
|
+
|
|
23
|
+
- **Built-in pagination**
|
|
24
|
+
Just call `.next()` to fetch the next page.
|
|
25
|
+
|
|
26
|
+
- **Fast**
|
|
27
|
+
~1 second response time per request with full parallelization support.
|
|
28
|
+
|
|
29
|
+
- **Full TypeScript support**
|
|
30
|
+
Type-specific inference out of the box.
|
|
8
31
|
|
|
9
32
|
## Install
|
|
10
33
|
|
|
@@ -12,152 +35,246 @@
|
|
|
12
35
|
npm install @microlink/google
|
|
13
36
|
```
|
|
14
37
|
|
|
15
|
-
##
|
|
38
|
+
## Quick start
|
|
16
39
|
|
|
17
|
-
|
|
40
|
+
### Your first query
|
|
41
|
+
|
|
42
|
+
Initialize `@microlink/google`. The only prerequisite is a [Microlink API key](https://microlink.io/#pricing):
|
|
18
43
|
|
|
19
44
|
```js
|
|
20
45
|
const google = require('@microlink/google')({
|
|
21
|
-
apiKey:
|
|
46
|
+
apiKey: process.env.MICROLINK_API_KEY
|
|
22
47
|
})
|
|
48
|
+
```
|
|
23
49
|
|
|
50
|
+
Make your first query:
|
|
51
|
+
|
|
52
|
+
```js
|
|
24
53
|
const page = await google('Lotus Elise S2')
|
|
25
54
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
55
|
+
console.log(page.results)
|
|
56
|
+
// [
|
|
57
|
+
// {
|
|
58
|
+
// title: 'Lotus Elise - Wikipedia',
|
|
59
|
+
// url: 'https://en.wikipedia.org/wiki/Lotus_Elise',
|
|
60
|
+
// description: 'The Lotus Elise is a two-seat, rear-wheel-drive...'
|
|
61
|
+
// }
|
|
62
|
+
// ]
|
|
31
63
|
```
|
|
32
64
|
|
|
33
|
-
|
|
65
|
+
Use [Google search operators](https://ahrefs.com/blog/google-advanced-search-operators/) to refine queries:
|
|
34
66
|
|
|
35
67
|
```js
|
|
36
|
-
const
|
|
68
|
+
const page = await google('Lotus Elise S2 filetype:pdf')
|
|
37
69
|
```
|
|
38
70
|
|
|
39
|
-
|
|
71
|
+
Localize results using `location` or filter by time with `period`:
|
|
40
72
|
|
|
41
73
|
```js
|
|
42
|
-
|
|
74
|
+
await google('recetas de pasta', {
|
|
75
|
+
location: 'es',
|
|
76
|
+
period: 'week'
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Get HTML markup
|
|
81
|
+
|
|
82
|
+
Any result containing a `url` exposes a lazy `.html()` method:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const { results } = await google('node.js frameworks')
|
|
86
|
+
|
|
87
|
+
for (const result of results) {
|
|
88
|
+
const html = await result.html()
|
|
89
|
+
console.log(html)
|
|
90
|
+
}
|
|
43
91
|
```
|
|
44
92
|
|
|
45
93
|
### Pagination
|
|
46
94
|
|
|
47
|
-
|
|
95
|
+
Pages chain naturally:
|
|
48
96
|
|
|
49
97
|
```js
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
98
|
+
const page1 = await google('node.js frameworks')
|
|
99
|
+
const page2 = await page1.next()
|
|
100
|
+
const page3 = await page2.next()
|
|
53
101
|
```
|
|
54
102
|
|
|
55
|
-
|
|
103
|
+
You can also iterate:
|
|
56
104
|
|
|
57
|
-
|
|
105
|
+
```js
|
|
106
|
+
let page = await google('node.js frameworks')
|
|
58
107
|
|
|
59
|
-
|
|
108
|
+
while (page) {
|
|
109
|
+
for (const result of page.results) {
|
|
110
|
+
console.log(result.title)
|
|
111
|
+
}
|
|
60
112
|
|
|
61
|
-
|
|
113
|
+
page = await page.next()
|
|
114
|
+
}
|
|
115
|
+
```
|
|
62
116
|
|
|
63
|
-
|
|
64
|
-
|
|
117
|
+
# Google products
|
|
118
|
+
|
|
119
|
+
| Type | Product | Example |
|
|
120
|
+
| -------------- | ------------------- | ----------------------------------------------------------- |
|
|
121
|
+
| `search` | Google Search | `google('Lotus Elise S2')` |
|
|
122
|
+
| `news` | Google News | `google('artificial intelligence', { type: 'news' })` |
|
|
123
|
+
| `images` | Google Images | `google('northern lights', { type: 'images' })` |
|
|
124
|
+
| `videos` | Google Videos | `google('cooking tutorial', { type: 'videos' })` |
|
|
125
|
+
| `places` | Google Places | `google('coffee shops denver', { type: 'places' })` |
|
|
126
|
+
| `maps` | Google Maps | `google('apple store new york', { type: 'maps' })` |
|
|
127
|
+
| `shopping` | Google Shopping | `google('macbook pro', { type: 'shopping' })` |
|
|
128
|
+
| `scholar` | Google Scholar | `google('transformer architecture', { type: 'scholar' })` |
|
|
129
|
+
| `patents` | Google Patents | `google('touchscreen gestures apple', { type: 'patents' })` |
|
|
130
|
+
| `autocomplete` | Google Autocomplete | `google('how to', { type: 'autocomplete' })` |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Google Search
|
|
65
135
|
|
|
66
|
-
|
|
136
|
+
Web results with knowledge graph, related questions, and related searches.
|
|
67
137
|
|
|
68
138
|
```js
|
|
69
|
-
|
|
70
|
-
|
|
139
|
+
const page = await google('Lotus Elise S2')
|
|
140
|
+
|
|
141
|
+
page.results[0]
|
|
71
142
|
|
|
72
|
-
|
|
73
|
-
|
|
143
|
+
page.knowledgeGraph
|
|
144
|
+
page.peopleAlsoAsk
|
|
145
|
+
page.relatedSearches
|
|
146
|
+
```
|
|
74
147
|
|
|
75
|
-
|
|
76
|
-
const page = await google('node.js tutorials -site:w3schools.com')
|
|
148
|
+
## Google News
|
|
77
149
|
|
|
78
|
-
|
|
79
|
-
const page = await google('"machine learning" site:arxiv.org')
|
|
150
|
+
Recent articles with publisher, date, and thumbnail.
|
|
80
151
|
|
|
81
|
-
|
|
82
|
-
const page = await google('
|
|
152
|
+
```js
|
|
153
|
+
const page = await google('artificial intelligence', { type: 'news' })
|
|
83
154
|
```
|
|
84
155
|
|
|
85
|
-
|
|
156
|
+
## Google Images
|
|
86
157
|
|
|
87
|
-
|
|
158
|
+
Full-resolution image URLs with dimensions.
|
|
88
159
|
|
|
89
|
-
|
|
160
|
+
```js
|
|
161
|
+
const page = await google('northern lights', { type: 'images' })
|
|
162
|
+
```
|
|
90
163
|
|
|
91
|
-
|
|
164
|
+
## Google Videos
|
|
92
165
|
|
|
93
|
-
|
|
166
|
+
Video metadata with duration in milliseconds.
|
|
94
167
|
|
|
95
|
-
|
|
168
|
+
```js
|
|
169
|
+
const page = await google('cooking tutorial', { type: 'videos' })
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Google Places
|
|
96
173
|
|
|
97
|
-
|
|
174
|
+
Local business listings with coordinates and contact info.
|
|
98
175
|
|
|
99
176
|
```js
|
|
100
|
-
const page = await google('
|
|
177
|
+
const page = await google('coffee shops denver', { type: 'places' })
|
|
101
178
|
```
|
|
102
179
|
|
|
103
|
-
|
|
180
|
+
## Google Maps
|
|
104
181
|
|
|
105
|
-
|
|
106
|
-
Values: `'desktop'`, `'mobile'`
|
|
107
|
-
Default: `'desktop'`
|
|
182
|
+
Detailed place data with ratings, hours, and pricing.
|
|
108
183
|
|
|
109
|
-
|
|
184
|
+
```js
|
|
185
|
+
const page = await google('apple store new york', { type: 'maps' })
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Google Shopping
|
|
189
|
+
|
|
190
|
+
Product listings with parsed prices and structured ratings.
|
|
110
191
|
|
|
111
192
|
```js
|
|
112
|
-
const page = await google('
|
|
193
|
+
const page = await google('macbook pro', { type: 'shopping' })
|
|
113
194
|
```
|
|
114
195
|
|
|
115
|
-
|
|
196
|
+
## Google Scholar
|
|
116
197
|
|
|
117
|
-
|
|
118
|
-
|
|
198
|
+
Academic papers with citation counts and PDF links.
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
const page = await google('transformer architecture', { type: 'scholar' })
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Google Patents
|
|
119
205
|
|
|
120
|
-
|
|
206
|
+
Patent filings with ISO 8601 dates and metadata.
|
|
121
207
|
|
|
122
208
|
```js
|
|
123
|
-
const page = await google('
|
|
209
|
+
const page = await google('touchscreen gestures apple', { type: 'patents' })
|
|
124
210
|
```
|
|
125
211
|
|
|
126
|
-
|
|
212
|
+
## Google Autocomplete
|
|
213
|
+
|
|
214
|
+
Search suggestions as you type.
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
const page = await google('how to', { type: 'autocomplete' })
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
# API
|
|
221
|
+
|
|
222
|
+
## google(query, options?)
|
|
223
|
+
|
|
224
|
+
### query
|
|
225
|
+
|
|
226
|
+
**Required**
|
|
227
|
+
Type: `string`
|
|
228
|
+
|
|
229
|
+
The search query. Supports [Google search operators](https://support.google.com/websearch/answer/2466433).
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
await google('annual report filetype:pdf')
|
|
233
|
+
await google('security updates site:github.com')
|
|
234
|
+
await google('"machine learning" site:arxiv.org')
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### options
|
|
238
|
+
|
|
239
|
+
#### type
|
|
127
240
|
|
|
128
241
|
Type: `string`<br>
|
|
129
|
-
Default: `'
|
|
242
|
+
Default: `'search'`<br>
|
|
243
|
+
Values: `'search'` | `'news'` | `'images'` | `'videos'` | `'places'` | `'maps'` | `'shopping'` | `'scholar'` | `'patents'` | `'autocomplete'`
|
|
130
244
|
|
|
131
|
-
|
|
245
|
+
Selects which Google product to query.
|
|
132
246
|
|
|
133
247
|
```js
|
|
134
|
-
|
|
248
|
+
await google('artificial intelligence', { type: 'news' })
|
|
135
249
|
```
|
|
136
250
|
|
|
137
|
-
|
|
251
|
+
#### location
|
|
138
252
|
|
|
139
|
-
|
|
253
|
+
Type: `string`<br>
|
|
254
|
+
Default: `'us'`<br>
|
|
255
|
+
Values: [`Location`](https://github.com/microlinkhq/google/blob/master/src/index.d.ts#L28)
|
|
256
|
+
|
|
257
|
+
Controls result geolocation using a country code ([ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)). This influences ranking, language, and local intent.
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
await google('recetas de pasta', { location: 'es' })
|
|
261
|
+
```
|
|
140
262
|
|
|
141
|
-
|
|
142
|
-
|---|---|---|
|
|
143
|
-
| `results` | `Array<Result>` | Array of search results |
|
|
144
|
-
| `html()` | `() => Promise<string>` | Returns the raw SERP HTML |
|
|
145
|
-
| `next()` | `() => Promise<Page>` | Fetches the next page of results |
|
|
263
|
+
#### period
|
|
146
264
|
|
|
147
|
-
|
|
265
|
+
Type: `string`<br>
|
|
266
|
+
Default: `undefined`<br>
|
|
267
|
+
Values: `hour` | `day` | `week` | `month` | `year`
|
|
148
268
|
|
|
149
|
-
|
|
269
|
+
Limits results to a recent time window. Useful for news monitoring and freshness-sensitive queries.
|
|
150
270
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
| `url` | `string` | Direct URL to the page |
|
|
155
|
-
| `description` | `string` | Result snippet text |
|
|
156
|
-
| `html()` | `() => Promise<string>` | Fetches the full HTML of this result's URL via Microlink |
|
|
271
|
+
```js
|
|
272
|
+
await google('tech news', { period: 'week' })
|
|
273
|
+
```
|
|
157
274
|
|
|
158
275
|
## License
|
|
159
276
|
|
|
160
|
-
**@microlink/google** © [
|
|
161
|
-
Authored and maintained by [
|
|
277
|
+
**@microlink/google** © [Microlink](https://microlink.io), released under the [MIT](https://github.com/microlinkhq/google/blob/master/LICENSE.md) License.<br>
|
|
278
|
+
Authored and maintained by [Kiko Beats](https://kikobeats.com) with help from [contributors](https://github.com/microlinkhq/google/contributors).
|
|
162
279
|
|
|
163
|
-
> [microlink.io](https://microlink.io) · GitHub [
|
|
280
|
+
> [microlink.io](https://microlink.io) · GitHub [microlinkhq](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microlink/google",
|
|
3
|
-
"description": "Google
|
|
3
|
+
"description": "Structured Google data from 10 verticals through Microlink API",
|
|
4
4
|
"homepage": "https://github.com/microlinkhq/microlink-google",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.1.0",
|
|
6
6
|
"exports": {
|
|
7
|
-
"
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"require": "./src/index.js",
|
|
9
|
+
"import": "./src/main.mjs",
|
|
10
|
+
"default": "./src/main.mjs"
|
|
8
11
|
},
|
|
9
12
|
"author": {
|
|
10
13
|
"email": "hello@microlink.io",
|
|
@@ -42,7 +45,9 @@
|
|
|
42
45
|
"simple-git-hooks": "latest",
|
|
43
46
|
"standard": "latest",
|
|
44
47
|
"standard-markdown": "latest",
|
|
45
|
-
"standard-version": "latest"
|
|
48
|
+
"standard-version": "latest",
|
|
49
|
+
"proxyquire": "latest",
|
|
50
|
+
"tinyspawn": "latest"
|
|
46
51
|
},
|
|
47
52
|
"engines": {
|
|
48
53
|
"node": ">= 24"
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
type Period = 'hour' | 'day' | 'week' | 'month' | 'year'
|
|
2
|
+
|
|
3
|
+
type Type =
|
|
4
|
+
| 'search'
|
|
5
|
+
| 'news'
|
|
6
|
+
| 'images'
|
|
7
|
+
| 'videos'
|
|
8
|
+
| 'places'
|
|
9
|
+
| 'maps'
|
|
10
|
+
| 'shopping'
|
|
11
|
+
| 'scholar'
|
|
12
|
+
| 'patents'
|
|
13
|
+
| 'autocomplete'
|
|
14
|
+
|
|
15
|
+
interface TypeToPage {
|
|
16
|
+
search: SearchPage
|
|
17
|
+
news: NewsPage
|
|
18
|
+
images: ImagesPage
|
|
19
|
+
videos: VideosPage
|
|
20
|
+
places: PlacesPage
|
|
21
|
+
maps: MapsPage
|
|
22
|
+
shopping: ShoppingPage
|
|
23
|
+
scholar: ScholarPage
|
|
24
|
+
patents: PatentsPage
|
|
25
|
+
autocomplete: AutocompletePage
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Location =
|
|
29
|
+
| 'af' | 'al' | 'dz' | 'as' | 'ad' | 'ao' | 'ai' | 'aq' | 'ag' | 'ar'
|
|
30
|
+
| 'am' | 'aw' | 'au' | 'at' | 'az' | 'bs' | 'bh' | 'bd' | 'bb' | 'by'
|
|
31
|
+
| 'be' | 'bz' | 'bj' | 'bm' | 'bt' | 'bo' | 'ba' | 'bw' | 'bv' | 'br'
|
|
32
|
+
| 'io' | 'bn' | 'bg' | 'bf' | 'bi' | 'kh' | 'cm' | 'ca' | 'cv' | 'ky'
|
|
33
|
+
| 'cf' | 'td' | 'cl' | 'cn' | 'cx' | 'cc' | 'co' | 'km' | 'cg' | 'cd'
|
|
34
|
+
| 'ck' | 'cr' | 'ci' | 'hr' | 'cu' | 'cy' | 'cz' | 'dk' | 'dj' | 'dm'
|
|
35
|
+
| 'do' | 'ec' | 'eg' | 'sv' | 'gq' | 'er' | 'ee' | 'et' | 'fk' | 'fo'
|
|
36
|
+
| 'fj' | 'fi' | 'fr' | 'gf' | 'pf' | 'tf' | 'ga' | 'gm' | 'ge' | 'de'
|
|
37
|
+
| 'gh' | 'gi' | 'gr' | 'gl' | 'gd' | 'gp' | 'gu' | 'gt' | 'gn' | 'gw'
|
|
38
|
+
| 'gy' | 'ht' | 'hm' | 'va' | 'hn' | 'hk' | 'hu' | 'is' | 'in' | 'id'
|
|
39
|
+
| 'ir' | 'iq' | 'ie' | 'il' | 'it' | 'jm' | 'jp' | 'jo' | 'kz' | 'ke'
|
|
40
|
+
| 'ki' | 'kp' | 'kr' | 'kw' | 'kg' | 'la' | 'lv' | 'lb' | 'ls' | 'lr'
|
|
41
|
+
| 'ly' | 'li' | 'lt' | 'lu' | 'mo' | 'mk' | 'mg' | 'mw' | 'my' | 'mv'
|
|
42
|
+
| 'ml' | 'mt' | 'mh' | 'mq' | 'mr' | 'mu' | 'yt' | 'mx' | 'fm' | 'md'
|
|
43
|
+
| 'mc' | 'mn' | 'ms' | 'ma' | 'mz' | 'mm' | 'na' | 'nr' | 'np' | 'nl'
|
|
44
|
+
| 'an' | 'nc' | 'nz' | 'ni' | 'ne' | 'ng' | 'nu' | 'nf' | 'mp' | 'no'
|
|
45
|
+
| 'om' | 'pk' | 'pw' | 'ps' | 'pa' | 'pg' | 'py' | 'pe' | 'ph' | 'pn'
|
|
46
|
+
| 'pl' | 'pt' | 'pr' | 'qa' | 're' | 'ro' | 'ru' | 'rw' | 'sh' | 'kn'
|
|
47
|
+
| 'lc' | 'pm' | 'vc' | 'ws' | 'sm' | 'st' | 'sa' | 'sn' | 'rs' | 'sc'
|
|
48
|
+
| 'sl' | 'sg' | 'sk' | 'si' | 'sb' | 'so' | 'za' | 'gs' | 'es' | 'lk'
|
|
49
|
+
| 'sd' | 'sr' | 'sj' | 'sz' | 'se' | 'ch' | 'sy' | 'tw' | 'tj' | 'tz'
|
|
50
|
+
| 'th' | 'tl' | 'tg' | 'tk' | 'to' | 'tt' | 'tn' | 'tr' | 'tm' | 'tc'
|
|
51
|
+
| 'tv' | 'ug' | 'ua' | 'ae' | 'gb' | 'us' | 'um' | 'uy' | 'uz' | 'vu'
|
|
52
|
+
| 've' | 'vn' | 'vg' | 'vi' | 'wf' | 'eh' | 'ye' | 'zm' | 'zw'
|
|
53
|
+
|
|
54
|
+
interface Options {
|
|
55
|
+
type?: Type
|
|
56
|
+
limit?: number
|
|
57
|
+
location?: Location
|
|
58
|
+
period?: Period
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface Sitelink {
|
|
62
|
+
title: string
|
|
63
|
+
link: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface KnowledgeGraph {
|
|
67
|
+
title?: string
|
|
68
|
+
type?: string
|
|
69
|
+
website?: string
|
|
70
|
+
image?: { url: string }
|
|
71
|
+
description?: string
|
|
72
|
+
descriptionSource?: string
|
|
73
|
+
descriptionLink?: string
|
|
74
|
+
attributes?: Record<string, string>
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface PeopleAlsoAsk {
|
|
78
|
+
question: string
|
|
79
|
+
snippet: string
|
|
80
|
+
title: string
|
|
81
|
+
link: string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface RelatedSearch {
|
|
85
|
+
query: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface SearchResult {
|
|
89
|
+
title: string
|
|
90
|
+
url: string
|
|
91
|
+
description: string
|
|
92
|
+
html(): Promise<string>
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface SearchPage {
|
|
96
|
+
results: SearchResult[]
|
|
97
|
+
knowledgeGraph?: KnowledgeGraph
|
|
98
|
+
peopleAlsoAsk?: PeopleAlsoAsk[]
|
|
99
|
+
relatedSearches?: RelatedSearch[]
|
|
100
|
+
html(): Promise<string>
|
|
101
|
+
next(): Promise<SearchPage>
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface NewsResult {
|
|
105
|
+
title: string
|
|
106
|
+
url: string
|
|
107
|
+
description: string
|
|
108
|
+
date: string
|
|
109
|
+
publisher: string
|
|
110
|
+
image?: { url: string }
|
|
111
|
+
html(): Promise<string>
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface NewsPage {
|
|
115
|
+
results: NewsResult[]
|
|
116
|
+
html(): Promise<string>
|
|
117
|
+
next(): Promise<NewsPage>
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface ImageResult {
|
|
121
|
+
title: string
|
|
122
|
+
url: string
|
|
123
|
+
image: { url: string; width: number; height: number }
|
|
124
|
+
thumbnail: { url: string; width: number; height: number }
|
|
125
|
+
google?: { url: string }
|
|
126
|
+
creator?: string
|
|
127
|
+
credit?: string
|
|
128
|
+
html(): Promise<string>
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface ImagesPage {
|
|
132
|
+
results: ImageResult[]
|
|
133
|
+
html(): Promise<string>
|
|
134
|
+
next(): Promise<ImagesPage>
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface VideoResult {
|
|
138
|
+
title: string
|
|
139
|
+
url: string
|
|
140
|
+
description: string
|
|
141
|
+
image?: { url: string }
|
|
142
|
+
video?: { url: string }
|
|
143
|
+
duration?: number
|
|
144
|
+
duration_pretty?: string
|
|
145
|
+
publisher?: string
|
|
146
|
+
channel?: string
|
|
147
|
+
date?: string
|
|
148
|
+
html(): Promise<string>
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface VideosPage {
|
|
152
|
+
results: VideoResult[]
|
|
153
|
+
html(): Promise<string>
|
|
154
|
+
next(): Promise<VideosPage>
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface PlaceResult {
|
|
158
|
+
title: string
|
|
159
|
+
address: string
|
|
160
|
+
latitude: number
|
|
161
|
+
longitude: number
|
|
162
|
+
phone?: { number: string }
|
|
163
|
+
url?: string
|
|
164
|
+
cid: string
|
|
165
|
+
html(): Promise<string>
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface PlacesPage {
|
|
169
|
+
results: PlaceResult[]
|
|
170
|
+
html(): Promise<string>
|
|
171
|
+
next(): Promise<PlacesPage>
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface MapPlaceResult {
|
|
175
|
+
title: string
|
|
176
|
+
address: string
|
|
177
|
+
latitude: number
|
|
178
|
+
longitude: number
|
|
179
|
+
rating?: number
|
|
180
|
+
ratingCount?: number
|
|
181
|
+
price?: { level: string }
|
|
182
|
+
type?: string
|
|
183
|
+
types?: string[]
|
|
184
|
+
url?: string
|
|
185
|
+
phone?: { number: string }
|
|
186
|
+
description?: string
|
|
187
|
+
opening?: { hours: Record<string, string> }
|
|
188
|
+
thumbnail?: { url: string }
|
|
189
|
+
cid: string
|
|
190
|
+
fid?: string
|
|
191
|
+
place?: { id: string }
|
|
192
|
+
html(): Promise<string>
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
interface MapsPage {
|
|
196
|
+
results: MapPlaceResult[]
|
|
197
|
+
html(): Promise<string>
|
|
198
|
+
next(): Promise<MapsPage>
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
interface ShoppingResult {
|
|
202
|
+
title: string
|
|
203
|
+
url: string
|
|
204
|
+
publisher: string
|
|
205
|
+
price: { symbol: string; amount: number }
|
|
206
|
+
image?: { url: string }
|
|
207
|
+
rating?: { score: number; total: number; reviews?: number }
|
|
208
|
+
id?: string
|
|
209
|
+
html(): Promise<string>
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface ShoppingPage {
|
|
213
|
+
results: ShoppingResult[]
|
|
214
|
+
html(): Promise<string>
|
|
215
|
+
next(): Promise<ShoppingPage>
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
interface ScholarResult {
|
|
219
|
+
title: string
|
|
220
|
+
url: string
|
|
221
|
+
description: string
|
|
222
|
+
publisher: string
|
|
223
|
+
year: number
|
|
224
|
+
citations: number
|
|
225
|
+
pdf?: { url: string }
|
|
226
|
+
id: string
|
|
227
|
+
html(): Promise<string>
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface ScholarPage {
|
|
231
|
+
results: ScholarResult[]
|
|
232
|
+
html(): Promise<string>
|
|
233
|
+
next(): Promise<ScholarPage>
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
interface PatentResult {
|
|
237
|
+
title: string
|
|
238
|
+
description: string
|
|
239
|
+
url: string
|
|
240
|
+
priority: { date: string }
|
|
241
|
+
filing: { date: string }
|
|
242
|
+
grant?: { date: string }
|
|
243
|
+
publication: { date: string; number: string }
|
|
244
|
+
inventor: string
|
|
245
|
+
assignee: string
|
|
246
|
+
language: string
|
|
247
|
+
pdf?: { url: string }
|
|
248
|
+
thumbnail?: { url: string }
|
|
249
|
+
figures?: Array<{ image: { url: string }; thumbnail: { url: string } }>
|
|
250
|
+
id?: string
|
|
251
|
+
html(): Promise<string>
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
interface PatentsPage {
|
|
255
|
+
results: PatentResult[]
|
|
256
|
+
html(): Promise<string>
|
|
257
|
+
next(): Promise<PatentsPage>
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
interface SuggestionResult {
|
|
261
|
+
value: string
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
interface AutocompletePage {
|
|
265
|
+
results: SuggestionResult[]
|
|
266
|
+
html(): Promise<string>
|
|
267
|
+
next(): Promise<AutocompletePage>
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface GoogleClient {
|
|
271
|
+
<K extends Type>(
|
|
272
|
+
query: string,
|
|
273
|
+
options: Omit<Options, 'type'> & { type: K }
|
|
274
|
+
): Promise<TypeToPage[K]>
|
|
275
|
+
(query: string, options?: Options): Promise<SearchPage>
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
interface ContextOptions {
|
|
279
|
+
apiKey?: string
|
|
280
|
+
endpoint?: string
|
|
281
|
+
timeout?: number
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export declare const DOMAIN: string
|
|
285
|
+
|
|
286
|
+
export declare function buildPath(
|
|
287
|
+
query: string,
|
|
288
|
+
limit?: number,
|
|
289
|
+
location?: string
|
|
290
|
+
): string
|
|
291
|
+
|
|
292
|
+
export declare function buildUrl(
|
|
293
|
+
query: string,
|
|
294
|
+
options?: {
|
|
295
|
+
limit?: number
|
|
296
|
+
location?: string
|
|
297
|
+
type?: Type
|
|
298
|
+
period?: Period
|
|
299
|
+
}
|
|
300
|
+
): URL
|
|
301
|
+
|
|
302
|
+
interface createGoogleClient {
|
|
303
|
+
(options?: ContextOptions): GoogleClient
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
declare const createGoogleClient: createGoogleClient
|
|
307
|
+
|
|
308
|
+
export default createGoogleClient
|
package/src/index.js
CHANGED
|
@@ -4,51 +4,70 @@ const mql = require('@microlink/mql')
|
|
|
4
4
|
|
|
5
5
|
const DOMAIN = 'microlink.google'
|
|
6
6
|
|
|
7
|
-
const buildPath = (query, limit,
|
|
8
|
-
[encodeURIComponent(query).replace(/%20/g, '+'), limit,
|
|
7
|
+
const buildPath = (query, limit, location) =>
|
|
8
|
+
[encodeURIComponent(query).replace(/%20/g, '+'), limit, location]
|
|
9
9
|
.filter(v => v !== undefined)
|
|
10
10
|
.join('/')
|
|
11
11
|
|
|
12
|
-
const buildUrl = (query, { limit,
|
|
13
|
-
const url = new URL(`https://${DOMAIN}/${buildPath(query, limit,
|
|
14
|
-
if (
|
|
12
|
+
const buildUrl = (query, { limit, location, type, period } = {}) => {
|
|
13
|
+
const url = new URL(`https://${DOMAIN}/${buildPath(query, limit, location)}`)
|
|
14
|
+
if (type) url.searchParams.set('type', type)
|
|
15
15
|
if (period) url.searchParams.set('period', period)
|
|
16
|
-
if (domain) url.searchParams.set('domain', domain)
|
|
17
16
|
return url
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
const
|
|
19
|
+
const resultUrl = result => result.url
|
|
20
|
+
|
|
21
|
+
const fetchPage = async (url, mqlOpts, offset, query) => {
|
|
21
22
|
url.searchParams.set('start', String(offset))
|
|
22
23
|
const { data } = await mql(url.toString(), mqlOpts)
|
|
23
|
-
const { results,
|
|
24
|
+
const { results, ...extra } = data
|
|
24
25
|
|
|
25
26
|
return {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
...extra,
|
|
28
|
+
html: async () => {
|
|
29
|
+
const { data } = await mql(
|
|
30
|
+
`https://www.google.com/search?q=${encodeURIComponent(query)}`,
|
|
31
|
+
{
|
|
31
32
|
...mqlOpts,
|
|
32
33
|
data: { content: { attr: 'html' } }
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
return data.content
|
|
37
|
+
},
|
|
38
|
+
results: results.map(result => {
|
|
39
|
+
const url = resultUrl(result)
|
|
40
|
+
return {
|
|
41
|
+
...result,
|
|
42
|
+
...(url && {
|
|
43
|
+
html: async () => {
|
|
44
|
+
const { data } = await mql(url, {
|
|
45
|
+
...mqlOpts,
|
|
46
|
+
data: { content: { attr: 'html' } }
|
|
47
|
+
})
|
|
48
|
+
return data.content
|
|
49
|
+
}
|
|
33
50
|
})
|
|
34
|
-
return data.content
|
|
35
51
|
}
|
|
36
|
-
})
|
|
52
|
+
}),
|
|
37
53
|
next: () =>
|
|
38
|
-
fetchPage(
|
|
54
|
+
fetchPage(
|
|
55
|
+
new URL(url.toString()),
|
|
56
|
+
mqlOpts,
|
|
57
|
+
offset + results.length,
|
|
58
|
+
query
|
|
59
|
+
)
|
|
39
60
|
}
|
|
40
61
|
}
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
return async (
|
|
44
|
-
query,
|
|
45
|
-
|
|
46
|
-
) => {
|
|
47
|
-
const url = buildUrl(query, { limit, lang, device, period, domain })
|
|
48
|
-
return fetchPage(url, { ...ctxOpts, ...opts }, 0)
|
|
63
|
+
const createGoogleClient = ctxOpts => {
|
|
64
|
+
return async (query, { limit, location, type, period, ...opts } = {}) => {
|
|
65
|
+
const url = buildUrl(query, { limit, location, type, period })
|
|
66
|
+
return fetchPage(url, { ...ctxOpts, ...opts }, 0, query)
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
|
|
70
|
+
module.exports = createGoogleClient
|
|
52
71
|
module.exports.buildPath = buildPath
|
|
53
72
|
module.exports.buildUrl = buildUrl
|
|
54
73
|
module.exports.DOMAIN = DOMAIN
|
package/src/main.mjs
ADDED