pal-crawl 1.8.0 → 2.0.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 CHANGED
@@ -30,6 +30,16 @@
30
30
  - [search / searchDone](#searchquery-isearchquery--promiseisearchresult)
31
31
  - [getPage / getDonePage](#getpagepageindex-number-pageunit-number--promiseitable-data)
32
32
  - [getAllPages / getAllDonePages](#getallpagesquery-isearchquery-options-ibulkoptions--asyncgeneratorisearchresult)
33
+ - [NsmLmSts - 국민참여입법센터 국회입법현황](#nsmlmsts--국민참여입법센터-국회입법현황)
34
+ - [NsmLmSts Configuration](#nsmlmsts-configuration)
35
+ - [NsmLmSts Types](#nsmlmsts-types)
36
+ - [search (NsmLmSts)](#searchquery-insmsearchquery--promiseinsmsearchresult)
37
+ - [searchPending](#searchpendingquery--promiseinsmsearchresult)
38
+ - [getPage (NsmLmSts)](#getpagepageindex-number-query--promiseinsmBillitem)
39
+ - [getDetail](#getdetailbillno-string--promiseinsmBilldetail)
40
+ - [getAllPages (NsmLmSts)](#getallpagesquery-options--asyncgeneratorinsmsearchresult)
41
+ - [getAllPendingPages](#getallpendingpagesquery-options--asyncgeneratorinsmsearchresult)
42
+ - [Screenshot (NsmLmSts)](#getnsmlisscreenshotquery--promisebuffer)
33
43
  - [Examples](#examples)
34
44
  - [License](#license)
35
45
 
@@ -39,6 +49,8 @@
39
49
 
40
50
  국회입법예고(pal.assembly.go.kr) 사이트에서 진행 중인 입법 예고 데이터를 크롤링하는 도구입니다. 입법 예고의 주요 정보를 손쉽게 가져올 수 있습니다.
41
51
 
52
+ 국민참여입법센터 국회입법현황(opinion.lawmaking.go.kr)에서 법안을 크롤링하는 `NsmLmSts` 클래스도 포함되어 있습니다. 위원회 회부 이전에 발의된 상태로 대기 중인 법안까지 조회할 수 있습니다.
53
+
42
54
  ---
43
55
 
44
56
  ## Installation
@@ -463,6 +475,294 @@ for await (const page of palCrawl.getAllDonePages(
463
475
 
464
476
  ---
465
477
 
478
+ ## NsmLmSts - 국민참여입법센터 국회입법현황
479
+
480
+ `NsmLmSts` 클래스는 [국민참여입법센터 국회입법현황](https://opinion.lawmaking.go.kr/gcom/nsmLmSts/out)에서 법안 목록과 상세 정보를 크롤링합니다. 위원회 회부 이전 발의 상태 법안까지 필터링할 수 있는 것이 특징입니다.
481
+
482
+ ---
483
+
484
+ ### NsmLmSts Configuration
485
+
486
+ `NsmLmSts` 생성자는 `PalCrawl`과 동일한 네트워크 설정 옵션을 받습니다 (스크린샷 제외).
487
+
488
+ ```typescript
489
+ const nsm = new NsmLmSts({
490
+ userAgent: 'My Bot 1.0',
491
+ timeout: 15000,
492
+ retryCount: 3,
493
+ customHeaders: { 'Accept-Language': 'ko-KR' },
494
+ });
495
+ ```
496
+
497
+ ---
498
+
499
+ ### NsmLmSts Types
500
+
501
+ `INsmSearchQuery`는 목록 검색 필터 옵션입니다.
502
+
503
+ ```typescript
504
+ interface INsmSearchQuery {
505
+ pageIndex?: number; // 페이지 번호 (기본값: 1)
506
+ pageSize?: number; // 페이지당 건수 (10 | 20 | 50 | 100)
507
+ sugCd?: string; // 제안대수 시작 (예: "22" → 제22대)
508
+ endSugCd?: string; // 제안대수 끝
509
+ sgtCls?: NsmProposerType; // 발의구분
510
+ cptOfiOrgCd?: string; // 소관부처 코드
511
+ rslRsltNmL?: NsmProgressStatus; // 국회현황 코드
512
+ rslRsltNmR?: NsmResolutionStatus; // 의결현황 코드
513
+ scCptPpostCmt?: string; // 상임위 (예: "법제사법위원회")
514
+ searchStDtNew?: string; // 제안일자 시작 (YYYY-MM-DD)
515
+ searchEdDtNew?: string; // 제안일자 종료 (YYYY-MM-DD)
516
+ scPpsUsr?: string; // 제안자
517
+ issLawitmYn?: 'Y'; // 규제 신설·강화 해당 법안만
518
+ stDt?: string; // 추진일자 시작 (YYYY-MM-DD)
519
+ edDt?: string; // 추진일자 종료 (YYYY-MM-DD)
520
+ scBlNmSct?: string; // 의안번호 또는 의안명
521
+ sortCol?: string;
522
+ sortOrder?: 'DESC' | 'ASC';
523
+ }
524
+ ```
525
+
526
+ `NsmProgressStatus`는 국회현황 필터 코드입니다.
527
+
528
+ | 코드 | 의미 |
529
+ | ---------- | -------------------------------------- |
530
+ | `'900101'` | 발의 (위원회 회부 이전 대기 상태 포함) |
531
+ | `'900102'` | 위원회 회부 |
532
+ | `'900103'` | 위원회 상정 |
533
+ | `'900104'` | 위원회 법안소위 |
534
+ | `'900105'` | 위원회 전체회의 |
535
+ | `'900106'` | 법사위 심사 |
536
+ | `'900107'` | 본회의 심의 |
537
+ | `'900108'` | 정부이송 |
538
+ | `'900109'` | 공포 |
539
+
540
+ `NsmProposerType`은 발의구분 코드입니다.
541
+
542
+ | 코드 | 의미 |
543
+ | ---------- | ------ |
544
+ | `'900201'` | 정부 |
545
+ | `'900202'` | 의원 |
546
+ | `'900203'` | 위원장 |
547
+
548
+ `NsmResolutionStatus`는 의결현황 코드입니다.
549
+
550
+ | 코드 | 의미 |
551
+ | ---------- | ------------ |
552
+ | `'902911'` | 수정가결 |
553
+ | `'902912'` | 원안가결 |
554
+ | `'902913'` | 부결 |
555
+ | `'902914'` | 대안반영폐기 |
556
+ | `'902915'` | 폐기 |
557
+ | `'902916'` | 임기만료폐기 |
558
+ | `'902917'` | 철회 |
559
+
560
+ `INsmBillItem`은 목록 페이지의 법안 한 건입니다.
561
+
562
+ ```typescript
563
+ interface INsmBillItem {
564
+ billName: string; // 법안명
565
+ billNo: string; // 의안번호
566
+ link: string; // 상세 페이지 링크
567
+ proposer: string; // 제안자
568
+ proposalDate: string; // 제안일
569
+ committee: string; // 상임위원회 (회부 전이면 빈 문자열)
570
+ ministry: string; // 소관부처
571
+ progressStatus: string; // 국회현황 (예: "발의", "위원회 회부")
572
+ progressDate: string; // 추진일자
573
+ resolutionStatus: string; // 의결현황 (예: "원안가결")
574
+ resolutionDate: string; // 의결일자
575
+ }
576
+ ```
577
+
578
+ `INsmBillDetail`은 상세 페이지의 법안 정보입니다.
579
+
580
+ ```typescript
581
+ interface INsmBillDetail {
582
+ title: string; // 법안명
583
+ billNo: string; // 의안번호
584
+ proposalInfo: string; // 발의정보 원문 텍스트
585
+ proposer: string; // 제안자
586
+ proposalDate: string; // 제안일
587
+ session: string; // 제안회기 (예: "제435회 국회(임시회)")
588
+ proposalReason: string | null; // 제안이유 및 주요내용
589
+ attachments: INsmAttachment[]; // 의안원문 첨부파일 목록
590
+ }
591
+ ```
592
+
593
+ `INsmAttachment`는 첨부파일 정보입니다.
594
+
595
+ ```typescript
596
+ interface INsmAttachment {
597
+ filename: string; // 파일명
598
+ fileId: string; // fnDownload() 호출에 사용되는 파일 ID
599
+ }
600
+ ```
601
+
602
+ `INsmSearchResult`는 목록 검색 결과입니다.
603
+
604
+ ```typescript
605
+ interface INsmSearchResult {
606
+ total: number;
607
+ totalPages: number;
608
+ currentPage: number;
609
+ items: INsmBillItem[];
610
+ }
611
+ ```
612
+
613
+ ---
614
+
615
+ ### search(query?: INsmSearchQuery) => Promise\<INsmSearchResult>
616
+
617
+ 법안 목록을 검색합니다. 필터를 지정하지 않으면 최신 법안 1페이지를 반환합니다.
618
+
619
+ ```typescript
620
+ import { NsmLmSts } from 'pal-crawl';
621
+
622
+ const nsm = new NsmLmSts();
623
+
624
+ // 기본 조회
625
+ const result = await nsm.search();
626
+ console.log(result.total, result.items);
627
+
628
+ // 제22대 의원발의 법안 조회
629
+ const filtered = await nsm.search({
630
+ sugCd: '22',
631
+ endSugCd: '22',
632
+ sgtCls: '900202',
633
+ pageSize: 20,
634
+ });
635
+ ```
636
+
637
+ ---
638
+
639
+ ### searchPending(query?) => Promise\<INsmSearchResult>
640
+
641
+ 위원회 회부 이전 발의 상태(`rslRsltNmL: '900101'`)로 고정하여 조회합니다. 대기 중인 법안만 가져오고 싶을 때 사용합니다.
642
+
643
+ ```typescript
644
+ import { NsmLmSts } from 'pal-crawl';
645
+
646
+ const nsm = new NsmLmSts();
647
+
648
+ // 현재 발의 상태로 대기 중인 법안 조회
649
+ const pending = await nsm.searchPending();
650
+ console.log(`발의 대기 중: ${pending.total}건`);
651
+ pending.items.forEach((item) => console.log(item.billName));
652
+ ```
653
+
654
+ ---
655
+
656
+ ### getPage(pageIndex: number, query?) => Promise\<INsmBillItem[]>
657
+
658
+ 특정 페이지의 법안 목록만 배열로 반환합니다.
659
+
660
+ ```typescript
661
+ import { NsmLmSts } from 'pal-crawl';
662
+
663
+ const nsm = new NsmLmSts();
664
+ const page2 = await nsm.getPage(2, { pageSize: 20 });
665
+ ```
666
+
667
+ ---
668
+
669
+ ### getDetailHTML(billNo: string) => Promise\<string>
670
+
671
+ 법안 상세 페이지의 HTML 원문을 반환합니다.
672
+
673
+ ### getDetail(billNo: string) => Promise\<INsmBillDetail>
674
+
675
+ 의안번호로 법안 상세 정보를 조회합니다.
676
+
677
+ ```typescript
678
+ import { NsmLmSts } from 'pal-crawl';
679
+
680
+ const nsm = new NsmLmSts();
681
+ const items = await nsm.getPage(1);
682
+ const detail = await nsm.getDetail(items[0].billNo);
683
+
684
+ console.log(detail.title);
685
+ console.log(detail.proposer);
686
+ console.log(detail.proposalDate);
687
+ console.log(detail.session);
688
+ console.log(detail.proposalReason);
689
+ console.log(detail.attachments);
690
+ // [{ filename: '법안.hwp', fileId: '99001' }, ...]
691
+ ```
692
+
693
+ ---
694
+
695
+ ### getAllPages(query?, options?) => AsyncGenerator\<INsmSearchResult>
696
+
697
+ 전체 페이지를 순차적으로 yield하는 async generator입니다. `IBulkOptions`로 딜레이·동시성·최대 페이지를 조절할 수 있습니다.
698
+
699
+ ```typescript
700
+ import { NsmLmSts } from 'pal-crawl';
701
+
702
+ const nsm = new NsmLmSts();
703
+
704
+ for await (const page of nsm.getAllPages(
705
+ { pageSize: 20 },
706
+ { maxPages: 5, delayMs: 300 },
707
+ )) {
708
+ console.log(
709
+ `페이지 ${page.currentPage}/${page.totalPages}: ${page.items.length}건`,
710
+ );
711
+ }
712
+ ```
713
+
714
+ ---
715
+
716
+ ### getAllPendingPages(query?, options?) => AsyncGenerator\<INsmSearchResult>
717
+
718
+ 발의 상태(`rslRsltNmL: '900101'`) 법안 전체를 페이지 단위로 yield합니다.
719
+
720
+ ```typescript
721
+ import { NsmLmSts } from 'pal-crawl';
722
+
723
+ const nsm = new NsmLmSts();
724
+ const pendingItems = [];
725
+
726
+ for await (const page of nsm.getAllPendingPages({}, { delayMs: 500 })) {
727
+ pendingItems.push(...page.items);
728
+ console.log(
729
+ `${page.currentPage}/${page.totalPages}: 누적 ${pendingItems.length}건`,
730
+ );
731
+ }
732
+ ```
733
+
734
+ ---
735
+
736
+ ### getNsmListScreenshot(query?) => Promise\<Buffer>
737
+
738
+ 국회입법현황 목록 페이지의 스크린샷을 `Buffer`로 반환합니다. `screenshot.enabled: true`로 초기화해야 합니다.
739
+
740
+ ### getDetailScreenshot(billNo: string) => Promise\<Buffer>
741
+
742
+ 법안 상세 페이지의 스크린샷을 `Buffer`로 반환합니다.
743
+
744
+ ```typescript
745
+ import fs from 'node:fs';
746
+ import { NsmLmSts } from 'pal-crawl';
747
+
748
+ const nsm = new NsmLmSts({ screenshot: { enabled: true, fullPage: true } });
749
+
750
+ try {
751
+ const items = await nsm.getPage(1);
752
+ const listBuf = await nsm.getNsmListScreenshot();
753
+ fs.writeFileSync('nsm-list.png', listBuf);
754
+
755
+ const detailBuf = await nsm.getDetailScreenshot(items[0].billNo);
756
+ fs.writeFileSync('nsm-detail.png', detailBuf);
757
+ } finally {
758
+ await nsm.closeBrowser();
759
+ }
760
+ ```
761
+
762
+ > `takeScreenshot(url)`, `initBrowser()`, `closeBrowser()`, `updateScreenshotConfig()` 메서드는 `PalCrawl`과 공유되는 `ScreenshotBase`에서 상속됩니다.
763
+
764
+ ---
765
+
466
766
  ## Examples
467
767
 
468
768
  ### 기본 사용법
@@ -628,6 +928,67 @@ try {
628
928
 
629
929
  `takeScreenshot`, `getPalScreenshot`, `getContentScreenshot`, `getDoneScreenshot`, `getDoneContentScreenshot`는 모두 `Buffer`를 반환합니다.
630
930
 
931
+ ### 국민참여입법센터에서 발의 대기 중인 법안 전체 수집
932
+
933
+ ```typescript
934
+ import { NsmLmSts, type INsmBillItem } from 'pal-crawl';
935
+
936
+ const nsm = new NsmLmSts();
937
+ const pendingItems: INsmBillItem[] = [];
938
+
939
+ for await (const page of nsm.getAllPendingPages({}, { delayMs: 500 })) {
940
+ pendingItems.push(...page.items);
941
+ console.log(
942
+ `수집 중: ${page.currentPage}/${page.totalPages} 페이지 (누적 ${pendingItems.length}건)`,
943
+ );
944
+ }
945
+
946
+ console.log(`발의 대기 중 법안 ${pendingItems.length}건 수집 완료`);
947
+ ```
948
+
949
+ ### 국민참여입법센터에서 법안 상세 정보 조회
950
+
951
+ ```typescript
952
+ import { NsmLmSts } from 'pal-crawl';
953
+
954
+ const nsm = new NsmLmSts();
955
+
956
+ // 1페이지 목록에서 첫 번째 법안 상세 조회
957
+ const items = await nsm.getPage(1);
958
+ if (items.length > 0) {
959
+ const detail = await nsm.getDetail(items[0].billNo);
960
+ console.log(detail.title);
961
+ console.log(detail.proposer);
962
+ console.log(detail.proposalDate);
963
+ console.log(detail.session);
964
+ console.log(detail.proposalReason);
965
+ // 첨부파일 목록
966
+ detail.attachments.forEach((att) => {
967
+ console.log(`${att.filename} (ID: ${att.fileId})`);
968
+ });
969
+ }
970
+ ```
971
+
972
+ ### 국민참여입법센터 조건부 검색 (제22대 의원발의 법안)
973
+
974
+ ```typescript
975
+ import { NsmLmSts } from 'pal-crawl';
976
+
977
+ const nsm = new NsmLmSts();
978
+
979
+ const result = await nsm.search({
980
+ sugCd: '22',
981
+ endSugCd: '22',
982
+ sgtCls: '900202', // 의원발의
983
+ pageSize: 50,
984
+ });
985
+
986
+ console.log(`제22대 의원발의 법안: ${result.total}건`);
987
+ result.items.forEach((item) => {
988
+ console.log(`[${item.progressStatus}] ${item.billName} (${item.proposer})`);
989
+ });
990
+ ```
991
+
631
992
  ### 에러 처리
632
993
 
633
994
  ```typescript
package/dist/config.d.ts CHANGED
@@ -4,5 +4,7 @@ export declare enum Config {
4
4
  CONTENT_URL = "/napal/lgsltpa/lgsltpaOngoing/view.do",
5
5
  DONE_LIST_URL = "/napal/lgsltpa/lgsltpaDone/list.do",
6
6
  DONE_CONTENT_URL = "/napal/lgsltpa/lgsltpaDone/view.do",
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"
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
+ NSM_DOMAIN = "https://opinion.lawmaking.go.kr",
9
+ NSM_LIST_URL = "/gcom/nsmLmSts/out"
8
10
  }
package/dist/config.js CHANGED
@@ -9,5 +9,8 @@ var Config;
9
9
  Config["DONE_LIST_URL"] = "/napal/lgsltpa/lgsltpaDone/list.do";
10
10
  Config["DONE_CONTENT_URL"] = "/napal/lgsltpa/lgsltpaDone/view.do";
11
11
  Config["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
12
+ // 국민참여입법센터 국회입법현황 (opinion.lawmaking.go.kr)
13
+ Config["NSM_DOMAIN"] = "https://opinion.lawmaking.go.kr";
14
+ Config["NSM_LIST_URL"] = "/gcom/nsmLmSts/out";
12
15
  })(Config || (exports.Config = Config = {}));
13
16
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAAA,IAAY,MAOX;AAPD,WAAY,MAAM;IAChB,+CAAqC,CAAA;IACrC,4DAAkD,CAAA;IAClD,+DAAqD,CAAA;IACrD,8DAAoD,CAAA;IACpD,iEAAuD,CAAA;IACvD,uIAA6H,CAAA;AAC/H,CAAC,EAPW,MAAM,sBAAN,MAAM,QAOjB"}
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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { PalCrawl, type ITableData, type IAttachment, type IContentData, type ISearchResult, type ISearchQuery, type IBulkOptions, type PalCrawlConfig, type ScreenshotOptions, } from './pal';
2
- export { PalParser } from './parser';
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
+ export { PalParser, NsmLmStsParser } from './parser';
3
3
  export { Config } from './config';
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Config = exports.PalParser = exports.PalCrawl = void 0;
3
+ exports.Config = exports.NsmLmStsParser = exports.PalParser = exports.NsmLmSts = exports.PalCrawl = exports.ScreenshotBase = void 0;
4
4
  var pal_1 = require("./pal");
5
+ Object.defineProperty(exports, "ScreenshotBase", { enumerable: true, get: function () { return pal_1.ScreenshotBase; } });
5
6
  Object.defineProperty(exports, "PalCrawl", { enumerable: true, get: function () { return pal_1.PalCrawl; } });
7
+ Object.defineProperty(exports, "NsmLmSts", { enumerable: true, get: function () { return pal_1.NsmLmSts; } });
6
8
  var parser_1 = require("./parser");
7
9
  Object.defineProperty(exports, "PalParser", { enumerable: true, get: function () { return parser_1.PalParser; } });
10
+ Object.defineProperty(exports, "NsmLmStsParser", { enumerable: true, get: function () { return parser_1.NsmLmStsParser; } });
8
11
  var config_1 = require("./config");
9
12
  Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
10
13
  //# 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,6BAUe;AATb,+FAAA,QAAQ,OAAA;AAUV,mCAAqC;AAA5B,mGAAA,SAAS,OAAA;AAClB,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,mCAAkC;AAAzB,gGAAA,MAAM,OAAA"}
package/dist/pal.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { type ITableData, type IContentData, type ISearchResult } from './parser';
2
- export type { IAttachment, ITableData, IContentData, ISearchResult, } from './parser';
1
+ import { type ITableData, type IContentData, type ISearchResult, type INsmBillItem, type INsmBillDetail, type INsmSearchResult } from './parser';
2
+ export type { IAttachment, ITableData, IContentData, ISearchResult, INsmAttachment, INsmBillItem, INsmBillDetail, INsmSearchResult, } from './parser';
3
3
  export interface ScreenshotOptions {
4
4
  enabled?: boolean;
5
5
  fullPage?: boolean;
@@ -34,75 +34,178 @@ export interface IBulkOptions {
34
34
  concurrency?: number;
35
35
  maxPages?: number;
36
36
  }
37
- export declare class PalCrawl {
38
- private readonly httpClient;
39
- private readonly parser;
37
+ /**
38
+ * Puppeteer 기반 스크린샷 기능을 공유하는 베이스 클래스.
39
+ * `PalCrawl`과 `NsmLmSts` 양쪽에서 상속합니다.
40
+ */
41
+ export declare abstract class ScreenshotBase {
40
42
  private browser;
41
- private screenshotConfig;
42
- constructor(config?: PalCrawlConfig);
43
- /**
44
- * Initialize the Puppeteer browser instance.
45
- * Call this before taking screenshots if not already initialized.
46
- */
43
+ protected screenshotConfig: ScreenshotOptions;
44
+ protected constructor(screenshot?: ScreenshotOptions);
45
+ /** Puppeteer 브라우저 인스턴스를 초기화합니다. */
47
46
  initBrowser(): Promise<void>;
48
- /**
49
- * Close the Puppeteer browser instance.
50
- * Call this when done to free up resources.
51
- */
47
+ /** Puppeteer 브라우저 인스턴스를 종료하고 리소스를 해제합니다. */
52
48
  closeBrowser(): Promise<void>;
53
- /**
54
- * Take a screenshot of a URL and return it as a Buffer.
55
- * Initializes browser if not already done.
56
- */
49
+ /** 주어진 URL의 스크린샷을 Buffer로 반환합니다. */
57
50
  takeScreenshot(urlStr: string): Promise<Buffer>;
58
- /**
59
- * Get a screenshot of the bill list page.
60
- */
51
+ /** 스크린샷 설정을 업데이트합니다. */
52
+ updateScreenshotConfig(config: Partial<ScreenshotOptions>): void;
53
+ }
54
+ export declare class PalCrawl extends ScreenshotBase {
55
+ private readonly httpClient;
56
+ private readonly parser;
57
+ constructor(config?: PalCrawlConfig);
58
+ /** 진행 중인 입법예고 목록 페이지 스크린샷을 반환합니다. */
61
59
  getPalScreenshot(): Promise<Buffer>;
62
- /**
63
- * Get a screenshot of a specific bill content page.
64
- */
60
+ /** 진행 중인 입법예고의 특정 법률안 상세 페이지 스크린샷을 반환합니다. */
65
61
  getContentScreenshot(id: string): Promise<Buffer>;
66
- /**
67
- * Get a screenshot of the done bills list page.
68
- */
62
+ /** 완료된 입법예고 목록 페이지 스크린샷을 반환합니다. */
69
63
  getDoneScreenshot(): Promise<Buffer>;
70
- /**
71
- * Get a screenshot of a specific done bill content page.
72
- */
64
+ /** 완료된 입법예고의 특정 법률안 상세 페이지 스크린샷을 반환합니다. */
73
65
  getDoneContentScreenshot(id: string): Promise<Buffer>;
74
- /**
75
- * Update screenshot configuration.
76
- */
77
- updateScreenshotConfig(config: Partial<ScreenshotOptions>): void;
78
66
  private buildListUrl;
67
+ /** 진행 중인 입법예고 목록 페이지의 HTML을 반환합니다. */
79
68
  getPalHTML(): Promise<string>;
69
+ /** HTML에서 법률안 목록을 파싱하여 반환합니다. */
80
70
  parseTable(html: string): ITableData[];
71
+ /** HTML에서 법률안 상세 내용을 파싱하여 반환합니다. */
81
72
  parseContent(html: string): IContentData;
73
+ /** 진행 중인 입법예고 목록의 첫 페이지를 반환합니다. */
82
74
  get(): Promise<ITableData[]>;
75
+ /** ID로 진행 중인 입법예고의 법률안 상세 페이지 HTML을 반환합니다. */
83
76
  getContentHTML(id: string): Promise<string>;
77
+ /** ID로 진행 중인 입법예고의 법률안 상세 정보를 조회합니다. */
84
78
  getContent(id: string): Promise<IContentData>;
79
+ /** 완료된 입법예고 목록 페이지의 HTML을 반환합니다. */
85
80
  getDoneHTML(): Promise<string>;
81
+ /** 완료된 입법예고 목록의 첫 페이지를 반환합니다. */
86
82
  getDone(): Promise<ITableData[]>;
83
+ /** ID로 완료된 입법예고의 법률안 상세 페이지 HTML을 반환합니다. */
87
84
  getDoneContentHTML(id: string): Promise<string>;
85
+ /** ID로 완료된 입법예고의 법률안 상세 정보를 조회합니다. */
88
86
  getDoneContent(id: string): Promise<IContentData>;
89
- /** Fetch ongoing notices with optional filters and return parsed result with metadata. */
87
+ /** 진행 중인 입법예고를 검색합니다. 필터를 지정하지 않으면 1페이지를 반환합니다. */
90
88
  search(query?: ISearchQuery): Promise<ISearchResult>;
91
- /** Fetch done notices with optional filters and return parsed result with metadata. */
89
+ /** 완료된 입법예고를 검색합니다. 필터를 지정하지 않으면 1페이지를 반환합니다. */
92
90
  searchDone(query?: ISearchQuery): Promise<ISearchResult>;
93
- /** Fetch a specific page of ongoing notices. */
91
+ /** 진행 중인 입법예고의 특정 페이지 목록을 반환합니다. */
94
92
  getPage(pageIndex: number, pageUnit?: number): Promise<ITableData[]>;
95
- /** Fetch a specific page of done notices. */
93
+ /** 완료된 입법예고의 특정 페이지 목록을 반환합니다. */
96
94
  getDonePage(pageIndex: number, pageUnit?: number): Promise<ITableData[]>;
97
95
  private _getAllPagesImpl;
98
96
  /**
99
- * Async generator that yields every page of ongoing notices.
100
- * Respects `IBulkOptions` for rate-limiting and concurrency.
97
+ * 진행 중인 입법예고 전체 페이지를 순차적으로 yield하는 async generator.
98
+ * `IBulkOptions`로 딜레이·동시성·최대 페이지를 조절할 수 있습니다.
101
99
  */
102
100
  getAllPages(query?: Omit<ISearchQuery, 'pageIndex'>, options?: IBulkOptions): AsyncGenerator<ISearchResult>;
103
101
  /**
104
- * Async generator that yields every page of done notices.
105
- * Respects `IBulkOptions` for rate-limiting and concurrency.
102
+ * 완료된 입법예고 전체 페이지를 순차적으로 yield하는 async generator.
103
+ * `IBulkOptions`로 딜레이·동시성·최대 페이지를 조절할 수 있습니다.
106
104
  */
107
105
  getAllDonePages(query?: Omit<ISearchQuery, 'pageIndex'>, options?: IBulkOptions): AsyncGenerator<ISearchResult>;
108
106
  }
107
+ /**
108
+ * 국회현황 코드
109
+ * - 900101: 발의 (위원회 회부 이전 대기 상태 포함)
110
+ * - 900102: 위원회 회부
111
+ * - 900103: 위원회 상정
112
+ * - 900104: 위원회 법안소위
113
+ * - 900105: 위원회 전체회의
114
+ * - 900106: 법사위 심사
115
+ * - 900107: 본회의 심의
116
+ * - 900108: 정부이송
117
+ * - 900109: 공포
118
+ */
119
+ export type NsmProgressStatus = '900101' | '900102' | '900103' | '900104' | '900105' | '900106' | '900107' | '900108' | '900109';
120
+ /**
121
+ * 발의구분 코드
122
+ * - 900201: 정부
123
+ * - 900202: 의원
124
+ * - 900203: 위원장
125
+ */
126
+ export type NsmProposerType = '900201' | '900202' | '900203';
127
+ /**
128
+ * 의결현황 코드
129
+ * - 902911: 수정가결
130
+ * - 902912: 원안가결
131
+ * - 902913: 부결
132
+ * - 902914: 대안반영폐기
133
+ * - 902915: 폐기
134
+ * - 902916: 임기만료폐기
135
+ * - 902917: 철회
136
+ */
137
+ export type NsmResolutionStatus = '902911' | '902912' | '902913' | '902914' | '902915' | '902916' | '902917';
138
+ export interface INsmSearchQuery {
139
+ pageIndex?: number;
140
+ /** 페이지당 건수 (10 | 20 | 50 | 100) */
141
+ pageSize?: number;
142
+ /** 제안대수 시작 (예: "22" → 제22대) */
143
+ sugCd?: string;
144
+ /** 제안대수 끝 */
145
+ endSugCd?: string;
146
+ /** 발의구분 */
147
+ sgtCls?: NsmProposerType;
148
+ /** 소관부처 코드 */
149
+ cptOfiOrgCd?: string;
150
+ /** 국회현황 */
151
+ rslRsltNmL?: NsmProgressStatus;
152
+ /** 의결현황 */
153
+ rslRsltNmR?: NsmResolutionStatus;
154
+ /** 상임위 (예: "법제사법위원회") */
155
+ scCptPpostCmt?: string;
156
+ /** 제안일자 시작 (YYYY-MM-DD) */
157
+ searchStDtNew?: string;
158
+ /** 제안일자 종료 (YYYY-MM-DD) */
159
+ searchEdDtNew?: string;
160
+ /** 제안자 */
161
+ scPpsUsr?: string;
162
+ /** 규제 신설·강화 해당 여지 법안만 조회 */
163
+ issLawitmYn?: 'Y';
164
+ /** 추진일자 시작 (YYYY-MM-DD) */
165
+ stDt?: string;
166
+ /** 추진일자 종료 (YYYY-MM-DD) */
167
+ edDt?: string;
168
+ /** 의안번호 또는 의안명 */
169
+ scBlNmSct?: string;
170
+ sortCol?: string;
171
+ sortOrder?: 'DESC' | 'ASC';
172
+ }
173
+ export declare class NsmLmSts extends ScreenshotBase {
174
+ private readonly httpClient;
175
+ private readonly parser;
176
+ constructor(config?: PalCrawlConfig);
177
+ private buildListUrl;
178
+ /** 목록 페이지 HTML 반환 */
179
+ getListHTML(query?: INsmSearchQuery): Promise<string>;
180
+ /** HTML에서 법안 목록 검색 결과를 파싱하여 반환합니다. */
181
+ parseList(html: string): INsmSearchResult;
182
+ /** HTML에서 법안 상세 정보를 파싱하여 반환합니다. */
183
+ parseDetail(html: string): INsmBillDetail;
184
+ /** 목록 검색 (필터 지원) */
185
+ search(query?: INsmSearchQuery): Promise<INsmSearchResult>;
186
+ /**
187
+ * 위원회 회부 이전 발의 상태인 법안만 조회 (rslRsltNmL=900101 고정).
188
+ * 소관부처·제안대수·날짜 등 나머지 필터는 그대로 적용됩니다.
189
+ */
190
+ searchPending(query?: Omit<INsmSearchQuery, 'rslRsltNmL'>): Promise<INsmSearchResult>;
191
+ /** 상세 페이지 HTML 반환 */
192
+ getDetailHTML(billNo: string): Promise<string>;
193
+ /** 법안 상세 정보 조회 */
194
+ getDetail(billNo: string): Promise<INsmBillDetail>;
195
+ /** 특정 페이지의 법안 목록 조회 */
196
+ getPage(pageIndex: number, query?: Omit<INsmSearchQuery, 'pageIndex'>): Promise<INsmBillItem[]>;
197
+ private _getAllPagesImpl;
198
+ /**
199
+ * 전체 페이지를 순차적으로 yield하는 async generator.
200
+ * `IBulkOptions`로 딜레이·동시성·최대 페이지를 조절할 수 있습니다.
201
+ */
202
+ getAllPages(query?: Omit<INsmSearchQuery, 'pageIndex'>, options?: IBulkOptions): AsyncGenerator<INsmSearchResult>;
203
+ /**
204
+ * 발의 상태(위원회 회부 전) 법안 전체를 페이지 단위로 yield합니다.
205
+ */
206
+ getAllPendingPages(query?: Omit<INsmSearchQuery, 'pageIndex' | 'rslRsltNmL'>, options?: IBulkOptions): AsyncGenerator<INsmSearchResult>;
207
+ /** 국회입법현황 목록 페이지 스크린샷 */
208
+ getNsmListScreenshot(query?: Omit<INsmSearchQuery, 'pageIndex'>): Promise<Buffer>;
209
+ /** 법안 상세 페이지 스크린샷 */
210
+ getDetailScreenshot(billNo: string): Promise<Buffer>;
211
+ }