universal-parcel-scraper 0.809.2-main.4367 → 0.810.1-main.4374
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 +1 -1
- package/data/catalog.json +6 -0
- package/data/detection-golden.json +13 -0
- package/dist/browser/scraper.js +9 -1
- package/dist/carriers/meso-global/statuses.json +3 -1
- package/dist/carriers/spring-gds/adapter.d.ts +1 -1
- package/dist/carriers/spring-gds/adapter.js +30 -0
- package/dist/carriers/spring-gds/carrier.json +9 -0
- package/dist/carriers/spring-gds/numbers.json +17 -0
- package/dist/carriers/techlink/statuses.json +2 -1
- package/dist/data/catalog.json +6 -0
- package/dist/generated/catalog.d.ts +5 -0
- package/dist/generated/catalog.js +7 -1
- package/dist/generated/recognition.js +1 -0
- package/dist/providers/shared/result.js +8 -3
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ the command line's `track --source ParcelsApp` does the same.
|
|
|
161
161
|
<!-- GENERATED:stages -->
|
|
162
162
|
<img src="docs/assets/stages.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">
|
|
163
163
|
|
|
164
|
-
The carrier folders record 17,
|
|
164
|
+
The carrier folders record 17,648 such statuses, each filed under one stage.
|
|
165
165
|
<!-- /GENERATED:stages -->
|
|
166
166
|
|
|
167
167
|
Wording nobody recorded yet goes through a classifier that reads seven European languages.
|
package/data/catalog.json
CHANGED
|
@@ -427,6 +427,8 @@
|
|
|
427
427
|
"autoComplete": "postal-code"
|
|
428
428
|
}
|
|
429
429
|
],
|
|
430
|
+
"recognitionRank": 524,
|
|
431
|
+
"recognitionPattern": "^1810\\d{14}$",
|
|
430
432
|
"refresh": {
|
|
431
433
|
"minMinutes": 30
|
|
432
434
|
},
|
|
@@ -476,6 +478,10 @@
|
|
|
476
478
|
{
|
|
477
479
|
"pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
|
|
478
480
|
"confidence": "low"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"pattern": "^1810\\d{14}$",
|
|
484
|
+
"confidence": "low"
|
|
479
485
|
}
|
|
480
486
|
]
|
|
481
487
|
},
|
|
@@ -20397,6 +20397,19 @@
|
|
|
20397
20397
|
"heppner"
|
|
20398
20398
|
]
|
|
20399
20399
|
},
|
|
20400
|
+
{
|
|
20401
|
+
"input": "181011000000000017",
|
|
20402
|
+
"carrier": "unknown",
|
|
20403
|
+
"confidence": "low",
|
|
20404
|
+
"candidates": [
|
|
20405
|
+
"spring-gds",
|
|
20406
|
+
"bpost",
|
|
20407
|
+
"ecoscooting"
|
|
20408
|
+
],
|
|
20409
|
+
"asked": [
|
|
20410
|
+
"spring-gds"
|
|
20411
|
+
]
|
|
20412
|
+
},
|
|
20400
20413
|
{
|
|
20401
20414
|
"input": "18113149",
|
|
20402
20415
|
"carrier": "unknown",
|
package/dist/browser/scraper.js
CHANGED
|
@@ -685,6 +685,8 @@ var tt = {
|
|
|
685
685
|
inputMode: "text",
|
|
686
686
|
autoComplete: "postal-code"
|
|
687
687
|
}],
|
|
688
|
+
recognitionRank: 524,
|
|
689
|
+
recognitionPattern: "^1810\\d{14}$",
|
|
688
690
|
refresh: { minMinutes: 30 },
|
|
689
691
|
localClocks: !0
|
|
690
692
|
},
|
|
@@ -722,6 +724,10 @@ var tt = {
|
|
|
722
724
|
{
|
|
723
725
|
pattern: "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
|
|
724
726
|
confidence: "low"
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
pattern: "^1810\\d{14}$",
|
|
730
|
+
confidence: "low"
|
|
725
731
|
}
|
|
726
732
|
]
|
|
727
733
|
},
|
|
@@ -26880,7 +26886,8 @@ var tt = {
|
|
|
26880
26886
|
"spring-gds": [
|
|
26881
26887
|
"spring-gds-1",
|
|
26882
26888
|
"spring-gds-2",
|
|
26883
|
-
"spring-gds-3"
|
|
26889
|
+
"spring-gds-3",
|
|
26890
|
+
"spring-gds-1810"
|
|
26884
26891
|
],
|
|
26885
26892
|
postlogistics: ["postlogistics-dashed-reference", "postlogistics-compact-reference"],
|
|
26886
26893
|
dachser: [],
|
|
@@ -34304,6 +34311,7 @@ var Uu = {
|
|
|
34304
34311
|
speedaf: 989,
|
|
34305
34312
|
speedex: 938,
|
|
34306
34313
|
speedy: 280,
|
|
34314
|
+
"spring-gds": 524,
|
|
34307
34315
|
"spx-br": 982,
|
|
34308
34316
|
"st-courier": 753,
|
|
34309
34317
|
"stallion-express": 105,
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
{"wording": "预计…飞", "language": "zh", "english": "Flight booked", "stage": "in_transit", "confirmedBy": "source", "note": "The row names the day the flight is expected to leave, as month-day; the key replaces it with an ellipsis and the English leaves it out, since it is still to come. As a universal provider relays it."},
|
|
8
8
|
{"wording": "已飞未落地", "language": "zh", "english": "Flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."},
|
|
9
9
|
{"wording": "一程已落地 二程预计…飞", "language": "zh", "english": "First flight landed, connecting flight booked", "stage": "in_transit", "confirmedBy": "source", "note": "The first leg has landed; the row names the day the second is expected to leave, which the key replaces with an ellipsis. As a universal provider relays it."},
|
|
10
|
-
{"wording": "二程已飞未落地", "language": "zh", "english": "Connecting flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."}
|
|
10
|
+
{"wording": "二程已飞未落地", "language": "zh", "english": "Connecting flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."},
|
|
11
|
+
{"wording": "已落地 等待拆板提货", "language": "zh", "english": "Landed, awaiting unloading for collection", "stage": "in_transit", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "The last flight has landed; its pallets are still to be broken down and the shipment collected from the airport."},
|
|
12
|
+
{"wording": "已提回 等待清关", "language": "zh", "english": "Collected from the airport, awaiting customs clearance", "stage": "customs", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "Collected from the airport and held for import clearance, as other forwarders' rows of the same step read."}
|
|
11
13
|
]
|
|
12
14
|
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* delivery postcode. With a Dutch postcode, or another country's postcode
|
|
23
23
|
* given with that country, that tracker is asked first.
|
|
24
24
|
*/
|
|
25
|
-
import type
|
|
25
|
+
import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
|
|
26
26
|
import type { CarrierResult } from '../../core/result/index.js';
|
|
27
27
|
import { type StepRecorder } from '../../core/telemetry/index.js';
|
|
28
28
|
/** Projects one `tracking-items` payload. Pure: the offline tests target this. */
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostNL international tracking (carrier id `spring-gds`).
|
|
3
|
+
*
|
|
4
|
+
* The folder keeps the historical `spring-gds` id for parcels and clients that
|
|
5
|
+
* already store it; the carrier is presented as PostNL everywhere else. Spring
|
|
6
|
+
* GDS is PostNL's international subsidiary and its mailingtechnology.com
|
|
7
|
+
* portal shows the same barcode (see this folder's README).
|
|
8
|
+
*
|
|
9
|
+
* `postnl.post` hands out a visitor token that lasts a day to anyone who asks,
|
|
10
|
+
* then accepts a batch tracking request with it. The tracker keeps the token
|
|
11
|
+
* for its later lookups. Both calls replay once after a transport failure or an
|
|
12
|
+
* HTTP 502/503/504, and an HTTP 429 only when it supplies a short, valid
|
|
13
|
+
* `Retry-After` that ends before the lookup does. A 429 left standing names the
|
|
14
|
+
* wait PostNL asked for.
|
|
15
|
+
*
|
|
16
|
+
* The response echoes the requested barcodes, so the item whose `item` equals
|
|
17
|
+
* the requested number is the only one read. PostNL answers an unknown barcode
|
|
18
|
+
* with an ordinary item that has no events and says so in `message`.
|
|
19
|
+
*
|
|
20
|
+
* A 3S barcode sent within the Netherlands is not there: PostNL's domestic
|
|
21
|
+
* tracker on jouw.postnl.nl shows it, given the barcode, the country and the
|
|
22
|
+
* delivery postcode. With a Dutch postcode, or another country's postcode
|
|
23
|
+
* given with that country, that tracker is asked first.
|
|
24
|
+
*/
|
|
25
|
+
import { recognizeFromLookup } from '../../core/adapter/index.js';
|
|
26
|
+
import { CARRIER_DEFINITIONS } from '../../core/catalog/definitions.js';
|
|
1
27
|
import { DateTime } from 'luxon';
|
|
2
28
|
import { CarrierError, IndeterminateError, InputRequiredError, NoHistoryError, NotFoundError, RateLimitedError, SchemaError, TransportError, UpstreamHttpError, UpstreamNetworkError, } from '../../core/errors/index.js';
|
|
3
29
|
import { runSteps } from '../../core/runner/index.js';
|
|
@@ -8,6 +34,7 @@ import { fetchBounded, parseJsonBytes, userAgentOf } from '../../core/transport/
|
|
|
8
34
|
import { isRecord } from '../../core/types.js';
|
|
9
35
|
import { postNLCode, postNLDomesticStage, postNLStatus } from './status.js';
|
|
10
36
|
const PROVIDER = 'PostNL';
|
|
37
|
+
const RECOGNIZED = new RegExp(CARRIER_DEFINITIONS['spring-gds']?.tracking.recognitionPattern ?? '(?!)');
|
|
11
38
|
const TOKEN_URL = 'https://postnl.post/api/v1/auth/token';
|
|
12
39
|
const TRACK_URL = 'https://postnl.post/api/v1/tracking-items';
|
|
13
40
|
const DOMESTIC_URL = 'https://jouw.postnl.nl/track-and-trace/api/trackAndTrace';
|
|
@@ -449,5 +476,8 @@ export const adapter = (environment) => {
|
|
|
449
476
|
// on the same host, and each replays once inside the step.
|
|
450
477
|
steps: ['domestic', 'direct'],
|
|
451
478
|
track: (input, context) => tracker.fetch(input.number, context, input.postcode, input.postcodeCountry),
|
|
479
|
+
// Only the series the catalog's recognition pattern names: a 3S barcode PostNL
|
|
480
|
+
// does not find may still be on the domestic tracker, behind a postcode.
|
|
481
|
+
recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => RECOGNIZED.test(comparableIdentifier(number))),
|
|
452
482
|
};
|
|
453
483
|
};
|
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
"domestic",
|
|
41
41
|
"direct"
|
|
42
42
|
],
|
|
43
|
+
"recognition": {
|
|
44
|
+
"rank": 524,
|
|
45
|
+
"pattern": "^1810\\d{14}$"
|
|
46
|
+
},
|
|
43
47
|
"refresh": {
|
|
44
48
|
"minMinutes": 30
|
|
45
49
|
},
|
|
@@ -118,6 +122,11 @@
|
|
|
118
122
|
"id": "spring-gds-3",
|
|
119
123
|
"pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
|
|
120
124
|
"confidence": "low"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "spring-gds-1810",
|
|
128
|
+
"pattern": "^1810\\d{14}$",
|
|
129
|
+
"confidence": "low"
|
|
121
130
|
}
|
|
122
131
|
]
|
|
123
132
|
}
|
|
@@ -595,6 +595,23 @@
|
|
|
595
595
|
"confidence": "high"
|
|
596
596
|
},
|
|
597
597
|
"note": "A PostNL tracking link archived by the Wayback Machine. PostNL's tracker returns its history, an item delivered abroad."
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"number": "181011000000000017",
|
|
601
|
+
"role": "shipment",
|
|
602
|
+
"evidence": "synthetic",
|
|
603
|
+
"derivedFrom": "donated_real",
|
|
604
|
+
"shapeConfirmed": "2026-10-29",
|
|
605
|
+
"expect": {
|
|
606
|
+
"carrier": "unknown",
|
|
607
|
+
"confidence": "low",
|
|
608
|
+
"candidates": [
|
|
609
|
+
"spring-gds",
|
|
610
|
+
"bpost",
|
|
611
|
+
"ecoscooting"
|
|
612
|
+
]
|
|
613
|
+
},
|
|
614
|
+
"note": "Made-up number in the shape of a parcel for Italy that PostNL's international tracker answered: 1810 and fourteen digits."
|
|
598
615
|
}
|
|
599
616
|
]
|
|
600
617
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
{"code": "Warehousing_Packed", "wording": "Parcel has been packed and is ready for outbound shipping", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-21", "note": "Packed at the warehouse for the line abroad; its Chinese name is 包裹装箱."},
|
|
7
7
|
{"code": "Warehousing_Departed", "wording": "Departed from the original facility", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-25", "note": "The parcel left Techlink's warehouse in China."},
|
|
8
8
|
{"code": "Decl_ExportDone", "wording": "Export customs declaration completed", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-25", "note": "China's export declaration, written after the parcel left the warehouse; the parcel is not held in customs."},
|
|
9
|
-
{"code": "InTransit_Departure", "wording": "Depart from the original airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-26", "note": "The flight left the airport in China."}
|
|
9
|
+
{"code": "InTransit_Departure", "wording": "Depart from the original airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-26", "note": "The flight left the airport in China."},
|
|
10
|
+
{"code": "InTransit_Arrival", "wording": "Arrive at the destination airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "The flight landed in the destination country, before its import clearance."}
|
|
10
11
|
]
|
|
11
12
|
}
|
package/dist/data/catalog.json
CHANGED
|
@@ -427,6 +427,8 @@
|
|
|
427
427
|
"autoComplete": "postal-code"
|
|
428
428
|
}
|
|
429
429
|
],
|
|
430
|
+
"recognitionRank": 524,
|
|
431
|
+
"recognitionPattern": "^1810\\d{14}$",
|
|
430
432
|
"refresh": {
|
|
431
433
|
"minMinutes": 30
|
|
432
434
|
},
|
|
@@ -476,6 +478,10 @@
|
|
|
476
478
|
{
|
|
477
479
|
"pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
|
|
478
480
|
"confidence": "low"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"pattern": "^1810\\d{14}$",
|
|
484
|
+
"confidence": "low"
|
|
479
485
|
}
|
|
480
486
|
]
|
|
481
487
|
},
|
|
@@ -298,6 +298,8 @@ export declare const CARRIER_CATALOG: {
|
|
|
298
298
|
readonly inputMode: "text";
|
|
299
299
|
readonly autoComplete: "postal-code";
|
|
300
300
|
}];
|
|
301
|
+
readonly recognitionRank: 524;
|
|
302
|
+
readonly recognitionPattern: "^1810\\d{14}$";
|
|
301
303
|
readonly refresh: {
|
|
302
304
|
readonly minMinutes: 30;
|
|
303
305
|
};
|
|
@@ -330,6 +332,9 @@ export declare const CARRIER_CATALOG: {
|
|
|
330
332
|
}, {
|
|
331
333
|
readonly pattern: "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$";
|
|
332
334
|
readonly confidence: "low";
|
|
335
|
+
}, {
|
|
336
|
+
readonly pattern: "^1810\\d{14}$";
|
|
337
|
+
readonly confidence: "low";
|
|
333
338
|
}];
|
|
334
339
|
};
|
|
335
340
|
readonly postlogistics: {
|
|
@@ -428,6 +428,8 @@ export const CARRIER_CATALOG = {
|
|
|
428
428
|
"autoComplete": "postal-code"
|
|
429
429
|
}
|
|
430
430
|
],
|
|
431
|
+
"recognitionRank": 524,
|
|
432
|
+
"recognitionPattern": "^1810\\d{14}$",
|
|
431
433
|
"refresh": {
|
|
432
434
|
"minMinutes": 30
|
|
433
435
|
},
|
|
@@ -477,6 +479,10 @@ export const CARRIER_CATALOG = {
|
|
|
477
479
|
{
|
|
478
480
|
"pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
|
|
479
481
|
"confidence": "low"
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"pattern": "^1810\\d{14}$",
|
|
485
|
+
"confidence": "low"
|
|
480
486
|
}
|
|
481
487
|
]
|
|
482
488
|
},
|
|
@@ -36392,7 +36398,7 @@ export const DETECTION_RULE_IDS = {
|
|
|
36392
36398
|
"aliexpress": ["aliexpress-1", "aliexpress-cnfr", "aliexpress-2", "aliexpress-maersk", "aliexpress-lp-reference", "aliexpress-ap-reference", "aliexpress-cnbr", "aliexpress-cnmex", "aliexpress-cnusup", "aliexpress-cacainiao", "aliexpress-rl", "aliexpress-jncn", "aliexpress-gfus", "aliexpress-ecsc-aaro", "aliexpress-pa", "aliexpress-f", "aliexpress-9c-i", "aliexpress-9c-j", "aliexpress-rtz", "aliexpress-fmp", "aliexpress-sda-waybill", "aliexpress-ty", "aliexpress-mi", "aliexpress-xx"],
|
|
36393
36399
|
"sunyou": ["sunyou-1", "sunyou-2", "sunyou-3"],
|
|
36394
36400
|
"hermes": ["hermes-delivery-note"],
|
|
36395
|
-
"spring-gds": ["spring-gds-1", "spring-gds-2", "spring-gds-3"],
|
|
36401
|
+
"spring-gds": ["spring-gds-1", "spring-gds-2", "spring-gds-3", "spring-gds-1810"],
|
|
36396
36402
|
"postlogistics": ["postlogistics-dashed-reference", "postlogistics-compact-reference"],
|
|
36397
36403
|
"dachser": [],
|
|
36398
36404
|
"dhl": ["dhl-1", "dhl-14", "dhl-16", "dhl-15", "dhl-9", "dhl-8", "dhl-10", "dhl-3", "dhl-13", "dhl-12", "dhl-7"],
|
|
@@ -560,13 +560,18 @@ const LOCAL_WALL_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?$/;
|
|
|
560
560
|
// A flight written before it leaves is still to come: no scan, as the lines' own trackers drop it.
|
|
561
561
|
// 17FEIA's estimated departure, and the flight DHLink, Intel-Valley and Mayi Yinfu book.
|
|
562
562
|
const flightToCome = (label) => FLIGHT_ESTIMATE.test(label) || DHLINK_FLIGHT.test(label) || intelValleyFlight(label) || MAYIYINFU_FLIGHT.test(label);
|
|
563
|
+
// A carrier's schedule, as 17TRACK relays it beside the milestones: an ocean line's estimated vessel departure and
|
|
564
|
+
// arrival, each again once updated, and its cargo cut-off, and a flight's ETD or ETA. Each is dated when it is due,
|
|
565
|
+
// often weeks ahead, so it is no scan.
|
|
566
|
+
const SCHEDULE = /^(?:estimated vessel (?:departure|arrival)|cfs\/cy cut-off date)(?: \(last updated\))?$|^flight et[ad]\b/i;
|
|
563
567
|
// A time or date in brackets with no words, as 17TRACK relays a Juxi Express row between the flight
|
|
564
|
-
// being arranged at the airport and the departure
|
|
565
|
-
|
|
568
|
+
// being arranged at the airport and the departure, and ParcelsApp one dated by month and day ("(10.20)")
|
|
569
|
+
// between its departure and arrival: it says nothing happened, so it is no scan.
|
|
570
|
+
const BARE_TIME = /^[((]\s*\d{1,2}\s*[::..]\s*\d{1,2}\s*[))]$/;
|
|
566
571
|
function describe(description, stage) {
|
|
567
572
|
// A copy of SunYou's departure drops the last-mile number, as SunYou's own result does.
|
|
568
573
|
const label = sunYouWording(relayedNotice(text(description)).replace(CLEARANCE_STATUS, ''));
|
|
569
|
-
if (!label || isNotice(label) || flightToCome(label) || BARE_TIME.test(label))
|
|
574
|
+
if (!label || isNotice(label) || flightToCome(label) || SCHEDULE.test(label) || BARE_TIME.test(label))
|
|
570
575
|
return null;
|
|
571
576
|
const declared = typeof stage === 'string' && Object.hasOwn(STAGES, stage) ? STAGES[stage] : undefined;
|
|
572
577
|
// Established source semantics (e.g. handoff/negation) remain first. A real
|
package/dist/server/openapi.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-parcel-scraper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.810.1-main.4374",
|
|
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",
|