webmagic addTargetRequests 不抓二级页面的问题

最近在做一个信息采集项目,需要用到爬虫,调研了市面上的爬虫框架,最终选择webmagic

首先,有一个需求是这样的,爬虫需要先去抓取列表页的href链接,抓完之后,再把这些链接放到一个队列里,爬虫再从队列里poll出来,再去抓每个链接里的详情内容,也就是addTargetRequests 的逻辑。

但是实际上,爬虫只抓了初始列表的数据,详情页的抓取逻辑没执行,一开始,看了文档,设置setSpawnUrl(true),仍然无效。只能从源码上找问题。
webmagic的启动大概有两种方法,一是调用run方法;二是调用get或者getAll

run 方法,新开一个线程去爬取数据

public void run() {
        checkRunningStat();
        initComponent();
        while (!Thread.currentThread().isInterrupted() && stat.get() == STAT_RUNNING) {
        	//这个scheduler 存储了要爬取的url
            Request poll = scheduler.poll(this);
            if (poll == null) {
                if (threadPool.getThreadAlive() == 0) {
                 
                    poll = scheduler.poll(this);
                    if (poll == null) {
                        if (exitWhenComplete) {
                            break;
                        } else {
                        
                            try {
                                Thread.sleep(emptySleepTime);
                                continue;
                            } catch (InterruptedException e) {
                                break;
                            }
                        }
                    }
                } else {
                  
                    if (waitNewUrl())
                        
                        break;
                    continue;
                }
            }
            final Request request = poll;
      
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                    	//具体执行在这个方法
                        processRequest(request);
                        onSuccess(request);
                    } catch (Exception e) {
                        onError(request, e);
                        
                    } finally {
                        pageCount.incrementAndGet();
                        signalNewUrl();
                    }
                }
            });
        }
        stat.set(STAT_STOPPED);
     
        if (destroyWhenExit) {
            close();
        }
    }

debug可以看到scheduler 只poll了一个request,说明二级页面的链接没加到scheduler 里,继续跟进 #processRequest

private void processRequest(Request request) {
        Page page;
        //这里是选择下载器
        if (null != request.getDownloader()){
            page = request.getDownloader().download(request,this);
        }else {
            page = downloader.download(request, this);
        }
        
        if (page.isDownloadSuccess()){
        //这里对下载好的页面进行处理
            onDownloadSuccess(request, page);
        } else {
            onDownloaderFail(request);
        }
    }

debug可知,page对象里的TargetRequests 是有数据的,说明addTargetRequests 方法执行了,跟进去 #onDownloadSuccess

private void onDownloadSuccess(Request request, Page page) {
        if (site.getAcceptStatCode().contains(page.getStatusCode())){
        	//这里是自定义的processor的处理
            pageProcessor.process(page);
        	//下面pipelines是处理结果了,所以问题应该在这里 
            extractAndAddRequests(page, spawnUrl);
            if (!page.getResultItems().isSkip()) {
                for (Pipeline pipeline : pipelines) {
                    pipeline.process(page.getResultItems(), this);
                }
            }
        } else {
           
        }
        sleep(site.getSleepTime());
        return;
    }

跟进去 #extractAndAddRequests

protected void extractAndAddRequests(Page page, boolean spawnUrl) {
		//
        if (spawnUrl && CollectionUtils.isNotEmpty(page.getTargetRequests())) {
            for (Request request : page.getTargetRequests()) {
                addRequest(request);
            }
        }
    }
    private void addRequest(Request request) {
        if (site.getDomain() == null && request != null && request.getUrl() != null) {
            site.setDomain(UrlUtils.getDomain(request.getUrl()));
        }
        scheduler.push(request, this);
    }

可以看到 #addRequest 实际上就是往 scheduler push request,debug可知,spawnUrl此时是false,导致根本没执行addRequest 方法,所以scheduler里面也就没有二级详情页的链接了

所以,简单的处理就是去掉 extractAndAddRequests 方法里 去掉 spawnUrl==true 的判断

protected void extractAndAddRequests(Page page, boolean spawnUrl) {
        if (CollectionUtils.isNotEmpty(page.getTargetRequests())) {
            for (Request request : page.getTargetRequests()) {
                addRequest(request);
            }
        }
    }

成功爬取页面详情
成功爬取页面

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值