Недавно я прочитал много статей о внедрении обходчиков и обнаружил, что большинство из них основаны на знаниях как объекте обходчика, поэтому на этот раз я также нацелился на знания как демонстрацию обходчика, используя фреймворк обходчика для PHP Beanbun.
Адрес проекта: https://github.com/kiddyuchina/Beanbun
Содержание этой статьи предназначено для обхода осведомленных пользователей, ниже приводится подробное описание процесса написания обходчика.
Идея обхода, чтобы узнать пользователя, относительно проста, то есть, начиная с пользователя, сначала захватите людей, о которых заботится пользователь, и людей, которые заботятся о них, после захвата этих людей, затем захватите их соответствующих пользователей. Теперь я знаю, что могу просматривать страницы как турист, и я также опускаю часть регистрации и входа в систему. Сначала найдите большого V, потому что у них больше подписчиков. Я выбираю знаменитого Чжан Гонцзы. У Чжан Гонцзы 130 000 последователей. То есть, мы можем только ползти по его последователям. У всех нас есть 130 000 пользовательских данных.~
Откройте опцию разработчика браузера Chrome на странице пользователя и нажмите на подписчика, чтобы просмотреть адрес запроса и данные.
Вот тут-то вход и начинает ползти.~ Здесь пропустите установку рамки и открытие очереди и перейдите непосредственно к коду искателя: (Если вам нужно пропустить раздел, вы можете просмотреть документ.)
Выше приведена конфигурация гусеничного движка. Откройте пять процессов и выполните обход одновременно. Установите интервал обхода на 4 секунды. Прежде чем подниматься, нам также нужно настроить заголовки запросов, чтобы веб-сайт мог думать о нем как о человеческом браузере. Содержимое заголовков вставляется в параметры разработчика.
$beanbun->beforeDownloadPage = function ($beanbun) { // Setting the headers of the request before crawling $beanbun->options['headers'] = [ 'Host' => 'www.zhihu.com', 'Connection' => 'keep-alive', 'Cache-Control' => 'max-age=0', 'Upgrade-Insecure-Requests' => '1', 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36', 'Accept' => 'application/json, text/plain, */*', 'Accept-Encoding' => 'gzip, deflate, sdch, br', 'authorization' => 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20', ]; };
После запроса данных мне также нужно сохранить их в базе данных, потому что основная презентация, поэтому только идентификатор пользователя, имя, подписчик, следующие за этими четырьмя данными.
// Database Configuration Db::$config['zhihu'] = [ 'server' => '127.0.0.1', 'port' => '3306', 'username' => 'xxxx', 'password' => 'xxxx', 'database_name' => 'zhihu', 'charset' => 'utf8', ]; $beanbun->afterDownloadPage = function ($beanbun) { // The data obtained is json, parsed first $data = json_decode($beanbun->page, true); // If there is no data or error, it may be blocked. Just add the address back to the queue if (isset($data['error']) || !isset($data['data'])) { $beanbun->queue()->add($beanbun->url); $beanbun->error(); } // If this crawl is not the last page, add the next page to the queue if ($data['paging']['is_end'] == false) { $beanbun->queue()->add($data['paging']['next']); } $insert = []; $date = date('Y-m-d H:i:s'); foreach ($data['data'] as $user) { // If there are less than five followers or followers, they will not be saved. if ($user['follower_count'] < 5 || $user['following_count'] < 5) { continue ; } $insert[] = [ 'id' => $user['id'], 'name' => $user['name'], 'follower' => $user['follower_count'], 'following' => $user['following_count'], 'created_at' => $date, ]; // Queue users'list of followers and followers $beanbun->queue()->add('https://www.zhihu.com/api/v4/members/' . $user['url_token'] . '/followers?include=data%5B*%5D.following_count%2Cfollower_count&limit=20&offset=0'); $beanbun->queue()->add('https://www.zhihu.com/api/v4/members/' . $user['url_token'] . '/followees?include=data%5B*%5D.following_count%2Cfollower_count&limit=20&offset=0'); } } if (count($insert)) { Db::instance('zhihu')->insert('zhihu_user', $insert); } // Mark the address you just crawled as crawled $beanbun->queue()->queued($beanbun->queue); }; // No framework is needed to find new URLs. $beanbun->discoverUrl = function () {}; $beanbun->start();
Затем запустите искатель в командной строке
$ php zhihu_user.php start
Посмотрите на базу данных еще раз, и в ней будет сохранен постоянный поток пользовательских данных.~ Когда все прошло гладко, я немного покончил с собой, сократил интервал обхода до 2 секунд, а через 10 минут меня сознательно заблокировали… Распространенным решением этой проблемы является использование прокси-сервера. Здесь, на основе оригинального искателя, мы добавляем простой пул прокси-серверов, который можно регулярно обновлять. Сначала перестань ползти
$ php zhihu_user.php stop
В Интернете есть много сайтов бесплатных агентов. Я случайным образом выбираю веб-сайт, который предоставляет бесплатный агент. После обхода данных агента я сначала запрашиваю 163, а затем присоединяюсь к пулу агентов, если это удастся.
function getProxies($beanbun) { $client = new \GuzzleHttp\Client(); $beanbun->proxies = []; $pattern = '/(.+)<\/td> (\d+)<\/td>(.+)(HTTP|HTTPS)<\/td> /isU'; for ($i = 1; $i < 5; $i++) { $res = $client->get("http://www.mimiip.com/gngao/$i"); $html = str_replace([' ', "\r", "\n"], '', $res->getBody()); preg_match_all($pattern, $html, $match); foreach ($match[1] as $k => $v) { $proxy = strtolower($match[4][$k]) . "://{$v}:{$match[2][$k]}"; echo "get proxy $proxy "; try { $res = $client->get('http://mail.163.com', [ 'proxy' => $proxy, 'timeout' => 6 ]); echo "success.\n"; } catch (\Exception $e) { echo "error.\n"; } } } } if ($argv[1] == 'start') { getProxies($beanbun); } $beanbun->startWorker = function($beanbun) { // Update the agent pool every half hour Beanbun::timer(1800, 'getProxies', $beanbun); };
Добавьте предыдущую страницу перед загрузкой
if (isset($beanbun->proxies) && count($beanbun->proxies)) { $beanbun->options['proxy'] = $beanbun->proxies[array_rand($beanbun->proxies)]; }
Запустите искатель снова, и искатель продолжит обход в предыдущей очереди.
$ php zhihu_user.php start
Если посмотреть на базу данных, то использование прокси-серверов может быть медленнее, чем раньше, но объем данных продолжает расти. Окончательный код можно посмотреть на Github
Если посмотреть на базу данных, то использование прокси-серверов может быть медленнее, чем раньше, но объем данных продолжает расти. Окончательный код можно посмотреть на Github
Пул прокси в примере все еще относительно прост, просто чтобы проиллюстрировать гибкость фреймворка, и для обхода данных здесь не требуется анализ графиков, я надеюсь, что вас также беспокоит процесс написания обходчиков. Наконец, если вы заинтересованы в этой статье, я надеюсь, что вы сможете получить звезду на Github. Спасибо.~
Пул прокси в примере все еще относительно прост, просто чтобы проиллюстрировать гибкость фреймворка, и для обхода данных здесь не требуется анализ графиков, я надеюсь, что вас также беспокоит процесс написания обходчиков. Наконец, если вы заинтересованы в этой статье, я надеюсь, что вы сможете получить звезду на Github. Спасибо.~