PHP에서도 동적 사이트를 스크래핑하고 싶은 밤
시작하기
이것은 지즈 아카데미 Advent Calendar 2020 기사입니다!
서장 - 난 스크래핑 할거야, PHP에서. -
대체로 스크래핑이라고 하면, 시세는 python
라고 정해져 있습니다.
하지만 평소 PHP를 만지고 있는 나는 PHP로 스크래핑하고 싶습니다.
그래서 PHP로 스크래핑이라고 하면 대체로 phpQuery
라는 것이 언급되기 쉽습니다.
확실히, jQuery처럼 조작할 수 있으므로 간단합니다.
하지만, 이것 동적 사이트에는 잘 이용할 수 없네요.
그래서 다른 방법이 필요합니다.
이번 대상.
모 해외 쇼핑 사이트 (일단 이름은 덮을 수 있습니다.)
다음과 같이
1. 검색
2. 일람표시(일부만)
3. 아래로 스크롤하면 스크롤한 만큼 정보를 취득한다
라는 움직임입니다.
첫째, 모든 정보가 검색되어 나열되면 phpQuery에서도 사용할 수 있습니다.
이것이라면 할 수 없습니다.
해결 방법
다음 도구를 사용하여 이동합니다.
대체로 스크래핑이라고 하면, 시세는
python
라고 정해져 있습니다.하지만 평소 PHP를 만지고 있는 나는 PHP로 스크래핑하고 싶습니다.
그래서 PHP로 스크래핑이라고 하면 대체로
phpQuery
라는 것이 언급되기 쉽습니다.확실히, jQuery처럼 조작할 수 있으므로 간단합니다.
하지만, 이것 동적 사이트에는 잘 이용할 수 없네요.
그래서 다른 방법이 필요합니다.
이번 대상.
모 해외 쇼핑 사이트 (일단 이름은 덮을 수 있습니다.)
다음과 같이
1. 검색
2. 일람표시(일부만)
3. 아래로 스크롤하면 스크롤한 만큼 정보를 취득한다
라는 움직임입니다.
첫째, 모든 정보가 검색되어 나열되면 phpQuery에서도 사용할 수 있습니다.
이것이라면 할 수 없습니다.
해결 방법
다음 도구를 사용하여 이동합니다.
라는 느낌입니다.
그래서 이번 일의 이미지는
1. selenium 브라우저에서 스크래핑하려는 사이트에 액세스합니다.
2. 정보를 취득하고 싶은 페이지로 가서, 일단 맨 아래로 스크롤시킨다(스크롤하면, 전부의 정보가 표시되고 있다)
3. 맨 아래로 스크롤했다 = 스크래핑하고 싶은 정보가 모두 표시되어 있기 때문에 그것을 스크래핑! ! ! !
무슨 해킹!
도구 준비
이번 작업 디렉토리로 이동
$ mkdir selenium
$ cd selenium
selenium-server-standalone 설치.
homebrew
를 이용.brew install selenium-server-standalone
Selenium Google 크롬 드라이버 다운로드
링크
어쩌면 여기 있을지도 ↓
다운로드가 끝나면 selenium 디렉토리에 묻는다.
facebook-webdriver 다운로드
$ php composer.phar require facebook/webdriver
만약,
Could not open input file: composer.phar
라든지의 경우는, 이하의 참고가 될지도.서버 시작
$ selenium-server -port 4444 &
$ selenium-server -port 4444 &
[1] 33415
C02SY1XFGTFJ:selenium username$ 18:04:14.512 INFO [GridLauncherV3.launch] - Selenium build info: version: '3.11.0', revision: 'e59cfb3'
18:04:14.513 INFO [GridLauncherV3$1.launch] - Launching a standalone Selenium Server on port 4444
2018-05-24 18:04:14.624:INFO::main: Logging initialized @441ms to org.seleniumhq.jetty9.util.log.StdErrLog
18:04:14.882 INFO [SeleniumServer.boot] - Welcome to Selenium for Workgroups....
18:04:14.882 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
그래서, 아래와 같이되면
$ jobs
[1]+ Running selenium-server -port 4444 &
PHP 파일 준비
시험에,
test.php
를 준비.<?php
require './vendor/autoload.php';
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;
// 今回の買い物サイト用に準備する変数。
// 検索したいワードを$wordに入れる。この例だとamazonと検索した場合
$word = 'amazon';
$title = " ********** "; // ここはhtmlのtitleに表示される文言を記述。そのサイトによって異なるので、一旦ブラウザでアクセスして確認してください。
// chrome利用用意
$options = new ChromeOptions();
// headlessモードで対応
$options->addArguments(['--headless']);
// ブラウザのサイズを指定
$options->addArguments(["window-size=1024,2048"]);
$host = 'http://localhost:4444/wd/hub';
$capabilities = Facebook\WebDriver\Remote\DesiredCapabilities::chrome();
$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);
$driver = Facebook\WebDriver\Remote\RemoteWebDriver::create($host, $capabilities);
//スクレイピングしたいアドレスを入力
$driver->get('https://www.******/');
$browserLogs = $driver->manage()->getLog('browser');
// 検索したい語をsendKeys()に入れて、submitする。ここの'q'はサイトによって異なる。
$element = $driver->findElement(WebDriverBy::name('q'));
$element->sendKeys($word);
$element->submit();
// このサイトでは、商品画像を全部表示するため、画面を少し右に移動。場合によっては不要。Y軸を動かしたい場合は、第2引数の数字を変える。
$driver->executeScript("window.scrollTo(300, 0);");
$driver->wait(15)->until(
WebDriverExpectedCondition::titleIs($title)
);
// もし、$title(htmlの<title>が想定どおりじゃない)がなければ、なにかした失敗していると判断
if ($driver->getTitle() !== "$title") {
throw new Exception('fail');
}
// 以下取得したい要素を指定してあげる。
// 今回は、検索結果のURL、写真、名前を取得したいので以下の用になっている。
// cssSelectorはサイトに寄って異なる。cssSelectorの中身を変えてね。
$itemUrls = $driver->findElements(WebDriverBy::cssSelector('div.c2iYAv > div.cRjKsc > a'));
$photos = $driver->findElements(WebDriverBy::cssSelector('.c5TXIP .c2iYAv .cRjKsc .c1ZEkM'));
$productNames = $driver->findElements(WebDriverBy::cssSelector('.c5TXIP .c3KeDq .c16H9d'));
$items = [];
// 商品あるかチェック
if (count($photos) < 0) {
throw new Exception('no item.');
}
//。今回は上から10件だけ取得して、情報を$item配列に格納する。
foreach ($itemUrls as $k => $v) {
if ($k === 10) {
break;
}
$items[$k]['$itemUrl'] = $v->getAttribute('href');
}
foreach ($photos as $k => $v) {
if ($k === 10) {
break;
}
$items[$k]['photoUrl'] = $v->getAttribute('src');
}
foreach ($productNames as $k => $v) {
if ($k === 10) {
break;
}
$items[$k]['titleName'] = $v->getText();
}
print_r($items);
echo "\n";
// ↓コメントアウト外せば、どこをスクレイピングしているかとスクリーンショットで確認できる↓
// $file = "sumple_chrome.png";
// $driver->takeScreenshot($file);
$driver->close();
※selenium-webdriver의 사용법은 이쪽.
링크
걸면,
$ php test.php
에서 실행.좋은 느낌이 들었습니다.
끝나면 kill한다.
$ jobs
[1]+ Running selenium-server -port 4444 & (wd: ~/selenium)
$ kill %1
$ jobs
[1]+ Exit 143 selenium-server -port 4444 (wd: ~/selenium)
요약
PHP에서도 동적 사이트를 스크래핑 할 수 있어요!
Reference
이 문제에 관하여(PHP에서도 동적 사이트를 스크래핑하고 싶은 밤), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/masuraoProg/items/0d863f18e862fdc41fa8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)