-
guzzle, phpSpreadsheet 로 스크래핑php 2023. 9. 12. 12:16
1. Guzzle 활용하기
<?php set_time_limit(0); require 'vendor/autoload.php'; use GuzzleHttp\Client; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use GuzzleHttp\Exception\RequestException; // Guzzle 클라이언트를 생성합니다. $client = new Client(); $spreadsheet = new Spreadsheet(); // 완료목록 // '동탄 동물병원' => '%EB%8F%99%ED%83%84+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 126.8946875%3B37.578325', // '동탄 고양이 호텔' => '%EB%8F%99%ED%83%84+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 127.10504700000229%3B37.18412720000249', // '화성 동물병원' => '%ED%99%94%EC%84%B1+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 127.10729150000145%3B37.16654380000182', $targets = [ '화성 고양이 호텔' => '%ED%99%94%EC%84%B1+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 126.83140500000144%3B37.199565000000675', '용인 동물병원' => '%EC%9A%A9%EC%9D%B8+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 127.10729150000094%3B37.16654380000074', '용인 고양이 호텔' => '%EC%9A%A9%EC%9D%B8+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 127.12444809999863%3B37.331904300000474', '오산 동물병원' => '%EC%98%A4%EC%82%B0+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 127.15263529999737%3B37.271100399999256', '오산 고양이 호텔' => '%EC%98%A4%EC%82%B0+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 127.07746199999809%3B37.14988700000025', '군포 동물병원' => '%EA%B5%B0%ED%8F%AC+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 127.06732260000092%3B37.169057900000354', '군포 고양이 호텔' => '%EA%B5%B0%ED%8F%AC+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 126.93533800000279%3B37.36152299999945', '세종 동물병원' => '%EC%84%B8%EC%A2%85+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 126.93498789999842%3B37.383211499998836', '세종 고양이 호텔' => '%EC%84%B8%EC%A2%85+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 127.28943249999855%3B36.4803512', '아산 동물병원' => '%EC%95%84%EC%82%B0+%EB%8F%99%EB%AC%BC%EB%B3%91%EC%9B%90, 127.22461590000336%3B36.503293900001395', '아산 고양이 호텔' => '%EC%95%84%EC%82%B0+%EA%B3%A0%EC%96%91%EC%9D%B4+%ED%98%B8%ED%85%94, 127.06977800000124%3B36.77321300000108', ]; $cartegoryNames = ['name', 'roadAddress', 'tel', 'telDisplay', 'homePage']; foreach ($targets as $key => $value) { $resultLists = []; $pageNumber = 1; $totalCount = 0; $target = explode(', ', $value); // 새로운 시트 생성 $sheet = $spreadsheet->createSheet(); $sheet->setTitle($key); // 시트의 이름을 키 값으로 설정 while (true) { try { // 요청을 보낼 URL을 정의합니다. $url = "https://"; echo "현재 request url = {$url}" . PHP_EOL; // HTTP GET 요청을 보냅니다. $response = $client->request('GET', $url, [ 'headers' => [ 'Accept' => 'application/json, text/plain, */*', 'Accept-Encoding' => 'gzip, deflate, br', 'Accept-Language' => 'ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4', 'Cache-Control' => 'no-cache', 'Expires' => 'Sat, 01 Jan 2000 00:00:00 GMT', 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36', 'Cookie' => 'NNB=; nx_ssl=2; page_uid=', 'Pragma' => 'no-cache', 'Referer' => "https://", 'Sec-Ch-Ua' => '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"', 'Sec-Ch-Ua-Mobile' => '?0', 'Sec-Ch-Ua-Platform' => '"Windows"', 'Sec-Fetch-Dest' => 'empty', 'Sec-Fetch-Mode' => 'cors', 'Sec-Fetch-Site' => 'same-origin', ], ]); // 응답 본문을 문자열로 가져옵니다. $responseBody = (string) $response->getBody(); $jsonData = json_decode($responseBody, true); // 결과를 출력합니다. dump($jsonData); $lists = $jsonData['result']['place']['list']; } catch (RequestException $e) { echo "{$key} HTTP 요청 중 오류 발생: " . $e->getMessage() . PHP_EOL; break; } $totalCount = $jsonData['result']['place']['totalCount']; foreach ($lists as $list) { $resultList = []; foreach ($cartegoryNames as $name) { $resultList[$name] = $list[$name]; } $resultLists[] = $resultList; } if (count($lists) < 20) { break; } $pageNumber++; sleep(60); } // 엑셀 데이터 추가 $row = 2; // 데이터 행 시작 foreach ($resultLists as $resultList) { $col = 'A'; // 열 초기화 (첫 번째 열) $sheet->setCellValue($col . $row, $row - 1); // No. 추가 // 나머지 데이터 추가 foreach ($resultList as $value) { $col++; $sheet->setCellValue($col . $row, $value); } $row++; // 다음 행 } echo "{$key} 완료 / 리스트 총 개수 : {$totalCount}" . PHP_EOL; dump($resultLists); // Excel 파일로 저장 $writer = new Xlsx($spreadsheet); $writer->save("exceldata/{$key}.xlsx"); sleep(15); }
Guzzle의 Client() 기능을 생성하고
$response = $client->request('GET', $url, [ 'headers' => [ ], ]);
request를 할 수 있다. 이 때 headers에 넣을 데이터는
request headers 를 복사해서
PostMan의 Bulk Edit을 활용해서 필요한 헤더 데이터를 찾도록 하자
$responseBody = (string) $response->getBody(); $jsonData = json_decode($responseBody, true);
받아온 $response는 처음에 객체 형태이기 때문에 getBody() 메서드로 내용을 가져오고, (string) 형태로 선언해준 다음 json으로 변경해서 사용할 수 있다.
2. phpSpreadsheet
json형태의 데이터로 잘 만들었다면, 눈으로 확인하기 쉽게 엑셀에 담아서 보관할 수 있다
php8.1 버전에서 phpSpreadsheet 를 활용해서 excel파일을 읽고, 쓰는 방법을 알아보자
(버전에 따라 지원하는 excel 편집 라이브러리가 다르다)
<?php // PhpSpreadsheet 라이브러리를 로드합니다. require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; // Excel 파일을 로드합니다. $spreadsheet = IOFactory::load('exceldata/unique.xlsx'); // 모든 워크시트를 가져옵니다. $worksheets = $spreadsheet->getAllSheets(); foreach ($worksheets as $worksheet) { // 워크시트를 선택합니다. $worksheetTitle = $worksheet->getTitle(); // G 열 데이터를 기준으로 행을 그룹화합니다. $groupedRows = []; foreach ($worksheet->getRowIterator() as $row) { $cellG = $worksheet->getCell('F' . $row->getRowIndex()); $groupKey = $cellG->getValue(); if (!isset($groupedRows[$groupKey])) { $groupedRows[$groupKey] = []; } $rowData = $worksheet->rangeToArray("B{$row->getRowIndex()}:F{$row->getRowIndex()}")[0]; $groupedRows[$groupKey][] = $rowData; } dump($groupedRows); // 각 그룹마다 새로운 Excel 파일을 생성하고 데이터를 추가합니다. foreach ($groupedRows as $groupKey => $groupedRowData) { $newSpreadsheet = new Spreadsheet(); $newWorksheet = $newSpreadsheet->getActiveSheet(); $headerRow = ['Name', 'Address', 'Phone', 'Homepage', 'SearchKeyWord']; $newWorksheet->fromArray([$headerRow], null, 'A1'); $newWorksheet->fromArray($groupedRowData, null, 'A2'); // 데이터를 워크시트에 추가 // 새로운 Excel 파일로 저장합니다. $outputFileName = 'exceldata/'. $groupKey . '.xlsx'; $writer = IOFactory::createWriter($newSpreadsheet, 'Xlsx'); $writer->save($outputFileName); } }
위의 코드는 중복 데이터가 삭제 된 excel 파일을 불러와서 특정 열의 값을 비교해서 중복이 발생하는 행을 삭제하고, 특정 열의 값이 같은 요소들 끼리 excel 파일로 나누는 중복 제거 기능을 수행한다.
IOFactory, SpreadSheet를 활용한다.
getRowIterator() 로 워크시트를 행으로 나누고
getRowIndex()로 각 행의 인덱스를 설정한 후, getCell()을 이용해서 워크시트에 존재하는 모든 F열 값을 cellG에 저장한다.
$groupedRows 배열에 groupKey값과 배열을 선언해주고
원하는 범위의 엑셀 데이터를 배열에 넣어주고
Spreadsheet의 기능들로 스프레드 시트를 제작한 뒤IOFactory로 엑셀 파일을 생성하자.
'php' 카테고리의 다른 글
정규 표현식 (0) 2023.09.13 CI 프레임워크 활용 (주가스크래퍼) (0) 2023.09.12 http 헤더 추가하기 (0) 2023.09.08 MATCH 문 (0) 2023.09.07 Class .. Static (0) 2023.09.06