简介
SeimiCrawler是一个敏捷的,独立部署的,支持分布式的Java爬虫框架,希望能在最大程度上降低新手开发一个可用性高且性能不差的爬虫系统的门槛,以及提升开发爬虫系统的开发效率。在SeimiCrawler的世界里,绝大多数人只需关心去写抓取的业务逻辑就够了,其余的Seimi帮你搞定。设计思想上SeimiCrawler受Python的爬虫框架Scrapy启发,同时融合了Java语言本身特点与Spring的特性,并希望在国内更方便且普遍的使用更有效率的XPath解析HTML,所以SeimiCrawler默认的HTML解析器是JsoupXpath(独立扩展项目,非jsoup自带),默认解析提取HTML数据工作均使用XPath来完成(当然,数据处理亦可以自行选择其他解析器)。并结合SeimiAgent彻底完美解决复杂动态页面渲染抓取问题。完美支持SpringBoot,让你的想象力与创造力发挥到极致(需要JDK1.8+)。
快速开始
新建一个springboot项目,并加入SeimiCrawler的最新依赖:
在配置文件中配置两个属性:
第二个seimi.crawler.names配置的是爬虫的名字,这里配置一个basic。启动类不用做任何修改写一个爬虫类,起名叫basic:
注意该类加的注解和需要继承的类。然后配置需要爬的网页,这里我配置一个自己的nginx系列博客:
https://www.jianshu.com/c/18dd84d66135
打开可以看到一系列文章:
这是爬虫爬数据的起始页面,来看起始页面的配置:
可以看到非常简单,只是一行代码的事情。这里起始页面可以配置多个,如果有重复的,里面会自动去重。我们先获取整个页面上所有的标题的超级链接,然后循环打印出来:
获取页面上的元素需要用到JXDocument类,doc.sel方法的参数是一个xpath格式的字符串,关于xpath格式后面会详细说明,这里暂时不说。现在从内容看可以简单看出,这里是获取所有class为title的a标签的href的内容,也就是所有标题的超级链接放到list中,并打印出来,我们启动项目,看一下效果:
可以看到,文章数量有七个,这是正确的。打印出来的url也都是相对链接,这里简单起见,我们手动加上域名地址,查看效果:
打印出来的地址变成了蓝色可点击的,我们点击一个进去,发现正是其中一篇内容,获取链接成功!!获取链接后,我们能获取链接里面的二级页面的内容吗?可以!比如我们点击一个连接进去:
里面的内容可以简单的分为标题和正文,我们先获取标题。大家都知道,在浏览器里面打开开发者模式,可以看到html标签,我们根据标签可以整理出标题的xpath格式(关于这个后面会详细说明)。
关于title的xpath格式,可以看到是class为titleh1标签的内容。我们打印出来url和title,在上面地址循环的时候调用这个方法:
上面的回调getTitle方法使用的是Java8的语法,不懂的可以学习一下。我们现在来运行项目查看一下效果:
可以看到成功的爬下了标题这个属性。下面把正文也加上:
可以看到正文xpath的匹配规则更加复杂,后面再详细说xpath。我们现在运行看一下效果:
可以看到,现在有点爬虫的样子了!我们从开始到现在,总共写了十行左右的代码,爬下来几篇文章,实现了一个简单的爬虫。可以看出SeimiCrawlerV2的确是Java实现爬虫的一个非常简单的框架,值得学习。为了看得效果好一些,我们把getTitle方法加上锁:
运行查看效果:
上面爬的内容比较简单,只是一个起始页面和二级页面的链接和内容。作为一个入门例子足够了。
xpath介绍
请查看:http://jsoupxpath.wanghaomiao.cn/
框架基本原理
爬虫开发约定
之所以要有一些约定,主要目的是让使用SeimiCrawler开发的爬虫系统的源码更加的规范可读,大家都遵守一个约定,那么在团队成员相互协作开发的过程中,业务工程的代码在团队成员间就会更加的易读,易改。不至于某人开发了一个业务逻辑,另一个接手的人连到哪里去找他的类都很困难,这不是我们要的。我们要强大,简单,好用。最后,有约定不代表SeimiCrawler不够灵活。
由于SeimiCrawler的context基于spring实现,所以支持几乎所有spring格式的配置文件和spring通常用法。SeimiCrawler会扫描工程classpath下所有xml格式配置文件,但是只有文件名以seimi开头的xml配置文件能被SeimiCrawler识别并加载。
SeimiCrawler的日志使用slf4j,可自行配置具体的实现。
Seimi开发时要注意的约定,会在下面的开发要点中一一介绍。
爬虫类规则
爬虫规则类是使用SeimiCrawler开发爬虫最核心的部分,快速开始中的Basic类就是一个基本的爬虫类。写一个crawler需注意一下几点:
1. 需继承BaseSeimiCrawler
2. 需打上@Crawler注解,注解中name属性是可有可无的,如果设置了,那么这个crawler则以你定义的名字命名,否则默认使用你创建的类名。
3. 所有想要被SeimiCrawler扫描到的crawler需放在crawlers包下,如:cn.wanghaomiao.xxx.crawlers,也可以参考项目附带的demo工程。 初始化好Crawler后,你需要实现两个最基本的方法public String[] startUrls();和publicvoid start(Response response),实现后一个简单的爬虫就算写完了。
注解@Crawler
目前@Crawler注解有下面几个属性:
1. name 自定义一个爬虫规则的名字,一个SeimiCrawler可扫描范围内的工程中不能有同名的。默认使用类名。
2. proxy 告诉Seimi这个爬虫是否使用代理,以及使用什么样的代理。目前支持三种格式http|https|socket://host:port,这一版还没支持带用户名和密码的代理。
3. useCookie 是否启用cookies,启用后即可像浏览器一样保持你的请求状态,同样的也会被追踪。
4. queue 指定当前这个爬虫要使用的数据队列,默认的是本地队列实现DefaultLocalQueue.class,也可以配置使用默认的redis版实现或是自行基于其他队列系统的实现,这个后面会进行更为详细的介绍。
5. delay 设置请求抓取的时间间隔单位为秒,默认为0即没有间隔。
6. httpType Downloader实现类型,默认的Downloader实现为Apache Httpclient,可以通过他将网络请求处理实现改为OkHttp3。
7. httpTimeOut 支持自定义超时间,单位毫秒,默认15000ms
实现startUrls()
这是爬虫的入口,返回值为URL的数组。默认startURL会被以GET请求处理,如果某些特殊情况下你需要让Seimi以POST方法处理你的startURL,你只需在这条URL的后面加上##post即可,例如http://passport.cnblogs.com/user/signin?ReturnUrl=http%3a%2f%2fi.cnblogs.com%2f##post,这个指定不区分大小写。这个规则仅适用startURL的处理。
实现start(Response response)
这个方法是针对startURL的回调函数,即告诉Seimi如何处理请求startURL返回的数据。
Response数据提取
文本类结果 Seimi默认推荐使用XPath来提取HTML数据,虽然初期学习了解XPath有一点点的学习成本,但是与在你了解他之后给你带来的开发效率相比较来说实在是太微不足道了。JXDocument doc = response.document();即可拿到JXDocument(JsoupXpath的文档对象),然后就可以通过doc.sel("xpath")提取任何你想要的数据了,提取任何数据应该都是一条XPath语句就能搞定了。对Seimi使用的XPath语法解析器以及想对XPath进一步了解的同学请移步JsoupXpath。当然,实在对XPath提不起感觉的话,那么response里有原声的请求结果数据,您可自行选择其他数据解析器进行处理。
文件类结果 如果是文件类的返回结果,可以使用reponse.saveTo(File targetFile)进行存储,或是获取文件字节流byte[] getData()进行其他操作。
Response类内容
回调函数
使用默认的一个回调函数显然是不能满足你的要求的,如果你还想把startURL页面中的某些URL提取出来再进行请求获取数据并进行处理的话,你就需要自定义回调函数了。注意点如下:
1. V2.0开始支持方法引用,设置回调函数更加自然,如:Basic::getTitle。
2. 在回调函数里的产生的Request可以指定其他回调函数也可以指定自己为回调函数。
3. 作为回调函数需满足这个格式:public void callbackName(Response response),即方法是公有的,有且只能有一个参数Response,没有返回值。
4. Request设置一个回调函数只需提供这个回调函数的String类型的名称即可,如:快速开始中那个getTitle。
5. 继承了BaseSeimiCrawler的Crawler可以在回调函数内直接调用父类的push(Requestrequest)将新的抓取请求发送掉请求队列。
6. 可以通过Request.build()创建Request。
上面是比较重要的内容,其它参考官方文档 : http://wiki.seimicrawler.org/
代码地址: https://gitee.com/blueses/spring-boot-demo