run(); class SearchConsole { private $_selfURI; private $_outputPath = 'output/'; private $_gc; private $_gsw; private $_error = array(); function __construct() { // 古いファイルは消す $this->garbageCollection(); // ログアウト処理。セッションに記録したアクセストークンを破棄することで再度認証画面へ if (isset($_GET['logout'])) { $_SESSION = array(); } $this->_selfURI = 'http://' . $_SERVER['HTTP_HOST'] . preg_replace('/\?.*/', '', $_SERVER['REQUEST_URI']); $this->_gc = new Google_Client(); } public function run() { // client_id.jsonを使用 if (file_exists('client_id.json')) { $this->_gc->setAuthConfigFile('client_id.json'); $this->_gc->setRedirectUri($this->_selfURI); $this->_gc->addScope(Google_Service_Webmasters::WEBMASTERS_READONLY); // 認証しているか確認 if (!$this->checkCode() && !$this->checkToken()) { $this->redirectGoogleOAuth(); } else { $this->_gsw = new Google_Service_Webmasters($this->_gc); } } else { $this->setError('client_id.jsonがありません'); } // html出力 $this->getHeader(); if (is_object($this->_gsw)) { // サイトの一覧か結果の一覧 if (empty($_GET['uri'])) { $this->displaySiteList(); } else { $this->displayQueryList(); } } $this->displayErrors(); $this->getFooter(); } public function checkToken() { if (isset($_SESSION['access_token'])) { $this->_gc->setAccessToken($_SESSION['access_token']); if (!$this->_gc->isAccessTokenExpired()) { return true; } } return false; } public function checkCode() { // 認証されcodeがついていた時 if (isset($_GET['code'])) { $ret = $this->_gc->authenticate($_GET['code']); if (!isset($ret['error'])) { $_SESSION['access_token'] = $this->_gc->getAccessToken(); header('HTTP/1.1 301 Moved Permanently'); header('Location: ' . $this->_selfURI); die; } else { // $this->setError($ret['error_description']); $this->redirectGoogleOAuth(); } } return false; } public function redirectGoogleOAuth() { // Googleの認証画面へ header('HTTP/1.1 301 Moved Permanently'); header('Location: ' . $this->_gc->createAuthUrl()); die; } public function setError($str) { $this->_error[] = $str; } private function displayErrors() { echo implode('
', $this->_error); } public function displaySiteList() { $select = null; $html = '
'; // 任意の期間を選択(デフォルトで3日前から1か月。最近のものは取れないため) $end = date('Y-m-d', (strtotime(date('Y-m-d 00:00:00')) - 86400 * 3)); $start = date('Y-m-d', strtotime($end) - 86400 * 30); $html .= '

~

'; $html .= '

Sort:

'; $html .= '
'; echo $html; } public function displayQueryList() { $out = $rows = $csv = array(); $start = $_GET['start']; $end = $_GET['end']; $uri = $_GET['uri']; $limit = 5000; $devices = array('DESKTOP', 'MOBILE', 'TABLET'); $sort = $_GET['sort']; if (isset($_SESSION['access_token'])) { $this->_gc->setAccessToken($_SESSION['access_token']); $this->_gc->setAccessType('offline'); $this->_gc->setApprovalPrompt('force'); $this->_gc->addScope(Google_Service_Webmasters::WEBMASTERS_READONLY); $webmaster = new Google_Service_Webmasters($this->_gc); $query = new Google_Service_Webmasters_SearchAnalyticsQueryRequest; $query->setRowLimit($limit); $query->setDimensions(array('query', 'country', 'device', 'page')); $query->setStartDate($start); $query->setEndDate($end); $query->setSearchType('web'); // 5000件以上あるようなら引き続き取得を試みる $p = 1; do { if ($p >= 2) { $query->setStartRow(5000 * $p + 1); } $res = $webmaster->searchanalytics->query($uri, $query); if (!empty($res)) { if ($sort == 'query') { $head = array('クエリ', '国', 'デバイス', '期間', 'クリック', '表示', 'CTR', '平均順位', 'URI'); foreach ($res as $result) { // クエリ、国、デバイスで分類 $out[$result->keys[0]][$result->keys[1]][$result->keys[2]][] = array( 'clicks' => $result->clicks, // クリック数 'impressions' => $result->impressions, // 表示回数 'ctr' => $result->ctr, // CTR 'position' => round($result->position, 2), // 掲載順位 'page' => $result->keys[3] // URI ); } } elseif ($sort == 'uri') { $head = array('URI', 'クエリ', '国', 'デバイス', '期間', 'クリック', '表示', 'CTR', '平均順位'); foreach ($res as $result) { // URIで分類 $out[$result->keys[3]][$result->keys[0]][$result->keys[1]][$result->keys[2]][] = array( 'clicks' => $result->clicks, // クリック数 'impressions' => $result->impressions, // 表示回数 'ctr' => $result->ctr, // CTR 'position' => round($result->position, 2), // 掲載順位 'page' => $result->keys[3] // URI ); } } } usleep(1000000); $p++; } while (count($res) !== 0); // 出力用に整形 if ($sort == 'query') { foreach ($out as $query => $val) { $queryExists = false; foreach ($val as $country => $v) { foreach ($devices as $device) { if (isset($val[$country][$device])) { $before = null; foreach ($v[$device] as $data) { if (isset($before) && $before['clicks'] == $data['clicks'] && $before['impressions'] == $data['impressions'] && $before['ctr'] == $data['ctr'] && $before['position'] == $data['position'] && $before['page'] == $data['page'] ) { continue; } if ($queryExists) { $query = null; } $queryExists = true; $rows[] = array( $query, $country, $device, $start . '~' . $end, $data['clicks'], $data['impressions'], $data['ctr'], $data['position'], $data['page'], ); $before = $data; } } } } } } elseif ($sort == 'uri') { ksort($out); foreach ($out as $uri => $v) { $uriExists = false; ksort($v); foreach ($v as $query => $val) { foreach ($val as $country => $v) { foreach ($devices as $device) { if (isset($val[$country][$device])) { $before = null; foreach ($v[$device] as $data) { if (isset($before) && $before['clicks'] == $data['clicks'] && $before['impressions'] == $data['impressions'] && $before['ctr'] == $data['ctr'] && $before['position'] == $data['position'] ) { continue; } if ($uriExists) { $uri= null; } $uriExists = true; $rows[] = array( $uri, $query, $country, $device, $start . '~' . $end, $data['clicks'], $data['impressions'], $data['ctr'], $data['position'], ); $before = $data; } } } } } } } if (!empty($rows)) { // csvに書き出す $csv[] = $head; $csv = array_merge($csv, $rows); $dt = date('YmdHis'); file_put_contents($this->_outputPath . $dt . '.csv', $this->array2csv($csv)); // htmlを書き出す echo '

' . $uri . '

'; echo '

csv download

'; echo ''; foreach ($head as $h) { echo ''; } echo ''; foreach ($rows as $k => $row) { echo ''; foreach ($row as $c) { echo ''; } echo ''; } echo '
' . $h . '
' . htmlentities($c, ENT_QUOTES) . '
'; } else { echo '

結果がありませんでした

'; } } } public function getHeader() { echo '

Logout

'; } public function getFooter() { echo ''; } public function garbageCollection() { if (file_exists($this->_outputPath)) { $files = glob($this->_outputPath . '*'); foreach ($files as $file) { if (time() - 86400 > filemtime($file)) { unlink($file); } } } else { mkdir($this->_outputPath); } } public function array2csv($array, $outputPath = null, $outputEncoding = 'sjis-win') { $string = null; if (!empty($array) && is_array($array)) { foreach ($array as $val) { $line = null; if (!is_array($val)) { $val = array($val); } if (!count($val)) { $line[] = ''; } foreach ($val as $v) { $v = strtr($v, array('"' => '""')); if (preg_match("/(\r|\n|\"|'|,)/", $v)) { $line[] = '"' . $v . '"'; } else { $line[] = $v; } } $string .= implode(',', $line) . "\r\n"; } } if (isset($string)) { if (isset($outputEncoding)) { $string = mb_convert_encoding($string, $outputEncoding, 'utf-8'); } if (isset($outputPath)) { file_put_contents($outputPath, $string); } else { return $string; } } else { return false; } } }