_mySocket === null) { $this->_mySocket = new MySocketLibrary(getenv('yamap.host.url')); } return $this->_mySocket; } final protected function getMyStorage(): mixed { if ($this->_myStorage === null) { $this->_myStorage = new MyStorageLibrary(getenv('yamap.storage.upload.path')); $this->_myStorage->setBoardName($this->getBoardName()); $this->_myStorage->setBoardTable($this->getBoardModel()->getTable()); $this->_myStorage->setUserEntity($this->getUserEntity()); } return $this->_myStorage; } public function getBoardModel(): BoardModel { if ($this->_board_model === null) { $this->_board_model = new BoardModel("mb_" . $this->getBoardName()); } return $this->_board_model; } public function getUserEntity(): UserEntity { if ($this->_user_entity === null) { throw new \Exception("사용자정보가 없습니다."); } return $this->_user_entity; } public function setUserEntity(UserEntity $_user_entity): void { $this->_user_entity = $_user_entity; } public function getBoardName(): string { if ($this->_board_name === null) { $this->_board_name = getenv('yamap.storage.board.name'); } return $this->_board_name; } public function getBoardLevel(): int { if ($this->_board_level === null) { $this->_board_level = getenv('yamap.storage.board.level'); } return intval($this->_board_level); } private function createBoard(array $listInfo): BoardEntity { //미디어관련정보 entity에 넣기 $formDatas = []; $formDatas['title'] = $listInfo["title"]; $formDatas['user_pid'] = $this->getUserEntity()->getPK(); $formDatas['user_id'] = $this->getUserEntity()->getID(); $formDatas['user_name'] = $listInfo["nickname"] != "" ? $listInfo["nickname"] : $this->getUserEntity()->getTitle(); $formDatas['level'] = $this->getBoardLevel(); $formDatas['hit'] = $listInfo['hit']; $formDatas['reg_date'] = date("Y-m-d H:i:s", strtotime($listInfo['date'])); $formDatas['data_type'] = "html"; $formDatas['editor_type'] = "S"; $formDatas['image_path'] = ""; $formDatas['content'] = ""; //망보드 게시판에 등록 $entity = $this->getBoardModel()->create($formDatas); log_message("notice", message: __FUNCTION__ . " 작업 완료"); return $entity; } private function modifyBoard(BoardEntity $entity) { $content = implode("\n", $this->_media_tags["content"]); if ($content !== "") { $formDatas = [ "image_path" => array_shift($this->_media_tags["image_path"]), "content" => $content ]; $this->getBoardModel()->modify($entity, $formDatas); log_message("notice", __FUNCTION__ . " 작업 완료"); } else { $this->getBoardModel()->delete([$this->getBoardModel()->getPKField() => $entity->getPK()]); log_message(level: "warning", message: __FUNCTION__ . "내용이 없어 삭제처리 : {$entity->getPK()}=>{$entity->getTitle()}"); } } private function mainPage(string $url): array { $listInfos = []; $response = $this->getMySocket()->getResponse($url); $selector = $this->getSelector($response, getenv("yamap.list.tag")); //div.bbs_item를 가진 객체를 찾아서 같은 형식의 객체(sibling)를 배열로 넘김 // log_message("debug", sprintf("\n-------------MainPage------------\n%s\n--------------------------\n", $selector->html())); $selector->filter(getenv("yamap.list.item.tag"))->each( function (Crawler $node) use (&$listInfos): void { //bbs_item에서 span.g_nickname 객체를 찾아서 작성자가 "관리자" 아닌지 확인 후 Return Bool $nickname = $node->filter(getenv("yamap.list.item.nickname.tag"))->text(); $hit = $node->filter(getenv("yamap.list.item.hit.tag"))->text(); $date = $node->filter(getenv("yamap.list.item.date.tag"))->text(); if ($nickname != getenv("yamap.list.item.nickname.except")) { //작성자가 "관리자"가 아니 게시물이면 해당 bbs_item에서 a.list_subject 객체를 찾아서 $link_node = $node->filter(getenv("yamap.list.item.link.tag")); $detail_url = $link_node->attr("href"); $title = $link_node->children()->last()->text(); $listInfos[] = ['title' => $title, 'nickname' => $nickname, 'detail_url' => $detail_url, 'date' => $date, 'hit' => $hit]; } } ); if (!count($listInfos)) { throw new \Exception("Target URL이 없습니다."); } log_message("notice", __FUNCTION__ . " 작업 완료"); return $listInfos; } protected function save(string $url, string $mediaType, int $file_sequence): mixed { $myStorageLibrary = parent::save($url, $mediaType, $file_sequence); $content = ""; //Board 게시판 image_path , content용 데이터 배열에 추가 후 modifyBoard에서 처리 switch ($this->getMyStorage()->getOrintginType()) { case "image": $content = sprintf( "\"%s\"", getenv("mangboard.uloads.url"), $this->getMyStorage()->getPath(), $this->getMyStorage()->getOriginName(), $this->getMyStorage()->getOriginName() ); break; case "video": $content = sprintf( "", $this->getMyStorage()->getOriginName(), getenv("mangboard.uloads.url"), $this->getMyStorage()->getPath(), $this->getMyStorage()->getOriginName(), $this->getMyStorage()->getMimeType(), ); break; } log_message("debug", sprintf( "\n--------%s--------\n%s\n--------------------\n", __FUNCTION__, $content )); if ($content === "") { throw new \Exception(__FUNCTION__ . " Content의 내용없음"); } $this->_media_tags["image_path"][] = sprintf("%s/%s", $this->getMyStorage()->getPath(), $this->getMyStorage()->getOriginName()); $this->_media_tags["content"][] = $content; return $myStorageLibrary; } private function detailPage(array $listInfo): void { //1. Yamap ViewPage의 이미지나영상데이터가 있으면 $response = $this->getMySocket()->getResponse($listInfo['detail_url']); //1.망보드 일반게시판에 게시물 생성 처리 $board_entity = $this->createBoard($listInfo); $this->getMyStorage()->setBoardEntity($board_entity); $this->_media_tags = ["image_path" => [], "content" => []]; $selector = $this->getSelector($response, getenv("yamap.view.content.tag")); //3. Image 처리 log_message("debug", sprintf("\n-------------DetailPage------------\n%s\n--------------------------\n", $selector->html())); $myStorageLibrarys = $this->download("image", $selector, ["tag" => "img", "attr" => "src"]); //4. Video(mp4) 처리 $myStorageLibrarys = $this->download("video", $selector, ["tag" => "video", "attr" => "src"], $myStorageLibrarys); //5.망보드 일반게시판에 게시물 수정 처리 $this->modifyBoard($board_entity); log_message("notice", __FUNCTION__ . " 작업 완료"); } public function execute(): void { if ($this->getDebug()) { $listInfos = [ 'title' => getenv("yamap.view.test.title"), 'nickname' => getenv("yamap.view.test.nickname"), 'detail_url' => getenv("yamap.view.test.url"), 'time' => date("Y-m-d H:i:s"), 'hit' => 1, ]; } else { $listInfos = $this->mainPage(getenv("yamap.list.url")); } //Limit가 0이면 $listInfos 갯수만큼 다하고, LIMIT 갯수 혹은 item의 갯수중 작은수만큼 한다. $max_limit = intval(getenv("yamap.list.max_limit")); if ($max_limit) { $max_limit = count($listInfos) <= $max_limit ? count($listInfos) : $max_limit; } else { $max_limit = count($listInfos); } $i = 1; foreach ($listInfos as $listInfo) { if ($i <= $max_limit) { try { log_message("notice", "게시물 {$i}번째 {$listInfo["nickname"]} 작업시작"); $this->detailPage($listInfo); log_message("notice", "게시물 {$i}번째 {$listInfo["nickname"]} 작업완료."); $i++; } catch (\Exception $e) { log_message("debug", $e->getMessage()); } } } log_message("notice", "Crawler->" . __FUNCTION__ . " 작업이 완료되었습니다."); } }