Scraper Hub API

채널 코드 flex_notice · 수집 환경 windows

flex(HR) 홈 피드의 회사 공지사항을 게시일 최신순으로 수집합니다. 목록 + 공지마다 상세(전체 본문·첨부 파일 정보·댓글 수·반응 수). 수집 서버의 flex 수집기 앱이 전용 Chrome 프로필로 flex 에 로그인해 두고(세션 7일, 쓸 때마다 연장), 풀리면 앱에 저장된 아이디/비밀번호로 자동 로그인합니다 — 아이디/비밀번호는 API 로 보내지 않습니다. server 를 비우면 허브가 지금 가능한 flex 서버(온라인 · 로그인됨 · 대기 작업 적은 순)를 골라 배정하고, 가능한 서버가 없으면 409 no_flex_server 입니다. 지정한 서버가 오프라인이거나 flex 자동 로그인까지 실패한 상태면 409, flex 수집기가 없는 서버는 422 not_flex_server 입니다.

요청 파라미터

아래 값들을 POST /api/v1/collect 의 params 객체에 담아 보냅니다.

키타입필수기본설명
server text — — 비우면 허브가 지금 flex 수집이 가능한 서버(온라인 · flex 로그인됨 · 대기 작업 적은 순) 중 하나를 골라 배정하고, 응답의 server 로 알려줌. 특정 서버로 보내려면 그 서버 ID(예: win-flex-01, GET /flex-servers 로 조회)
limit number — 100 최신 공지부터 최대 N건(1~1000)
start_date date (YYYY-MM-DD) — — 비우면 전체. 게시일 최신순으로 내려가다 이 날짜 이전 공지를 만나면 종료
collect_body bool — true 공지마다 상세를 열어 전체 본문·첨부 파일 정보·댓글 수를 채움. 끄면 목록의 미리보기(약 100자)만
collect_comments bool — false 상세의 댓글을 extra.comments[] 로(댓글 달린 공지가 없어 구조는 미검증 — raw_keys 로 원래 키 목록을 함께 보냄)
include_rich bool — false 본문 서식 원본(Lexical JSON 문자열)을 extra.content_lexical 로
시작일(start_date) — 증분 수집
최신순으로 훑어 내려가다 start_date 이전 항목을 만나면 수집을 종료합니다(그 날짜 이후만 수집). 비우면 상한(limit)까지 최신순으로 수집합니다.

요청 예시

curl -X POST https://scraper.conbus.co.kr/api/v1/collect \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "channel": "flex_notice", "params": { "limit": 100, "start_date": "2026-06-01", "collect_body": true, "collect_comments": false, "include_rich": false } }'

응답 (202 Accepted)

요청은 즉시 큐에 적재되고 request_id 를 돌려줍니다. 실제 수집은 워커가 비동기로 처리합니다.

{ "success": true, "data": { "request_id": 42, "channel": "flex_notice", "status": "pending", "status_url": "https://scraper.conbus.co.kr/api/v1/requests/42" } }

결과 조회 — GET /requests/{id}

같은 API 키로 request_id 를 조회합니다. 상태에 따라 응답이 달라집니다. 결과(items)는 요청별로 보관되므로 같은 글이 다른 요청(다른 키워드·재수집)에 겹쳐도 이 요청의 결과는 그대로입니다 — 여러 요청에 걸친 중복 정리는 post_id로 호출 쪽에서 하세요. 보존 기간은 완료 후 7일입니다. 이 채널은 '지금 상태'가 중요한 데이터라 짧게 보관합니다 — 결과는 받은 즉시 저장하세요. 보존 기간이 지나면 items 는 빈 배열이고 items_expired: true, items_keep_days 가 함께 옵니다(status 는 그대로 done).

진행 중 (pending / running)

아직 끝나지 않았으면 progress 로 진행 상황만 옵니다(items 없음).

{ "success": true, "data": { "request_id": 42, "channel": "flex_notice", "status": "running", "external_ref": null, "result_count": null, "started_at": "2026-06-16T09:00:05+09:00", "finished_at": null, "duration_ms": null, "duration_sec": null, "created_at": "2026-06-16T09:00:00+09:00", "updated_at": "2026-06-16T09:01:30+09:00", "progress": { "count": 12, "phase": "list" }, "elapsed_ms": 85000 } }

완료 (done)

status 가 done 이면 data.items[] 에 결과가 담깁니다. 실패 시엔 status: "failed" 와 error 가 옵니다.

{ "success": true, "data": { "request_id": 42, "channel": "flex_notice", "status": "done", "external_ref": null, "result_count": 1, "started_at": "2026-06-16T09:00:05+09:00", "finished_at": "2026-06-16T09:02:00+09:00", "duration_ms": 115000, "duration_sec": 115, "created_at": "2026-06-16T09:00:00+09:00", "updated_at": "2026-06-16T09:02:00+09:00", "items": [ { "post_id": "01M2PT66DF24YHJ3D6RGAM9CW9", "url": "https://flex.team/notice?noticeId=01M2PT66DF24YHJ3D6RGAM9CW9", "title": "2026년 연차촉진제도 시행 공지", "author": "인사담당", "posted_at": "2026-07-01T10:00:00+09:00", "views": null, "comment_count": 0, "recommends": 2, "body": "안녕하세요, 구성원 여러분. 원활한 휴가 사용을 위해 올해도 연차촉진제도를 시행합니다 ...", "source": "flex 공지 / 공지사항", "extra": { "kind": "notice", "notice_id": "01M2PT66DF24YHJ3D6RGAM9CW9", "category": "공지사항", "category_id": "01KWCP99F0EP974AG6FTNCJ44T", "writer_id": "Xa1b2C3d4E", "published_at": "2026-07-01T10:00:00+09:00", "created_at": "2026-06-30T17:12:40+09:00", "updated_at": "2026-07-01T09:58:03+09:00", "pinned": false, "preview": "안녕하세요, 구성원 여러분. 원활한 휴가 사용을 위해 ...", "body_full": true, "reaction_count": 2, "attachments": [ { "file_key": "Dw5dryAyZG1tl5k6gQpG9oCrXmJme", "name": "2026 연차촉진제도 공지문서.pdf", "mime_type": "application/pdf", "size": 204578, "scan_status": "MALWARE_NONE" } ], "source_kind": "flex_notice" } } ] } }

실패 (failed)

status 가 failed 면 error 에 사유가 옵니다(items 없음). 일시적 실패는 자동 재시도되며, 위 응답은 마지막 시도 기준입니다.

{ "success": true, "data": { "request_id": 42, "channel": "flex_notice", "status": "failed", "external_ref": null, "result_count": 0, "started_at": "2026-06-16T09:00:05+09:00", "finished_at": "2026-06-16T09:00:16+09:00", "duration_ms": 11000, "duration_sec": 11, "created_at": "2026-06-16T09:00:00+09:00", "updated_at": "2026-06-16T09:00:16+09:00", "error": "flex 로그인 필요 — 자동 로그인 실패 — 아이디 또는 비밀번호가 틀렸습니다 (수집 PC 의 flex 수집기 계정 메뉴에서 확인 후 다시 요청)" } }

최상위 data에는 항상 request_id·channel·status·external_ref·result_count·started_at·finished_at·duration_ms·duration_sec·created_at·updated_at이 포함되고, 상태에 따라 items(done)·progress+elapsed_ms(진행 중)·error(failed/cancelled)가 추가됩니다. duration_*는 허브가 잰 수집 소요 시간(시작~종료) — 자세히는 비동기 & 콜백. 요청을 잘못 시작했다면 취소 API로 중단할 수 있습니다.

결과 필드 (items[])

필드설명
post_id공지 고유 ID(flex 공지 ID, ULID 형식). 재수집 중복 제거 키
urlflex 공지 주소 https://flex.team/notice?noticeId=…(로그인한 구성원만 열람)
title / bodytitle=공지 제목 / body=전체 본문 텍스트(줄바꿈 유지). collect_body=false면 목록의 미리보기(약 100자, extra.body_full=false)
author작성자 표시 이름
posted_at작성 시각 (ISO8601, KST) — 게시 시각(flex 의 publishedFrom, 예약 게시면 공개 시각). posted_at_raw는 원문(UTC)
views / comment_countviews=null(flex 가 조회수를 주지 않음) / comment_count=댓글 수(collect_body=false면 null)
recommends반응(이모지) 수 합계 — collect_body=false면 null
sourceflex 공지 / 분류명
extra.kindnotice
extra.notice_id공지 ID
extra.category / category_id공지 분류
extra.writer_id작성자 사용자 ID
extra.published_at / created_at / updated_at게시·작성·수정 시각(KST)
extra.pinned상단 고정 여부
extra.preview목록 미리보기
extra.body_full본문이 전체(true)인지 미리보기(false)인지
extra.reaction_count반응 수
extra.attachments첨부 파일 정보 배열 [{file_key, name, mime_type, size, scan_status}] — 파일 자체는 오지 않음(아래 참고)
extra.comments댓글 배열 — collect_comments=true일 때만. {comment_id, author, text, date, is_reply, raw_keys}
extra.content_lexical / content_schema서식 원본(JSON 문자열) — include_rich=true일 때만
extra.source_kindflex_notice
채널 참고
  • 수집 서버 자동 선택 — server 는 선택입니다. 비우면 허브가 지금 flex 수집이 가능한 서버(온라인 · flex 로그인됨 · 대기 작업 적은 순) 중 하나를 골라 배정하고 202 응답의 server 로 알려줍니다. 가능한 서버가 없으면 409 no_flex_server(이유 포함). 특정 서버로 보내려면 GET /flex-servers 의 서버 이름을 넣으세요 — 그 서버가 오프라인이면 409 server_offline, flex 로그인이 풀리고 자동 로그인까지 실패한 상태면 409 account_login_required(추가 인증 화면이면 account_blocked), flex 수집기가 없는 서버면 422 not_flex_server. 배정은 요청 시점에 고정되므로 고른 서버가 그 뒤 꺼지면 그 요청은 실패로 끝납니다(다시 요청하면 살아 있는 서버로 갑니다).
  • 수집 PC 가 flex 웹 화면이 쓰는 내부 API 를 로그인 세션으로 불러 가져옵니다(화면 스크래핑이 아님). 공지 48건·상세 포함이 수십 초 안에 끝납니다. flex 가 화면·API 를 바꾸면 failed(재시도 없음) 로 끝나고 오류에 "API 변경 의심" 이 표시됩니다.
  • 첨부 파일은 정보(이름·형식·크기)만 옵니다. flex 의 다운로드 주소는 60초만 유효해서 허브로 넘기지 않습니다 — 파일이 필요하면 수집 PC 앱의 "첨부 파일 내려받기" 설정으로 PC 출력 폴더에 받습니다.
  • 댓글은 2026-09-28 기준 댓글 달린 공지가 없어 실제 구조를 확인하지 못했습니다. 흔한 키 이름으로 채우고 원래 키 목록을 raw_keys 로 함께 보내니, 값이 비어 있으면 알려 주세요.

결과 수신(폴링·콜백) 방식은 비동기 & 콜백을 참고하세요.