pal-crawl 2.0.4 → 2.2.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.
@@ -0,0 +1 @@
1
+ d56ee6eb-546a-4a34-a6c7-6c28626bb8b8
package/README.md CHANGED
@@ -40,6 +40,7 @@
40
40
  - [getAllPages (NsmLmSts)](#getallpagesquery-options--asyncgeneratorinsmsearchresult)
41
41
  - [getAllPendingPages](#getallpendingpagesquery-options--asyncgeneratorinsmsearchresult)
42
42
  - [Screenshot (NsmLmSts)](#getnsmlisscreenshotquery--promisebuffer)
43
+ - [LikmsCrawler - 국회 의안정보시스템 제안이유 조회](#likmscrawler---국회-의안정보시스템-제안이유-조회)
43
44
  - [Examples](#examples)
44
45
  - [License](#license)
45
46
 
@@ -72,6 +73,8 @@ interface PalCrawlConfig {
72
73
  retryCount?: number; // 재시도 횟수 (기본값: 3)
73
74
  customHeaders?: Record<string, string>; // 사용자 정의 헤더
74
75
  screenshot?: ScreenshotOptions; // 헤드리스 크로뮴 스크린샷 옵션
76
+ hydrateTruncatedTitles?: boolean; // 잘린 제목 상세 조회 여부 (기본값: false)
77
+ hydrateProposalReason?: boolean; // 제안이유 빈 값일 때 의안정보시스템 보정 (기본값: true)
75
78
  }
76
79
 
77
80
  interface ScreenshotOptions {
@@ -150,6 +153,8 @@ interface IContentData {
150
153
  }
151
154
  ```
152
155
 
156
+ PAL 상세 페이지에서 `proposalReason`이 비어 있는 의안이 있을 수 있습니다. 이때는 기본값(`hydrateProposalReason: true`)으로 국회 의안정보시스템(likms.assembly.go.kr)의 같은 의안에서 제안이유를 자동으로 보정합니다. 보정에 실패하더라도 기존 결과(`null`)를 그대로 유지하며 오류를 던지지 않습니다.
157
+
153
158
  `ISearchResult`는 검색/페이지 조회 결과를 나타내는 인터페이스입니다.
154
159
 
155
160
  ```typescript
@@ -477,7 +482,7 @@ for await (const page of palCrawl.getAllDonePages(
477
482
 
478
483
  ## NsmLmSts - 국민참여입법센터 국회입법현황
479
484
 
480
- `NsmLmSts` 클래스는 [국민참여입법센터 국회입법현황](https://opinion.lawmaking.go.kr/gcom/nsmLmSts/out)에서 법안 목록과 상세 정보를 크롤링합니다. 위원회 회부 이전 발의 상태 법안까지 필터링할 수 있는 것이 특징입니다.
485
+ `NsmLmSts` 클래스는 [국민참여입법센터 국회입법현황](https://opinion.lawmaking.go.kr/gcom/nsmLmSts/out)에서 법안 목록과 상세 정보를 크롤링합니다. 위원회 회부 이전 발의 상태 법안까지 필터링할 수 있는 것이 특징입니다. 목록 검색은 기본적으로 목록 페이지만 요청하며, `...`으로 잘린 제목을 상세 페이지에서 보정하려면 `hydrateTruncatedTitles: true`를 명시해야 합니다.
481
486
 
482
487
  ---
483
488
 
@@ -490,6 +495,7 @@ const nsm = new NsmLmSts({
490
495
  userAgent: 'My Bot 1.0',
491
496
  timeout: 15000,
492
497
  retryCount: 3,
498
+ hydrateTruncatedTitles: true,
493
499
  customHeaders: { 'Accept-Language': 'ko-KR' },
494
500
  });
495
501
  ```
@@ -763,6 +769,34 @@ try {
763
769
 
764
770
  ---
765
771
 
772
+ ## LikmsCrawler - 국회 의안정보시스템 제안이유 조회
773
+
774
+ `LikmsCrawler`는 [국회 의안정보시스템](https://likms.assembly.go.kr)의 의안상세 페이지에서 제안이유 및 주요내용을 조회합니다. 의안상세 페이지는 심사정보 탭을 AJAX(POST)로 채우므로, 숨김 폼 파라미터를 추출해 `billInfo.do`에 POST한 뒤 `#prntSummary`에서 제안이유를 파싱합니다.
775
+
776
+ PAL의 `contentId`(`PRC_...`)가 이 시스템의 `billId`와 동일하므로 그대로 전달할 수 있습니다.
777
+
778
+ ```typescript
779
+ import { LikmsCrawler } from 'pal-crawl';
780
+
781
+ const likms = new LikmsCrawler();
782
+
783
+ // 제안이유 조회 (실패 시 null, 절대 예외를 던지지 않음)
784
+ const reason = await likms.getProposalReason(
785
+ 'PRC_G2G6E0D9E2Z3A1Y7Z5X1Y0W4E9E6D5',
786
+ );
787
+ console.log(reason);
788
+
789
+ // 파싱만 수행하고 싶은 경우
790
+ const fragmentHtml = await likms.getBillInfoHTML(
791
+ likms.parseDetailFormParams(await likms.getDetailPageHTML(billId)),
792
+ );
793
+ console.log(likms.parseProposalReason(fragmentHtml));
794
+ ```
795
+
796
+ `PalCrawl`의 `getContent`/`getDoneContent`는 내부적으로 이 크롤러를 사용해 빈 `proposalReason`을 보정합니다(`hydrateProposalReason: false`로 비활성화 가능).
797
+
798
+ ---
799
+
766
800
  ## Examples
767
801
 
768
802
  ### 기본 사용법
package/dist/config.d.ts CHANGED
@@ -6,5 +6,9 @@ export declare enum Config {
6
6
  DONE_CONTENT_URL = "/napal/lgsltpa/lgsltpaDone/view.do",
7
7
  UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
8
8
  NSM_DOMAIN = "https://opinion.lawmaking.go.kr",
9
- NSM_LIST_URL = "/gcom/nsmLmSts/out"
9
+ NSM_LIST_URL = "/gcom/nsmLmSts/out",
10
+ LIKMS_DOMAIN = "https://likms.assembly.go.kr",
11
+ LIKMS_DETAIL_PAGE_URL = "/bill/bi/billDetailPage.do",
12
+ LIKMS_BILL_INFO_URL = "/bill/bi/bill/detail/billInfo.do",
13
+ LIKMS_CURR_MENU_NO = "2600044"
10
14
  }
package/dist/config.js CHANGED
@@ -12,5 +12,10 @@ var Config;
12
12
  // 국민참여입법센터 국회입법현황 (opinion.lawmaking.go.kr)
13
13
  Config["NSM_DOMAIN"] = "https://opinion.lawmaking.go.kr";
14
14
  Config["NSM_LIST_URL"] = "/gcom/nsmLmSts/out";
15
+ // 국회 의안정보시스템 (likms.assembly.go.kr)
16
+ Config["LIKMS_DOMAIN"] = "https://likms.assembly.go.kr";
17
+ Config["LIKMS_DETAIL_PAGE_URL"] = "/bill/bi/billDetailPage.do";
18
+ Config["LIKMS_BILL_INFO_URL"] = "/bill/bi/bill/detail/billInfo.do";
19
+ Config["LIKMS_CURR_MENU_NO"] = "2600044";
15
20
  })(Config || (exports.Config = Config = {}));
16
21
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAAA,IAAY,MAUX;AAVD,WAAY,MAAM;IAChB,+CAAqC,CAAA;IACrC,4DAAkD,CAAA;IAClD,+DAAqD,CAAA;IACrD,8DAAoD,CAAA;IACpD,iEAAuD,CAAA;IACvD,uIAA6H,CAAA;IAC7H,4CAA4C;IAC5C,wDAA8C,CAAA;IAC9C,6CAAmC,CAAA;AACrC,CAAC,EAVW,MAAM,sBAAN,MAAM,QAUjB"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAAA,IAAY,MAeX;AAfD,WAAY,MAAM;IAChB,+CAAqC,CAAA;IACrC,4DAAkD,CAAA;IAClD,+DAAqD,CAAA;IACrD,8DAAoD,CAAA;IACpD,iEAAuD,CAAA;IACvD,uIAA6H,CAAA;IAC7H,4CAA4C;IAC5C,wDAA8C,CAAA;IAC9C,6CAAmC,CAAA;IACnC,oCAAoC;IACpC,uDAA6C,CAAA;IAC7C,8DAAoD,CAAA;IACpD,kEAAwD,CAAA;IACxD,wCAA8B,CAAA;AAChC,CAAC,EAfW,MAAM,sBAAN,MAAM,QAejB"}
@@ -16,4 +16,10 @@ export declare class HttpClient {
16
16
  private decodeBody;
17
17
  private makeRequest;
18
18
  get(url: URL): Promise<string>;
19
+ /**
20
+ * URL-encoded 본문을 POST로 전송합니다.
21
+ * 국회 의안정보시스템의 일부 조각(_fragment) 엔드포인트는 GET이 아닌 POST만 허용합니다.
22
+ */
23
+ post(url: URL, body: string): Promise<string>;
24
+ private requestWithRetry;
19
25
  }
@@ -100,17 +100,23 @@ class HttpClient {
100
100
  }
101
101
  return body.toString('utf8');
102
102
  }
103
- async makeRequest(url) {
103
+ async makeRequest(url, method = 'GET', body) {
104
104
  return new Promise((resolve, reject) => {
105
105
  const headers = {
106
106
  'User-Agent': this.userAgent,
107
107
  ...this.customHeaders,
108
108
  };
109
+ if (method === 'POST' && body !== undefined) {
110
+ headers['Content-Type'] =
111
+ 'application/x-www-form-urlencoded; charset=UTF-8';
112
+ headers['Content-Length'] = String(Buffer.byteLength(body));
113
+ }
109
114
  const options = {
110
115
  headers,
111
116
  timeout: this.timeout,
117
+ method,
112
118
  };
113
- const req = https.get(url, options, (res) => {
119
+ const req = https.request(url, options, (res) => {
114
120
  if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {
115
121
  reject(new Error(`Invalid response: ${res.statusCode} ${res.statusMessage}`));
116
122
  return;
@@ -120,8 +126,8 @@ class HttpClient {
120
126
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
121
127
  });
122
128
  res.on('end', () => {
123
- const body = Buffer.concat(chunks);
124
- resolve(this.decodeBody(body, res.headers['content-type']));
129
+ const responseBody = Buffer.concat(chunks);
130
+ resolve(this.decodeBody(responseBody, res.headers['content-type']));
125
131
  });
126
132
  });
127
133
  req.on('timeout', () => {
@@ -131,14 +137,28 @@ class HttpClient {
131
137
  req.on('error', (err) => {
132
138
  reject(err);
133
139
  });
140
+ if (method === 'POST' && body !== undefined) {
141
+ req.write(body);
142
+ }
143
+ req.end();
134
144
  req.setTimeout(this.timeout);
135
145
  });
136
146
  }
137
147
  async get(url) {
148
+ return this.requestWithRetry(url, 'GET');
149
+ }
150
+ /**
151
+ * URL-encoded 본문을 POST로 전송합니다.
152
+ * 국회 의안정보시스템의 일부 조각(_fragment) 엔드포인트는 GET이 아닌 POST만 허용합니다.
153
+ */
154
+ async post(url, body) {
155
+ return this.requestWithRetry(url, 'POST', body);
156
+ }
157
+ async requestWithRetry(url, method, body) {
138
158
  let lastError;
139
159
  for (let attempt = 1; attempt <= this.retryCount; attempt++) {
140
160
  try {
141
- return await this.makeRequest(url);
161
+ return await this.makeRequest(url, method, body);
142
162
  }
143
163
  catch (error) {
144
164
  lastError = error;
@@ -1 +1 @@
1
- {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA+B;AAE/B,4DAA+B;AAS/B,MAAa,UAAU;IAMrB,YAAY,MAAwB;QAClC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC5C,CAAC;IAEO,cAAc,CACpB,WAA0C,EAC1C,IAAY;QAEZ,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YACjD,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YACvB,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAExB,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACvE,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACzE,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAC,OAAe;QACtC,IAAI,OAAO,KAAK,gBAAgB,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;YAChE,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,UAAU,CAChB,IAAY,EACZ,WAA0C;QAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CACpC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CACvC,CAAC;QAEF,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAEvC,wEAAwE;YACxE,0FAA0F;YAC1F,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAC9C,IAAI,QAAQ,GAAG,QAAQ,CAAC;gBACxB,IAAI,SAAS,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;gBAEpD,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;oBACzC,IAAI,CAAC,oBAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACpC,SAAS;oBACX,CAAC;oBAED,MAAM,SAAS,GAAG,oBAAK,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;oBAC/C,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;oBACnD,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;wBACtB,QAAQ,GAAG,SAAS,CAAC;wBACrB,SAAS,GAAG,KAAK,CAAC;oBACpB,CAAC;gBACH,CAAC;gBAED,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,oBAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO,oBAAK,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,GAAQ,EACR,SAAyB,KAAK,EAC9B,IAAa;QAEb,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAA2B;gBACtC,YAAY,EAAE,IAAI,CAAC,SAAS;gBAC5B,GAAG,IAAI,CAAC,aAAa;aACtB,CAAC;YAEF,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5C,OAAO,CAAC,cAAc,CAAC;oBACrB,kDAAkD,CAAC;gBACrD,OAAO,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,OAAO,GAAG;gBACd,OAAO;gBACP,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM;aACP,CAAC;YAEF,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC9C,IAAI,GAAG,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,CAAC;oBACtE,MAAM,CACJ,IAAI,KAAK,CACP,qBAAqB,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,aAAa,EAAE,CAC3D,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAa,EAAE,CAAC;gBAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;oBACvB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnE,CAAC,CAAC,CAAC;gBAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC3C,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;gBACtE,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACrB,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACtB,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5C,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;YAED,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,GAAQ;QACvB,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,IAAI,CAAC,GAAQ,EAAE,IAAY;QACtC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,GAAQ,EACR,MAAsB,EACtB,IAAa;QAEb,IAAI,SAAgB,CAAC;QAErB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAc,CAAC;gBAE3B,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;oBAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;oBAC9D,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC7D,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAU,CAAC;IACnB,CAAC;CACF;AAzLD,gCAyLC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { ScreenshotBase, PalCrawl, NsmLmSts, type ITableData, type IAttachment, type IContentData, type ISearchResult, type ISearchQuery, type IBulkOptions, type PalCrawlConfig, type ScreenshotOptions, type INsmSearchQuery, type INsmSearchResult, type INsmBillItem, type INsmBillDetail, type INsmAttachment, type NsmProgressStatus, type NsmProposerType, type NsmResolutionStatus, } from './pal';
2
2
  export { PalParser, NsmLmStsParser } from './parser';
3
+ export { LikmsCrawler, type LikmsCrawlerConfig } from './likms';
3
4
  export { Config } from './config';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Config = exports.NsmLmStsParser = exports.PalParser = exports.NsmLmSts = exports.PalCrawl = exports.ScreenshotBase = void 0;
3
+ exports.Config = exports.LikmsCrawler = exports.NsmLmStsParser = exports.PalParser = exports.NsmLmSts = exports.PalCrawl = exports.ScreenshotBase = void 0;
4
4
  var pal_1 = require("./pal");
5
5
  Object.defineProperty(exports, "ScreenshotBase", { enumerable: true, get: function () { return pal_1.ScreenshotBase; } });
6
6
  Object.defineProperty(exports, "PalCrawl", { enumerable: true, get: function () { return pal_1.PalCrawl; } });
@@ -8,6 +8,8 @@ Object.defineProperty(exports, "NsmLmSts", { enumerable: true, get: function ()
8
8
  var parser_1 = require("./parser");
9
9
  Object.defineProperty(exports, "PalParser", { enumerable: true, get: function () { return parser_1.PalParser; } });
10
10
  Object.defineProperty(exports, "NsmLmStsParser", { enumerable: true, get: function () { return parser_1.NsmLmStsParser; } });
11
+ var likms_1 = require("./likms");
12
+ Object.defineProperty(exports, "LikmsCrawler", { enumerable: true, get: function () { return likms_1.LikmsCrawler; } });
11
13
  var config_1 = require("./config");
12
14
  Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
13
15
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6BAoBe;AAnBb,qGAAA,cAAc,OAAA;AACd,+FAAA,QAAQ,OAAA;AACR,+FAAA,QAAQ,OAAA;AAkBV,mCAAqD;AAA5C,mGAAA,SAAS,OAAA;AAAE,wGAAA,cAAc,OAAA;AAClC,mCAAkC;AAAzB,gGAAA,MAAM,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6BAoBe;AAnBb,qGAAA,cAAc,OAAA;AACd,+FAAA,QAAQ,OAAA;AACR,+FAAA,QAAQ,OAAA;AAkBV,mCAAqD;AAA5C,mGAAA,SAAS,OAAA;AAAE,wGAAA,cAAc,OAAA;AAClC,iCAAgE;AAAvD,qGAAA,YAAY,OAAA;AACrB,mCAAkC;AAAzB,gGAAA,MAAM,OAAA"}
@@ -0,0 +1,45 @@
1
+ export interface LikmsCrawlerConfig {
2
+ userAgent?: string;
3
+ timeout?: number;
4
+ retryCount?: number;
5
+ customHeaders?: Record<string, string>;
6
+ }
7
+ /**
8
+ * 국회 의안정보시스템(likms.assembly.go.kr) 크롤러.
9
+ *
10
+ * 의안상세 페이지(billDetailPage.do)는 심사정보 탭 내용을 빈 div에 AJAX(POST)로
11
+ * 채우므로, 정적 HTML만으로는 제안이유를 읽을 수 없다.
12
+ *
13
+ * 실제 흐름 (billDetail.js 기준):
14
+ * 1. GET /bill/bi/billDetailPage.do?billId=...&currMenuNo=2600044
15
+ * → 숨김 폼(#form)에 billId, billNo, billKindCd 등 파라미터 포함
16
+ * 2. POST /bill/bi/bill/detail/billInfo.do (폼 파라미터 직렬화)
17
+ * → 심사정보 탭 조각 HTML 반환
18
+ * 3. 조각의 <pre id="prntSummary"> 안에 제안이유 및 주요내용이 들어 있음
19
+ *
20
+ * PAL(입법예고) 상세 페이지에서 제안이유가 비어 있는 의안의 contentId(=PRC_...)
21
+ * 는 동일한 ID로 이 시스템에서 조회할 수 있다.
22
+ */
23
+ export declare class LikmsCrawler {
24
+ private readonly httpClient;
25
+ constructor(config?: LikmsCrawlerConfig);
26
+ private buildDetailPageUrl;
27
+ /** 의안상세 페이지 HTML을 반환합니다. */
28
+ getDetailPageHTML(billId: string): Promise<string>;
29
+ /**
30
+ * 의안상세 페이지의 숨김 폼(#form input[type=hidden]) 파라미터를 추출합니다.
31
+ * billInfo.do AJAX 요청은 이 파라미터들에 심사정보 섹션의 렌더링 조건이 걸려
32
+ * 있어 원본 페이지에서 그대로 가져와야 한다.
33
+ */
34
+ parseDetailFormParams(html: string): Record<string, string>;
35
+ /** 심사정보 탭 조각 HTML을 POST로 반환합니다. */
36
+ getBillInfoHTML(params: Record<string, string>): Promise<string>;
37
+ /** 심사정보 탭 조각 HTML에서 제안이유 및 주요내용을 파싱하여 반환합니다. */
38
+ parseProposalReason(fragmentHtml: string): string | null;
39
+ /**
40
+ * billId(PAL contentId와 동일)로 제안이유 및 주요내용을 조회합니다.
41
+ * 네트워크·파싱 실패를 절대 던지지 않고 null을 반환해 호출부가 안전하게
42
+ * 동작하도록 한다.
43
+ */
44
+ getProposalReason(billId: string): Promise<string | null>;
45
+ }
package/dist/likms.js ADDED
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LikmsCrawler = void 0;
37
+ const url_1 = require("url");
38
+ const cheerio = __importStar(require("cheerio"));
39
+ const config_1 = require("./config");
40
+ const http_client_1 = require("./http-client");
41
+ /**
42
+ * 국회 의안정보시스템(likms.assembly.go.kr) 크롤러.
43
+ *
44
+ * 의안상세 페이지(billDetailPage.do)는 심사정보 탭 내용을 빈 div에 AJAX(POST)로
45
+ * 채우므로, 정적 HTML만으로는 제안이유를 읽을 수 없다.
46
+ *
47
+ * 실제 흐름 (billDetail.js 기준):
48
+ * 1. GET /bill/bi/billDetailPage.do?billId=...&currMenuNo=2600044
49
+ * → 숨김 폼(#form)에 billId, billNo, billKindCd 등 파라미터 포함
50
+ * 2. POST /bill/bi/bill/detail/billInfo.do (폼 파라미터 직렬화)
51
+ * → 심사정보 탭 조각 HTML 반환
52
+ * 3. 조각의 <pre id="prntSummary"> 안에 제안이유 및 주요내용이 들어 있음
53
+ *
54
+ * PAL(입법예고) 상세 페이지에서 제안이유가 비어 있는 의안의 contentId(=PRC_...)
55
+ * 는 동일한 ID로 이 시스템에서 조회할 수 있다.
56
+ */
57
+ class LikmsCrawler {
58
+ constructor(config) {
59
+ this.httpClient = new http_client_1.HttpClient({
60
+ userAgent: config?.userAgent ?? config_1.Config.UserAgent,
61
+ timeout: config?.timeout ?? 10000,
62
+ retryCount: config?.retryCount ?? 3,
63
+ customHeaders: config?.customHeaders ?? {},
64
+ });
65
+ }
66
+ buildDetailPageUrl(billId) {
67
+ const url = new url_1.URL(config_1.Config.LIKMS_DETAIL_PAGE_URL, config_1.Config.LIKMS_DOMAIN);
68
+ url.searchParams.set('billId', billId);
69
+ url.searchParams.set('currMenuNo', config_1.Config.LIKMS_CURR_MENU_NO);
70
+ return url;
71
+ }
72
+ /** 의안상세 페이지 HTML을 반환합니다. */
73
+ async getDetailPageHTML(billId) {
74
+ const normalized = billId.trim();
75
+ if (!normalized) {
76
+ throw new Error('billId is required');
77
+ }
78
+ return this.httpClient.get(this.buildDetailPageUrl(normalized));
79
+ }
80
+ /**
81
+ * 의안상세 페이지의 숨김 폼(#form input[type=hidden]) 파라미터를 추출합니다.
82
+ * billInfo.do AJAX 요청은 이 파라미터들에 심사정보 섹션의 렌더링 조건이 걸려
83
+ * 있어 원본 페이지에서 그대로 가져와야 한다.
84
+ */
85
+ parseDetailFormParams(html) {
86
+ const $ = cheerio.load(html);
87
+ const params = {};
88
+ $('#form input[type="hidden"]').each((_, el) => {
89
+ const name = $(el).attr('name');
90
+ if (!name) {
91
+ return;
92
+ }
93
+ params[name] = $(el).attr('value') ?? '';
94
+ });
95
+ return params;
96
+ }
97
+ /** 심사정보 탭 조각 HTML을 POST로 반환합니다. */
98
+ async getBillInfoHTML(params) {
99
+ const url = new url_1.URL(config_1.Config.LIKMS_BILL_INFO_URL, config_1.Config.LIKMS_DOMAIN);
100
+ const body = new URLSearchParams(params).toString();
101
+ return this.httpClient.post(url, body);
102
+ }
103
+ /** 심사정보 탭 조각 HTML에서 제안이유 및 주요내용을 파싱하여 반환합니다. */
104
+ parseProposalReason(fragmentHtml) {
105
+ const $ = cheerio.load(fragmentHtml);
106
+ const pre = $('#prntSummary').first();
107
+ if (!pre.length) {
108
+ return null;
109
+ }
110
+ const clone = pre.clone();
111
+ clone.find('br').replaceWith('\n');
112
+ const lines = clone
113
+ .text()
114
+ .replace(/\u00a0/g, ' ')
115
+ .replace(/\r/g, '')
116
+ .split('\n')
117
+ .map((line) => line.replace(/\s+/g, ' ').trim())
118
+ .filter(Boolean);
119
+ // 첫 줄이 섹션 제목("제안이유 및 주요내용")을 반복하는 경우 제거
120
+ if (lines[0]?.replace(/\s+/g, '') === '제안이유및주요내용') {
121
+ lines.shift();
122
+ }
123
+ const text = lines.join('\n');
124
+ return text || null;
125
+ }
126
+ /**
127
+ * billId(PAL contentId와 동일)로 제안이유 및 주요내용을 조회합니다.
128
+ * 네트워크·파싱 실패를 절대 던지지 않고 null을 반환해 호출부가 안전하게
129
+ * 동작하도록 한다.
130
+ */
131
+ async getProposalReason(billId) {
132
+ const normalized = billId.trim();
133
+ if (!normalized) {
134
+ return null;
135
+ }
136
+ try {
137
+ const detailHtml = await this.getDetailPageHTML(normalized);
138
+ const params = this.parseDetailFormParams(detailHtml);
139
+ if (!params.billId) {
140
+ params.billId = normalized;
141
+ }
142
+ const fragmentHtml = await this.getBillInfoHTML(params);
143
+ return this.parseProposalReason(fragmentHtml);
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ }
149
+ }
150
+ exports.LikmsCrawler = LikmsCrawler;
151
+ //# sourceMappingURL=likms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"likms.js","sourceRoot":"","sources":["../src/likms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};