记住用户名密码
我们先说一下一个完整的爬虫步骤。
爬虫步骤分为2个阶段:
1:根据初始页面,获取更多的待爬取页面
2:根据页面,获取到自己想要的东西
当我们填入一个初始页面时,我们需要通过某一个特定的逻辑,进行获取更多的页面
例如:
爬取百度页面,我们可以通过页码按钮,获取更多页面的html源码:
爬取知乎用户,我们可以通过该用户的关注者,和粉丝爬取更多用户界面:
获取到了页面html代码之后,我们就可以根据相应的规则,获取到自己想要的东西了。
这里我推荐http://www.querylist.cc/ 可使用jq的语法选择html页面的元素,非常好用
我们现在已经知道了整个爬虫的步骤了,下一步是如何运行这个代码。
在上一步我们可以看出,一个页面,可能有多个待爬取页面,如果我们每次都是取一个页面,然后分析结果,然后再取一个页面,分析结果
这样会造成代码逻辑的难以掌控。
例如:
1:分析页面1,假设页面1有5个待爬取页面链接
2:分析页面1结果,存储
3:分析页面1的第一个结果待爬取页面2,页面2有5个待爬取页面链接
4:分析页面2的结果,存储
5:分析页面1的第二个待爬取页面3,页面3有5个待爬取页面链接。。。。。。
。。。。
这样会造成代码的难以控制,不好维护待爬取页面,我们可以使用队列的形式进行处理
1:初始页面存入分析队列
2:分析初始页面1,获取5个待爬取页面链接,存入分析队列
3:分析页面1的结果,存入结果队列
4:分析队列出列页面2,获取5个待爬取页面链接,存入分析队列
5:分析页面2的结果,存入结果队列
使用队列的情况下,逻辑将会非常的清晰,只需要每次将分析的页面出入队列,然后取出继续分析即可
同样,结果队列只需要新增一个结果消费进程,进行处理结果数据即可
本人已经写好了基础的爬虫框架,基于easyswoole,使用redis队列进行消费。
github地址:https://github.com/tioncico/ESSpider
首先进行composer安装
1
|
composer up |
复制produce.php命名为dev.php,增加redis配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?php /** * Created by PhpStorm. * User: yf * Date: 2019-01-01 * Time: 20:06 */
return [ 'SERVER_NAME' => "EasySwoole" , 'MAIN_SERVER' => [ 'LISTEN_ADDRESS' => '0.0.0.0' , 'PORT' => 9501, 'SERVER_TYPE' => EASYSWOOLE_WEB_SERVER, //可选为 EASYSWOOLE_SERVER EASYSWOOLE_WEB_SERVER EASYSWOOLE_WEB_SOCKET_SERVER,EASYSWOOLE_REDIS_SERVER 'SOCK_TYPE' => SWOOLE_TCP, 'RUN_MODEL' => SWOOLE_PROCESS, 'SETTING' => [ 'worker_num' => 8, 'task_worker_num' => 8, 'reload_async' => true, 'task_enable_coroutine' => true, 'max_wait_time' => 3 ], ], 'TEMP_DIR' => null, 'LOG_DIR' => null, /*################ REDIS CONFIG ##################*/ 'REDIS' => [ 'host' => '127.0.0.1' , 'port' => '6379' , 'auth' => '' , 'serialize' =>true ], ]; |
本身自带了某网站的爬取逻辑,直接运行即可看到:
1
|
php easyswoole start |
现在我们说下如何爬取其他网站的步骤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php
namespace App\Spider;
use EasySwoole\Utility\File; use QL\QueryList;
/** * Created by PhpStorm. * User: tioncico * Date: 19-6-16 * Time: 上午9:53 */ class Event {
static function consume( $data , $html ) { }
static function produce( $data , $html ) { } } |
首先,我们要确定,我们的初始页面是http://moe.005.tv/moeimg/,然后我们可以根据下一页按钮获取更多的页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static function produce( $data , $html ) { //获得一个queryList对象,并且防止报错 libxml_use_internal_errors(true); @ $ql = QueryList::html( $html );
//查询下一页链接,用于继续爬取数据 $nextLink = $ql ->find( '.pagelist .n' )->attr( 'href' ); RedisLogic::addProduce( $nextLink );
//查询所有需要爬取的数据,用于爬取里面的图片 $imgConsumeList = $ql ->find( '.zhuti_w_list li a' )->attrs( 'href' )->all(); foreach ( $imgConsumeList as $value ) { RedisLogic::addConsume([ 'type' => 1, //消费标识 'url' => $value , ]); } return true; } |
现在我们需要点击一个图片进入,可以发现很多图片,例如:http://moe.005.tv/78243.html
现在,我们编写消费代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
static function consume( $data , $html ) { //获得一个queryList对象,并且防止报错 libxml_use_internal_errors(true); if ( $data [ 'type' ] == 1) { //消费类型为1,则代表还不是下载图片,需要进行二次消费 //查询下一页链接,用于继续爬取数据 @ $ql = QueryList::html( $html ); $nextLink = $ql ->find( '.pagelist .n' )->attr( 'href' ); $nextLink = HttpClientLogic::getTrueUrl( $data [ 'url' ], $nextLink ); if ( $nextLink ) { RedisLogic::addConsume([ 'type' => 1, //消费标识 'url' => $nextLink , ]); } $imgList = $ql ->find( '.content_nr img' )->attrs( 'src' )->all(); // var_dump($img); foreach ( $imgList as $img ) { RedisLogic::addConsume([ 'type' => 2, //消费标识 'url' => $img , ]); } } elseif ( $data [ 'type' ] == 2) { $urlInfo = parse_url ( $data [ 'url' ]); $filePath = EASYSWOOLE_ROOT . '/Temp/' . $urlInfo [ 'host' ] . $urlInfo [ 'path' ]; // var_dump($filePath); File::createFile( $filePath , $html ); // var_dump($data['url']); }
} |
初始页面链接可通过协程调用进行增加:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?php /** * Created by PhpStorm. * User: tioncico * Date: 19-6-16 * Time: 下午5:35 */ include "./vendor/autoload.php" ; \EasySwoole\EasySwoole\Core::getInstance()->initialize(); go( function (){ \App\Spider\RedisLogic::clearConsumeMap(); //清除消费map \App\Spider\RedisLogic::clearProduceMap(); //清除生产map \App\Spider\RedisLogic::clearConsumeList(); //清除消费队列 \App\Spider\RedisLogic::clearProduceList(); //清除生产队列 //新增默认队列 \App\Spider\RedisLogic::addProduce( 'http://moe.005.tv/moeimg/' ); }); |
直接运行
1
|
php easyswoole start |
即可实现爬虫爬取页面
github地址:https://github.com/tioncico/ESSpider
1:可通过EasySwooleEvent.php 文件,进行配置爬取的协程数,不建议太大
2:本爬虫没有做ip池,需要的可自行实现
3:本爬虫框架只适用于学习,请不要用于违法用途
目前有 0 条留言 其中:访客:0 条, 博主:0 条