ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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
Designed by Tistory.