autoload.php beanbun_[PHP] 又是知乎,用 Beanbun 爬取知乎用户

最近看了不少关于爬虫入门的文章,发现其中大部分都是以知乎为爬取对象,因此此次我也以知乎为目标来进行爬取的演示,用到的爬虫框架为 PHP 编写的 Beanbun。php

此次写的内容为爬取知乎的用户,下面就是详细说一下写爬虫的过程了。git

爬取知乎用户的思路比较简单,就是从某个用户开始,先抓取这个用户关注的人和关注他的人,抓取到这些人后,再抓取他们的相关的用户。

如今知乎是可使用游客身份进行浏览的,也省去了注册和登陆这一部分。先随便找个大V吧,由于他们的关注者比较多,我选择的是大名鼎鼎的张公子,张公子的关注者有13万,就是说只爬取他的关注者,咱们都能有13万的用户数据~github

在用户页面中打开chrome浏览器的开发者选项,点击关注者后就能够看到请求地址和数据。chrome

就以这个做为入口开始爬取了~

此处跳过框架的安装和队列的开启,直接上爬虫的代码:

(若是须要跳过的部分,能够看一下文档)数据库

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';

上面是对爬虫的配置,开启5个进程同时爬取,设置爬取间隔为4秒。在爬去前,咱们还要设置一下请求的headers,好让网站认为是人类再浏览他- -。headers的内容从开发者选项中一股脑粘贴进来。json

$beanbun->beforeDownloadPage = function ($beanbun) {

// 在爬取前设置请求的 headers

$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',

];

};

而在请求到数据后,我还须要把他们存到数据库中,由于主要是演示,因此只保存用户的id,name,follower,following这四个数据。api

// 数据库配置

Db::$config['zhihu'] = [

'server' => '127.0.0.1',

'port' => '3306',

'username' => 'xxxx',

'password' => 'xxxx',

'database_name' => 'zhihu',

'charset' => 'utf8',

];

$beanbun->afterDownloadPage = function ($beanbun) {

// 获取的数据为 json,先解析

$data = json_decode($beanbun->page, true);

// 若是没有数据或报错,那多是被屏蔽了。就把地址才从新加回队列

if (isset($data['error']) || !isset($data['data'])) {

$beanbun->queue()->add($beanbun->url);

$beanbun->error();

}

// 若是本次爬取的不是最后一页,就把下一页加入队列

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) {

// 若是关注者或者关注的人小于5个,就不保存了

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,

];

// 把用户的关注者和关注的人列表加入队列

$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);

}

// 把刚刚爬取的地址标记为已经爬取

$beanbun->queue()->queued($beanbun->queue);

};

// 不须要框架来发现新的网址,

$beanbun->discoverUrl = function () {};

$beanbun->start();

接下来在命令行运行爬虫浏览器

$ php zhihu_user.php start

再去看一眼数据库,源源不断的用户数据保存进来了~

在一切顺利的状况下,我又稍微做了一下死,把爬取的间隔减到了2秒,因而在10几分钟以后,我被知乎封掉了....

这种状况比较常见的解决方式就是使用代理,下面就在原有爬虫基础上,增长一个简单的可定时更新的代理池。

先中止爬虫app

$ php zhihu_user.php stop

网上有不少免费代理的网站,我随便选了一个提供免费代理的网站,爬取到代理的数据后,先请求一下163,若是成功的话就加入代理池。

function getProxies($beanbun) {

$client = new \GuzzleHttp\Client();

$beanbun->proxies = [];

$pattern = '/

(.+)(\d+)(.+)(HTTP|HTTPS)
/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) {

// 每隔半小时,更新一下代理池

Beanbun::timer(1800, 'getProxies', $beanbun);

};

再在以前的 beforeDownloadPage 中加入

if (isset($beanbun->proxies) && count($beanbun->proxies)) {

$beanbun->options['proxy'] = $beanbun->proxies[array_rand($beanbun->proxies)];

}

再次启动爬虫,爬虫还会接着以前的队列继续爬取。

$ php zhihu_user.php start

再看看数据库,使用代理可能会比以前慢一些,不过数据又继续增长了。

最终的代码能够在 Github 上查看

例子中的代理池仍是比较简陋的,只是用来讲明框架的灵活,而爬取到数据在这里就不作图表进行分析了,但愿你们关注的也是写爬虫的过程。

最后若是你对这篇文章感兴趣,但愿能到 Github 上给个 star 啦,谢谢~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值