Рубрики
Uncategorized

[[PHP] также хорошо осведомлен, используя Bean bun для обхода знающих пользователей

Автор оригинала: David Wong.

Недавно я прочитал много статей о внедрении обходчиков и обнаружил, что большинство из них основаны на знаниях как объекте обходчика, поэтому на этот раз я также нацелился на знания как демонстрацию обходчика, используя фреймворк обходчика для PHP Beanbun.

  • Адрес проекта: https://github.com/kiddyuchina/Beanbun

Содержание этой статьи предназначено для обхода осведомленных пользователей, ниже приводится подробное описание процесса написания обходчика.

Идея обхода, чтобы узнать пользователя, относительно проста, то есть, начиная с пользователя, сначала захватите людей, о которых заботится пользователь, и людей, которые заботятся о них, после захвата этих людей, затем захватите их соответствующих пользователей. Теперь я знаю, что могу просматривать страницы как турист, и я также опускаю часть регистрации и входа в систему. Сначала найдите большого V, потому что у них больше подписчиков. Я выбираю знаменитого Чжан Гонцзы. У Чжан Гонцзы 130 000 последователей. То есть, мы можем только ползти по его последователям. У всех нас есть 130 000 пользовательских данных.~

Откройте опцию разработчика браузера Chrome на странице пользователя и нажмите на подписчика, чтобы просмотреть адрес запроса и данные.

Вот тут-то вход и начинает ползти.~ Здесь пропустите установку рамки и открытие очереди и перейдите непосредственно к коду искателя: (Если вам нужно пропустить раздел, вы можете просмотреть документ.)

php
use Beanbun\Beanbun;
use Beanbun\Lib\Db;
use GuzzleHttp\Client;

require_once(__DIR__ . '/vendor/autoload.php');

$beanbun = new Beanbun;
$beanbun->name = 'zhihu_user';
$beanbun->count = 5;
$beanbun->interval = 4;
$beanbun->seed = 'https://www.zhihu.com/api/v4/members/zhang-jia-wei/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset=0&limit=20';
$beanbun->logFile = __DIR__ . '/zhihu_user_access.log';

Выше приведена конфигурация гусеничного движка. Откройте пять процессов и выполните обход одновременно. Установите интервал обхода на 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. Спасибо.~