php Swoole多线程爬虫 八

157 阅读1分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

课程背景

  • 我作为一个PHP工程师 虽然这几年PHP没落了
  • 但我还是有责任补充一些PHP方面的高级教程
  • 掘金粑粑开始更文奖励了 不能白白拿人家的奖励
  • 应该发表一些高层次的PHP的技术文章 别让PHP倒了

正文开始

上一章节中因为 splQuery无法在多线程中共享导致无法进行多线程数据的爬取。这一节,我们用Redis的解决方案替代上面的方案。

1 redis多线程生成任务方案

<?php
$worker_num = 20; //线程数
$num = 2822; //总页数
$base_url = "https://toutiao.sanhao.com/news-list.php?u=p%s";

//开启Redis
$to_key = 'sanhao_list';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('admin123');

//生成目标连接
$redis->del($to_key);
for ($i=1; $i <= $num; $i++) { 
    $redis->lpush($to_key,sprintf($base_url,$i));
}

for ($i=0; $i < 10; $i++) { 
    $process = new swoole_process(function($pro) use ($to_key, $redis){
        $url = $redis->rpop($to_key);
        echo $url . PHP_EOL;
    },false);
    $process->start();
}

for ($i=0; $i < 10; $i++) { 
    swoole_process::wait();
}

上面代码中,我们把待完成的任务存到了redis的队列中。执行发现,每个线程都不会操作到相同的数据了,这是我们所期待的结果。

image.png 2 我们通过计算每个线程需要处理的连接请求数量,然后将数量去作为循环条件。 这就相当于我们平时的工作,工作的总量是确定的了。我们把工作量平均分配给几个员工,这样每个员工都去做一份工作,而且还不是重复工作。

    $per_count = ceil($num/$worker_num);
    for ($j=0; $j < $per_count; $j++) { 
        //todo
    }

这样通过计算就算出了任务量。并对任务进行循环即可。

3 循环中添加异常处理

因为之前我们已经完成了爬取部分代码,保证程序健壮。则直接在外层加入 异常捕获的代码即可。