基于webmagic框架的多主题爬虫关键词切换

WebMagic爬虫(二)升级版 我在爬取页面的时候发现有很多数据是js渲染进去的,通过: String htm = page.getHtml().xpath("*/html/html()").toString(); page.putField("html",htm); 就可以看到爬取下来的页面数据,可以很清晰的看出页面里面有没有自己想要的数据,如果没有,那么我们就需要进一步操作! 如果数据是ajax请求过来的,那么可以参... 阅读详情

 

1、背景介绍

       多主题爬虫中,我们一般先分析网站的url特点(重点是列表页),再根据项目需求预先设定好关键词,对待爬取url,或者称为种子url进行精准控制。

1.1、分析一

       带关键词的url场景有很多,如网站的特定版块、某模块发送的AJAX请求等都嵌入了关键词。

       eg:我们需要爬取同程旅游网杭州的旅游景点信息,url是:https://so.ly.com/hot?q=%E6%9D%AD%E5%B7%9E;

       其中%E6%9D%AD%E5%B7%9E是Unicode对关键词--“杭州”编码的结果

       eg:同程旅游网从杭州到北京的国内游,url是:

       https://gny.ly.com/list?src=%E6%9D%AD%E5%B7%9E&dest=%E5%8C%97%E4%BA%AC&prop=0,等同于https://gny.ly.com/list?src=杭州&dest=北京&prop=0,实际上也等同于https://gny.ly.com/list?src=杭州&dest=北京。在浏览器输入上述url后会显示该主题列表的第一页,点击下一页我们会发现该主题列表第二页url是:

       https://gny.ly.com/list?src=%E6%9D%AD%E5%B7%9E&dest=%E5%8C%97%E4%BA%AC&start=2

       第三页是:

       https://gny.ly.com/list?src=%E6%9D%AD%E5%B7%9E&dest=%E5%8C%97%E4%BA%AC&start=3

       ····

       https://gny.ly.com/list?src=%E6%9D%AD%E5%B7%9E&dest=%E5%8C%97%E4%BA%AC&start=n

       由此,我们就可以得出该模块的url拼接规则为:https://gny.ly.com/list?src=关键词1(Unicode编码)+“&dest=”+关键词2(Unicode编码)+“&start=”+index(页面索引)

       再比如:百度新闻,关键词搜索url:

       https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&rsv_dl=ns_pc&word=浙江++消防&pn=10

       https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&rsv_dl=ns_pc&word=浙江++消防&pn=20

1.2、分析二

       再进一步抽象,一般我们在配置文件中设定关键词,或者写入数据库中,然后爬虫从中读取并存入kw1List和kw2List中,

       两种方式的配置举例如下:

  • 配置1(yaml文件)
filters:
  searchfilter:
    kwfixvalue: [ 浙江, 江苏, 上海, 北京, 天津 ]
    kwvalue: [ 火灾, 坍塌, 爆炸, 事故, 安全, 伤亡 ]
  • 配置2(数据库)
起始城市ID起始城市名称目的地ID目的地名称
0510无锡0571杭州
001北京021南京
0519常州0996乌鲁木齐

 

       在拼接下一列表页的逻辑中(即换页,列表页切换),我们需要用到的变量是: 当前关键词1、当前关键词2、当前关键词1所处list1中的索引index1、当前关键词2所处list2中的索引index2,以及已爬取到的页面index(即网站所显示的第几页);

2、解决

       经上述分析,将列表页url拼接逻辑中表示关键词的选择切换抽取出来,并用一个pojo类定义,可以命名为KeywordOptions,代码如下:

  • currenyPage: 当前页面索引(表示关键词1+关键词2搜索结果中的第几页)
  • currentFixIndex: 关键词2所在list2中的index
  • kwFixValue: 关键词2
  • currentIndex: 关键词1所在list1中的index
  • kwValue: 关键词1
public class KeywordOptions {
    Long currentPage;
    Integer currentFixIndex;
    String kwFixValue = null;
    Integer currentIndex;
    String kwValue = null;

    public KeywordOptions() {
    }

    public Long getCurrentPage() {
        return this.currentPage;
    }

    public void setCurrentPage(Long currentPage) {
        this.currentPage = currentPage;
    }

    public Integer getCurrentFixIndex() {
        return this.currentFixIndex;
    }

    public void setCurrentFixIndex(Integer currentFixIndex) {
        this.currentFixIndex = currentFixIndex;
    }

    public Integer getCurrentIndex() {
        return this.currentIndex;
    }

    public void setCurrentIndex(Integer currentIndex) {
        this.currentIndex = currentIndex;
    }

    public String getKwFixValue() {
        return this.kwFixValue;
    }

    public void setKwFixValue(String kwFixValue) {
        this.kwFixValue = kwFixValue;
    }

    public String getKwValue() {
        return this.kwValue;
    }

    public void setKwValue(String kwValue) {
        this.kwValue = kwValue;
    }
}

       并基于webmagic框架中的PageProcessor接口编写抽象类BasePageProcessor,在该抽象类中根据通用性业务需求编写相关方法, 首先是关键词切换逻辑:

private boolean nextKeyword(KeywordOptions ko) {
    if (this.searchFilterConfig == null) {
        return false;
    } else {
        int kwSize = this.kwValues.size();
        int kwFixSize;
        
        if (this.kwFixValues == null) {
            kwFixSize = 0;
        } else {
            kwFixSize = this.kwFixValues.size();
        }

        if (ko.getCurrentIndex() >= kwSize - 1) {
            ko.setCurrentIndex(0);
            if (ko.getCurrentFixIndex() >= kwFixSize - 1) {
                return false;
            } else {
                ko.setCurrentFixIndex(ko.getCurrentFixIndex() + 1);
                ko.setKwValue((String)this.kwValues.get(ko.getCurrentIndex()));
                if (this.kwFixValues != null) {
                    ko.setKwFixValue((String)this.kwFixValues.get(ko.getCurrentFixIndex()));
                }
                return true;
            }
        } else {
            ko.setCurrentIndex(ko.getCurrentIndex() + 1);
            ko.setKwValue((String)this.kwValues.get(ko.getCurrentIndex()));
            if (this.kwFixValues != null) {
                ko.setKwFixValue((String)this.kwFixValues.get(ko.getCurrentFixIndex()));
            }
            return true;
        }
    }
}

 其中根据KeywordOptions对象拼接url的方法如下,将该方法设为public,以便后续根据不同拼接规则可以继承重写

public String koToUrl(KeywordOptions ko) {
    StringBuilder builder = new StringBuilder(this.baseUrl);
    builder.append(ko.getCurrentPage());
    if (this.searchFilterConfig == null) {
        return builder.toString();
    }else if (ko.getKwValue() == null && ko.getKwFixValue() == null) {
        return builder.toString();
    } else {
        builder.append("&");
        if (ko.getKwValue() != null) {
            if (this.kwCharset != null) {
                try {
                    builder.append(URLEncoder.encode(ko.getKwValue(), this.kwCharset));
                } catch (UnsupportedEncodingException var5) {
                    var5.printStackTrace();
                }
            } else {
                builder.append(ko.getKwValue());
            }
        }

        if (ko.getKwFixValue() != null) {
            builder.append("+");
            if (this.kwCharset != null) {
                try {
                    builder.append(URLEncoder.encode(ko.getKwFixValue(), this.kwCharset));
                } catch (UnsupportedEncodingException var4) {
                    var4.printStackTrace();
                }
            } else {
                builder.append(ko.getKwFixValue());
            }
        }

        return builder.toString();
    }
}

最后得到下一列表页请求(封装url)

public synchronized Request nextListPage(KeywordOptions ko) {
    //判断任务是否结束,列表切换是否锁定
    if (!this.listAddLock && !this.isComplete) {
        //获取配置文件解析器实例
        ConfigParser parser = ConfigParser.getInstance();
        Boolean fixed = (Boolean)parser.getValue(this.commonConfig, "fixed", false, this.spiderConfig.getConfigPath() + ".common");
        //判断页面url是否为固定
        if (fixed) {
            return null;
        } else {
            String url;
            //判断当前页是否为列表页尾页
            if (ko.getCurrentPage() >= this.totalPages) {
                //为真则切换关键词
                ko.setCurrentPage(Long.valueOf(String.valueOf(this.commonConfig.get("firstpage"))));
                if (this.nextKeyword(ko)) {
                    url = this.koToUrl(ko);
                    return this.nextListPageHook(this.pushRequest(url, ko));
                } else {
                    this.isComplete = true;
                    return this.nextListPageHook((Request)null);
                }
            } else {
                //非尾页,则当前页面索引加一
                ko.setCurrentPage(ko.getCurrentPage() + 1L);
                url = this.koToUrl(ko);
                return this.nextListPageHook(this.pushRequest(url, ko));
            }
        }
    } else {
        return null;
    }
}

在BasePageProcessor中编写页面处理逻辑,相关代码如下:

public void process(Page page) {
    Iterator var4;
    if (page.getUrl().toString().contains(this.baseUrl)) {
        //判断是否下载异常,自定义错误码600
        if (page.getStatusCode() == 600) {
            this.listAddLock = false;
            return;
        }
        //解析列表页,后续业务会重写processList(page)方法
        if (this.processList(page)) {
            this.processSuccessListPageCount.incrementAndGet();
            logger.info("list page crawl success url={}", page.getUrl());
            this.listAddLock = false;
        } else {
            this.processErrorListPageCount.incrementAndGet();
            logger.warn("list page crawl failed url={}", page.getUrl());
        }
        //每个List request中存储KeywordOptions实例
        KeywordOptions ko = (KeywordOptions)JSON.parseObject((String)page.getRequest().getExtra("ko"), KeywordOptions.class);
        if (ko != null) {
            List<Request> requests = page.getTargetRequests();
            var4 = requests.iterator();

            while(var4.hasNext()) {
                Request request = (Request)var4.next();
                request.putExtra("kw", ko.getKwValue());
            }
        }
        //获取下一列表页
        Request listpage = this.nextListPage(ko);
        if (listpage != null) {
            listpage.putExtra("nocheckdup", true);
            page.putField("listPage", listpage);
        }
    } else {
        //详细页解析,同样先进行异常检查
        if (page.getStatusCode() == 600) {
            return;
        }
        
        try {
            //processPage方法也会被后续具体业务重写
            this.processPage(page);
            this.processSuccessPageCount.incrementAndGet();
        } catch (Exception var7) {
            this.processErrorPageCount.incrementAndGet();
            logger.warn("page process failed url={} , error:{}", new Object[]{page.getUrl(), var7});
        }

        ResultItems items = page.getResultItems();
        String keyword = (String)page.getRequest().getExtra("kw");
        if (keyword == null) {
            keyword = this.kwValues != null ? (String)this.kwValues.get(0) : null;
        }

        if (keyword != null) {
            var4 = items.getAll().entrySet().iterator();

            while(var4.hasNext()) {
                Map.Entry<String, Object> entry1 = (Map.Entry)var4.next();
                Map<String, Object> map = (Map)entry1.getValue();
                map.put("keyword", keyword);
            }
        }
    }
}

 

webMagic爬虫抓取某个博客全部文章名称 webMagic爬虫抓取某个博客全部文章名称,简单列子,可以做参考 立即下载

相关推荐

优化Java实现网络爬虫 获取百度搜索内容 只支持http方式

优化上次上传的读者反馈问题:缺包以及空指针异常等。Java实现网络爬虫 获取百度搜索内容包括标题、链接、内容等信息,直接可以运行,仅供参考。 直接运行JSoupBaiduSearcher.java里面的main方法,会在控制台打印出搜索的信息。目前只支持http不支持https。感谢下载和问题反馈

使用webmagic爬取引用标准文献的新闻

目录目录 任务 总体思路 使用百度搜索 筛选搜索结果 新闻URL的转换 储存新闻 标准引用的统计工作 代码实现 运行流程 两个爬虫的结构 BaiduForEachCrawler Downloader Scheduler PageProcessor Pipeline BaiduURLConverter Downloader Scheduler PageProcessor PipeLine 新闻去重与统

nobrowning的博客 1259

爬虫基于Springboot+WebMagic+Mybatis+多数据源

闲来无事最近写了一个全新的爬虫框架WebMagic整合springboot的爬虫程序,不清楚WebMagic的童鞋可以先查看官网了解什么是Webmagic,顺便说说用springboot时遇到的一些坑

使用webmagic爬取网页信息以及通过selenium进行页面元素操作

前言 本篇文章主要讲解如何使用webmagic技术来实现网页的爬取, 以及使用selenium操作页面元素,实现点击、输入事件 所用技术 1.webmagic 添加需要爬取的url Spider.create(new MyProcessor()).addUrl("https://www.cnblogs.com/").thread(5).run(); 在process里面抓取符合条件...

前方一片光明 3万+

告别手动调参!PSCAD 4.2的Multiple-Run功能,5分钟搞定交流故障批量仿真

本文详细介绍了PSCAD 4.2的Multiple-Run功能如何高效处理交流故障批量仿真,告别传统手动调参的低效模式。通过五步配置法,工程师可在5分钟内完成数百次参数组合的仿真,显著提升电力系统分析效率。文章还包含工业级应用案例和高级调试技巧,助力实现故障仿真的自动化与智能化。

weixin_42552716的博客 279

AgentScope Java 2.0 项目实战:从零构建企业级自主Coding Agent

本文基于 AgentScope Java 框架,完整拆解两个生产级 AI Agent 项目的从零开发全过程。其一是企业级自主编码机器人(agentscope-codingagent),支持 Issue→PR 自动实现、PR Code Review、Docker 沙箱隔离执行与多通道接入;其二是个人 AI 助手管理平台(agentscope-paw),采用 Spring Boot + React 全栈架构,支持多 Agent、技能市场与多 IM 通道。

program哲学 842

WebMagic springboot 多站点垂直数据采集(支持插队采集)

WebMagic springboot 多站点垂直数据采集(支持插队采集)

解忧小童子 1282

5G射频设计中N77&N79的PRX为什么需要3个SRS

首先,我们来逐个拆解一下这个神秘的“

weixin_43199439的博客 1325

为什么选择gh_mirrors/spi/spider?6个理由让它成为你的爬虫首选工具

在当今数据驱动的时代,**网络爬虫工具**已成为数据采集和分析的重要工具。gh_mirrors/spi/spider(也称为Gather Platform数据采集与分析平台)是一款基于Webmagic内核的**可配置网络爬虫**,拥有直观的Web控制台界面。对于需要高效数据采集的用户来说,这款**爬虫工具**提供了完整而强大的解决方案。🚀 ## 1. 🎯 **零代码配置,快速上手** gh

gitblog_01161的博客 754

30天入门 SAP BTP 开发系列之十四: 将 SAP Business Application Studio 里开发好的 Node.js 应用部署到 Cloud Foundry 环境中

本教程详细介绍了如何将SAP Business Application Studio中的Node.js应用部署到Cloud Foundry环境。在完成本地开发和测试后,通过cf login命令连接Cloud Foundry环境,配置manifest.yml文件指定应用参数和路由信息。使用cf push命令完成应用的上传和部署,最终使应用运行在SAP BTP的云端环境中。教程包含从路由创建到部署验证的完整流程,确保开发者能够成功将Node.js应用发布到生产环境。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1085

Altium Designer应用技巧1: 功能模块的复用方法

Altium Designer应用技巧1: 功能模块的复用方法      我们在使用Altium Designer进行电路图设计时,常会遇到功能模块的复用问题,例如我们经常需要将12V以DC-DC的方式转换成5V,这在很多线路板上都会应用到。现在我们普通的做法是,每个板子都重新绘制一遍,像这样DC-DC的电路,很浪费时间。那么如何采用提高工作效率呢?我们可以采取Altium Desi

snmplink的博客 1万+

《倚天村 · 图解数据结构》导读:从 HashMap 面试连环问到 14 种数据结构的渐进式学习路径

数据结构是编程的根基,也是面试绕不开的话题。本文以开源仓库 CodeGuide 中收录的《倚天村 · 图解数据结构》系列文档为核心,梳理一份覆盖链表、数组、队列、堆栈、哈希表、堆、字典树、二分搜索树、平衡二叉树、2-3 树、红黑树、并查集、图、布隆过滤器共 14 种数据结构的全景学习指南。读完本文,你将掌握这套资料的章节脉络、每种结构的核心要点与配套源码位置,并能用它系统备战 HashMap 类高

gitblog_00585的博客 991

Node-RED教程(二):Node-RED的面板的操作

Node-RED系列(二):Node-RED的面板的操作 要使用Node-RED去搭建一个物联网平台,链接设备,设备通信,就必须要先熟悉Node-RED的这种面板,对于一个新的项目,在动手做之前一点想对这个的技术的文档有足够的了解做起来才能游刃有余。本期我给大家介绍一下Node-RED的各种面板,熟悉这些面板后,在后续的搭建Iot服务中,会举重若轻,同时该系列的文档,难度会逐步加深,知道了本章解释的名称后对后续文章的理解有很大帮助。 面板1:默认节点选项列表 安装Node-RED后默认的节点分为这5大类

知无涯 1万+

OneBlog文章搬运工:一键抓取优快云、博客园等平台文章的完整指南

OneBlog作为一款功能强大的Java博客系统,其内置的"文章搬运工"功能让博客内容迁移变得前所未有的简单。无论你是技术博主还是内容创作者,这个实用工具都能帮你快速将优快云、博客园等平台的文章迁移到自己的OneBlog博客中,大大节省了手动复制粘贴的时间。😊 ## 📋 什么是OneBlog文章搬运工? OneBlog文章搬运工是一个基于webMagic爬虫框架的智能文章迁移工具,它能够

gitblog_01114的博客 826

Allegro 给元器件PCB封装库添加3D模型详细步骤

从上面视图可以看到模型跟PCB 库的方向是对了,但是位置偏下,且在PCB封装库后面,我们下面需要做的就是把模型往上移、往前移。首先将元器件3D模型文件放在封装库的目录下(也可以单独新建一个模型库文件夹),注意3D文件必须是Step格式。Transparent: 选择透视的对象,可以是模型、也可以是PCB封装,或者两种都透视。在左边搜索要添加的3D模型的文件(注意是在* 星号前面输入文件名),按回车即可找到。同样的,接下来需要往Y 负方向移,即左移,一边调整一边观察视图。

sinat_15677011的博客 3685

高云FPGA系列教程(1):FPGA和ARM开发环境搭建

至此,高云FPGA和MCU开发环境就搭建完成了,整体还是比较简单的,几乎是一键完成,下一篇文章我们进行实际的FPGA和MCU开发。本文是高云FPGA系列教程的第1篇文章。

whik1194的博客 6195

基于Hadoop+Spark+Hive的招聘推荐系统设计与实践

大数据技术栈在现代数据处理中扮演着核心角色,其中Hadoop提供分布式存储基础,Spark实现高效内存计算,Hive则完成结构化查询。这些技术通过协同工作,能够处理海量数据并实现复杂分析。在招聘推荐场景中,结合TF-IDF特征提取和ALS协同过滤算法,可以构建精准的岗位推荐系统。该系统采用WebMagic进行数据采集,利用HanLP处理中文文本,并通过Spark MLlib快速实现推荐模型。对于计算机专业学生,这类项目既能掌握HDFS数据存储、Spark SQL分析等实用技能,又能学习解决数据倾斜、冷启动等

weixin_34224941的博客 444

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

OptiScaler:打破显卡限制!让所有GPU都能享受DLSS级画质提升的神器

还在为显卡性能不足而烦恼吗?是否因为硬件限制而无法体验游戏的最佳画质?OptiScaler正是解决这些痛点的终极方案——这款开源工具能让所有显卡(无论NVIDIA、AMD还是Intel)都能享受DLSS级画质优化技术,彻底打破硬件壁垒! ## 🎯 为什么OptiScaler是游戏玩家的必备神器? **核心关键词**:显卡性能优化、游戏画质提升、AI超分辨率技术、DLSS替代方案 **长尾关

gitblog_00311的博客 865

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

webmagic 获取文本_一个百度搜索结果内容获取爬虫

1 概述该项目是一个百度搜索结果获取爬虫。爬虫从一个文本文件中获取关键字组,查询获得结果后,将结果链接的内容下载存储到文件中。2 使用下载jar文件和配置文件。 百度网盘修改配置文件中的配置,最主要的是要指定关键字文件。运行run.bat,即可开始爬取。如果需要删除输出文件夹中的文件,需一并删除success.txt文件。3 运行流程读取配置文件settings.properties根据配置中指定...

weixin_29752563的博客 551

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java爬虫(webmagic)

webMaigc学习地址(强烈推荐):http://www.oschina.net/p/webmagic 本篇博客只是整理笔记。   webmagic的是一个无须配置、便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫。webmagic采用完全模块化的设计,功能覆盖整个爬虫的生命周期(链接提取、页面下载、内容抽取、持久化),支持多线程抓取,分布式抓取,并支持自动重试、

实践是最好的方法 2万+

Web项目之网络爬虫

一、爬虫基础篇   Python网络爬虫(认识爬虫)   Python网络爬虫(http和https协议)   Python网络爬虫(基于urllib库的get请求页面)   Python网络爬虫(requests模块应用1)   Python网络爬虫(验证码处理)   Python网络爬虫(session与ip代理池)   Python网络爬虫(线程池)   Py...

weixin_30706691的博客 481

使用webmagic爬取网站数据

通过webmagic爬取穷游网数据

兴国-为梦想而战 4328

Java爬虫框架WebMagic的使用总结

最近,项目做一个公司新闻网站,分为PC&移动端(h5),数据来源是从HSZX与huanqiu2个网站爬取,主要使用java编写的WebMagic作为爬虫框架,数据分为批量抓取、增量抓取,批量抓当前所有历史数据,增量需要每10分钟定时抓取一次,由于从2个网站抓取,并且频道很多,数据量大,更新频繁;开发过程中遇到很多的坑,今天腾出时间,感觉有必要做以总结。

在路上。。。 4万+

webmagic爬虫--爬取简单网页

WebMagic框架包含四个组件,PageProcessor、Scheduler、Downloader和Pipeline。 这四大组件对应爬虫生命周期中的处理、管理、下载和持久化等功能。 这四个组件都是Spider中的属性,爬虫框架通过Spider启动和管理。 PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。需要自己定义。 Scheduler负责管理...

jia1506的博客 935

okhttp3之java.net.SocketTimeoutException: timeout 异常处理

背景介绍     项目中开启线程池下载图片,okhttp报错如下:     一直沿用以前开发的工具类(将okhttp客户端封装成了单例模式),之前开发的项目涉及到的网络请求未出现过类似异常,而这次由于图片下载量大,线程数量多,造成socket超时。     之前的工具类: pu...

Vincent2014Linux 4万+
上一篇: MIT Place Pulse数据集及google街景图片爬取
下一篇: 专利网数字验证码识别
zhg_vincent
博客等级 码龄12年 93粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值