universal-parcel-scraper 0.3.0-main.298 → 0.3.0-main.302
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
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="docs/assets/
|
|
3
|
+
<img src="docs/assets/pip.svg" width="112" alt="Pip, a kraft parcel with a face">
|
|
4
4
|
|
|
5
5
|
# Universal Parcel Scraper
|
|
6
6
|
|
|
7
7
|
**Parcel tracking that asks the carrier directly, from your own machine.**
|
|
8
8
|
|
|
9
|
+
The engine behind [Peek](https://github.com/plhery/delivery-tracker), the open-source parcel tracker for iPhone and the web.
|
|
10
|
+
|
|
9
11
|
[](https://www.npmjs.com/package/universal-parcel-scraper)
|
|
10
12
|
[](https://github.com/plhery/universal-parcel-scraper/actions/workflows/ci.yml)
|
|
11
13
|
[](LICENSE)
|
|
12
14
|
|
|
13
15
|
<!-- GENERATED:summary -->
|
|
14
|
-
**
|
|
16
|
+
**3,500+ carriers** through **85 dedicated adapters** and **5 universal fallbacks**
|
|
17
|
+
|
|
18
|
+
<sub>105 carriers in the catalog · 58 countries represented</sub>
|
|
15
19
|
<!-- /GENERATED:summary -->
|
|
16
20
|
|
|
17
21
|
[Try it](#try-it) · [Ways to run it](#ways-to-run-it) · [Coverage](#how-much-can-it-track) · [Carriers](carriers/) · [Add a carrier](CONTRIBUTING.md)
|
|
18
22
|
|
|
19
|
-
<img src="docs/assets/
|
|
23
|
+
<img src="docs/assets/terminal.svg" width="840" alt="A terminal session: the detect command names UPS as the carrier of a tracking number, then the track command prints a parcel's scans with their stages">
|
|
20
24
|
|
|
21
25
|
</div>
|
|
22
26
|
|
|
@@ -24,10 +28,15 @@ Give it a tracking number. It works out which carrier the number belongs to and
|
|
|
24
28
|
history from that carrier's own website. What comes back has one shape, so a UPS parcel and
|
|
25
29
|
a Poczta Polska parcel look the same to your code.
|
|
26
30
|
|
|
27
|
-
There is no account to open and no API key.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
There is no account to open and no API key. The carriers it knows best each have a dedicated
|
|
32
|
+
adapter in [their own folder](carriers/), with a README on how that site is read. For the
|
|
33
|
+
rest it can ask the universal trackers such as 17TRACK and Ship24, which is where the big
|
|
34
|
+
number above comes from. Those stay off until you switch them on, and each one you enable
|
|
35
|
+
sees the numbers you send it.
|
|
36
|
+
|
|
37
|
+
It started as the tracking engine inside [Peek](https://github.com/plhery/delivery-tracker)
|
|
38
|
+
and was pulled out so it can be used on its own. It runs as a command-line tool and as a Node
|
|
39
|
+
library, and it can serve the same lookups over HTTP.
|
|
31
40
|
|
|
32
41
|
## Try it
|
|
33
42
|
|
|
@@ -138,8 +147,8 @@ The image runs `serve` and ships Chromium, for the carriers that only answer a r
|
|
|
138
147
|
|
|
139
148
|
## What you can build with it
|
|
140
149
|
|
|
141
|
-
- **A tracking
|
|
142
|
-
an
|
|
150
|
+
- **A parcel-tracking app.** [Peek](https://github.com/plhery/delivery-tracker) is the
|
|
151
|
+
full-size example: an iPhone and web app built on this package.
|
|
143
152
|
- **A Home Assistant sensor** for the parcel you are waiting on.
|
|
144
153
|
[The config is in examples](examples/home-assistant.yaml).
|
|
145
154
|
- **Order status inside a shop or help desk**, so customers are not sent off to the carrier's
|
|
@@ -156,7 +165,7 @@ are yours to do.
|
|
|
156
165
|
|
|
157
166
|
<picture>
|
|
158
167
|
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/how-it-works-dark.svg">
|
|
159
|
-
<img src="docs/assets/how-it-works-light.svg" width="840" alt="An input is detected offline and
|
|
168
|
+
<img src="docs/assets/how-it-works-light.svg" width="840" alt="An input is detected offline and fetched by the carrier's dedicated adapter, or by a fallback you enabled when that finds no history. Each scan's wording is filed under a stage, and the result is one timeline.">
|
|
160
169
|
</picture>
|
|
161
170
|
|
|
162
171
|
Each adapter uses plain HTTP wherever the carrier's site allows it. Some sites only answer a
|
|
@@ -181,14 +190,35 @@ one you enable receives the tracking number:
|
|
|
181
190
|
createTracker({ providers: ['ParcelsApp', 'Ship24', '17TRACK', 'Postal Ninja', 'UPU'] });
|
|
182
191
|
```
|
|
183
192
|
|
|
193
|
+
### One stage list
|
|
194
|
+
|
|
195
|
+
Carriers describe the same moment in their own words, or with a bare code. Each carrier
|
|
196
|
+
folder keeps a `statuses.json` with the codes and wordings seen from that carrier and the
|
|
197
|
+
stage each one means. Every entry also says how it was confirmed, by a live reply or the
|
|
198
|
+
carrier's own documentation for instance.
|
|
199
|
+
|
|
200
|
+
<!-- GENERATED:stages -->
|
|
201
|
+
<picture>
|
|
202
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/stages-dark.svg">
|
|
203
|
+
<img src="docs/assets/stages-light.svg" alt="DHL: Die Sendung wurde in das Zustellfahrzeug geladen.; Mondial Relay: En cours de livraison; Correios Brazil: Objeto saiu para entrega ao destinatário; Correos Express: EN REPARTO; Yamato Transport: 配達中; La Poste / Colissimo: DISTOU. All are filed under out_for_delivery." width="760">
|
|
204
|
+
</picture>
|
|
205
|
+
|
|
206
|
+
The folders hold 1,671 recorded statuses from 88 carriers.
|
|
207
|
+
<!-- /GENERATED:stages -->
|
|
208
|
+
|
|
209
|
+
A scan nobody has recorded yet goes through a shared classifier that reads English, French,
|
|
210
|
+
German, Italian, Spanish, Portuguese and Polish. Each scan in the result carries a
|
|
211
|
+
`stage_source` saying which of the two decided.
|
|
212
|
+
|
|
184
213
|
[ARCHITECTURE.md](ARCHITECTURE.md) has the rest.
|
|
185
214
|
|
|
186
215
|
## How much can it track?
|
|
187
216
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
217
|
+
The number at the top of this page is reach: with the fallbacks on, a lookup can go to the
|
|
218
|
+
largest aggregator, and [reach.json](docs/reach.json) records how many carriers each one
|
|
219
|
+
says it follows. Whether a real parcel comes back with its history is a different question,
|
|
220
|
+
so each source was run on its own against the same **100-carrier reference set**. The top
|
|
221
|
+
bar counts a carrier when any source below it returned a history.
|
|
192
222
|
|
|
193
223
|
<!-- GENERATED:coverage -->
|
|
194
224
|
<picture>
|
|
@@ -225,15 +255,15 @@ or a promise about today, because parcels expire and carrier sites change.
|
|
|
225
255
|
| Account | None | Sign-up and an API key |
|
|
226
256
|
| Cost | Your own compute | A plan or a per-shipment price |
|
|
227
257
|
| Who sees the tracking number | The carrier, plus any fallback you enable | The vendor, then the carrier |
|
|
228
|
-
| Carriers |
|
|
258
|
+
| Carriers | Dedicated adapters for the [catalog](carriers/), fallbacks for the rest | One large catalog |
|
|
229
259
|
| Updates | You poll | Webhooks |
|
|
230
260
|
| When a carrier changes its site | The adapter breaks until it is fixed here | The vendor deals with it |
|
|
231
261
|
| Hosting | Yours | Theirs |
|
|
232
262
|
|
|
233
|
-
If you want
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
263
|
+
If you want webhooks and nothing to run, a hosted API is the better choice. This project is
|
|
264
|
+
for when the numbers should stay on your side, or when a price per parcel makes no sense for
|
|
265
|
+
what you are building. Vendor catalog totals are not comparable with the reference test
|
|
266
|
+
above.
|
|
237
267
|
|
|
238
268
|
## Privacy and limits
|
|
239
269
|
|
|
@@ -172,7 +172,7 @@ export const adapter = (environment) => {
|
|
|
172
172
|
executablePath: environment.browserExecutablePath ?? undefined, recorder: environment.recorder,
|
|
173
173
|
});
|
|
174
174
|
return {
|
|
175
|
-
id: 'dhl-ecommerce',
|
|
175
|
+
id: 'dhl-ecommerce', recordsSteps: true,
|
|
176
176
|
steps: ['browser'],
|
|
177
177
|
track: (input, context) => tracker.fetch(input.number, context),
|
|
178
178
|
};
|
|
@@ -303,7 +303,7 @@ export const adapter = (environment) => {
|
|
|
303
303
|
recorder: environment.recorder,
|
|
304
304
|
});
|
|
305
305
|
return {
|
|
306
|
-
id: 'fedex',
|
|
306
|
+
id: 'fedex', recordsSteps: true,
|
|
307
307
|
// Browser-backed direct tracking; universal recovery belongs to the caller.
|
|
308
308
|
steps: ['trawl'],
|
|
309
309
|
track: (input, context) => tracker.fetch(input.number, context),
|
|
@@ -353,7 +353,7 @@ export const adapter = (environment) => {
|
|
|
353
353
|
recorder: environment.recorder,
|
|
354
354
|
});
|
|
355
355
|
return {
|
|
356
|
-
id: 'mondial-relay',
|
|
356
|
+
id: 'mondial-relay', recordsSteps: true,
|
|
357
357
|
// Cloudflare refuses every non-browser client, so there is no direct tier.
|
|
358
358
|
steps: ['trawl'],
|
|
359
359
|
track: (input, context) => tracker.fetch(input.number, input.postcode ?? '', context),
|
|
@@ -256,7 +256,7 @@ export const adapter = (environment) => {
|
|
|
256
256
|
recorder: environment.recorder,
|
|
257
257
|
});
|
|
258
258
|
return {
|
|
259
|
-
id: 'royal-mail',
|
|
259
|
+
id: 'royal-mail', recordsSteps: true,
|
|
260
260
|
// Akamai refuses every non-browser client, so there is no direct tier.
|
|
261
261
|
steps: ['trawl'],
|
|
262
262
|
track: (input, context) => tracker.fetch(input.number, context),
|
|
@@ -257,7 +257,7 @@ export const adapter = (environment) => {
|
|
|
257
257
|
recorder: environment.recorder,
|
|
258
258
|
});
|
|
259
259
|
return {
|
|
260
|
-
id: 'usps',
|
|
260
|
+
id: 'usps', recordsSteps: true,
|
|
261
261
|
// Akamai refuses every non-browser client, so there is no direct tier.
|
|
262
262
|
steps: ['trawl'],
|
|
263
263
|
track: (input, context) => tracker.fetch(input.number, context),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-parcel-scraper",
|
|
3
|
-
"version": "0.3.0-main.
|
|
3
|
+
"version": "0.3.0-main.302",
|
|
4
4
|
"description": "Self-hosted parcel tracking: carrier detection, dedicated scrapers and optional universal providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|