背景: 最近北京疫情有点严重,状态是居家办公,又是买菜做饭又是核酸检测心情是无比的烦躁还总是会议,无需发言的会议就边听边写写csdn记录一下。这几天在用Java写一个数据抓取的程序,用于数据分析等等。第一是因为原项目使用了Java开发,为有利于集成,所以也使用了Java而没有使用Python。第二是我们的需求是运行一个Java程序然后去调用爬虫,最后返回提取的数据,不需要进行存储,没有找到Scrapy直接返回数据给到Java程序的解决方案,并且不想复杂化,所以选择了一款github里较高star数的webmagic项目。
再重申一下我们的需求和困难点:把爬虫抽象为一个普通的方法,入参是目标网站的URL,返回内容就是提取的数据即可,无需存储。而Java程序可以通过curl http请求发送到Scrapyd是可以远程启动爬虫进行爬取数据,缺点就是无法直接返回数据给到Java程序,貌似没有好的解决方案。
1. 架构方面
webmagic(https://github.com/code4craft/webmagic) 这是一个基于Java语言的数据抓取的框架,star数为10k,整体架构和Python Scrapy差不多,但是这个项目后面更新的频率不高,可能是作者没有时间精力有限。于是在github上搜索到了webmagic,一个。
Scrapy( https://docs.scrapy.org/en/latest/) 这是基于Python的数据抓取框架,star数为45k,是一个非常棒的框架,扩展性较好,更新的频率也较高。
左侧是webmagic架构图,右侧是Scrapy架构图,webmagic参考了Scrapy,由Scrapy到webmagic进行切换,学习成本也较小。如果两个框架都不熟悉,一起学两个也不吃力。
2. 在生态方面,在Java生态中好像没有紧密配合webmagic的工具或中间件,这个webmagic框架只是抓取的框架,围绕着webmagic还有很多问题需要解决,例如分布式部署,远程控制启停等等,而scrapy的生态非常好,周围有很多适配的软件、中间件、插件等等,例如Scrapyd,Scrapyd-Client。
3. 在动态渲染页面的抓取方面:
以前都是通过测试工具+驱动+浏览器来实现,例如Selenium+ChromeDriver+Chrome浏览器,也有的工具是直接 Pyppeteer+Chromium实现,也有的工具Playwright会自动安装所需的驱动和浏览器。
webmagic对接Selenium,通过webmagic-selenium进行对接
Scrapy对接Selenium/Pyppeteer/Playwright都是通过Downloader Middleware进行对接,都有相应的解决方案,而对接Splash需要安装scrapy-splash的包进行对接。整体Scrapy对接各种下载器都能兼容。
对于动态渲染页面,无非是看前端代码分析Ajax请求然后直接抓取后端API方式,再或是模拟浏览器执行抓取前端界面来获取数据。
4. 扩展性方面:略,两者都能进行扩展,也能手动改代码并重新编译以扩展功能或增强功能。
5. 在编写代码方面,webmagic是通过实现PageProcessor接口中的process方法来对页面进行处理,Scrapy是通过在spiders文件夹中继承scrapy.Spider类,实现parse方法来对页面进行处理。
这里举一个文章列表+文章详情的例子来说明差异,我们的诉求是 抓取所有的文章,然后进行存储分析等操作:
假设现在有两类页面,第一类页面是文章列表页面,分为第一页第二页....第n页等,第二类页面是具体某偏文章的页面,这个页面包括 标题、时间、作者、内容等等信息。
webmagic是以访问链接进行区分两类的页面,什么意思呢?
我们有这两类页面,需要告诉框架如何处理这两类页面,也就是不同的处理逻辑,那么框架是如何区分这两类不同的页面呢?
回答: webmagic是基于URL进行正则匹配并在同一个Process方法中使用if/else或switch分支进行区分并进行处理,如下图所示:
如上图所示,通过在类中定义URL_LIST和URL_POST正则表达式,来对每个page进行正则匹配,匹配到列表则进行列表的逻辑处理,匹配到文章则进行文章的逻辑处理。可详细查看:https://github.com/code4craft/webmagic/blob/master/webmagic-samples/src/main/java/us/codecraft/webmagic/samples/SinaBlogProcessor.java
但这个例子是个老例子,而新的方法是使用 SubPageProcessor (http://webmagic.io/apidocs/index.html?help-doc.html),实现SubPageProcessor接口中的processPage方法来实现的。
而Scrapy则不一样,Scrapy是基于回调进行的,如下图所示:
如上图所示: Scrapy是通过给不同的页面设定不同的回调函数进行区分处理逻辑, 用page方法实现文章列表的处理,并从文章列表页面抽取文章的链接放入到请求队列中,对文章详情来说新增一个parse_page方法来处理文章详情等内容,然后存储到item给到pipeline进行后续的存储和分析。
如果是三级页面或者更多级页面,例如 论坛板块+某类文章列表+文章详情,这种三级页面进行抓取,webmagic需要再定义一个板块的URL进行正则匹配并编写处理逻辑,而Scrapy则需要多定义一个方法进行逻辑处理。
webmagic通过page的URL来区分不同的层级的处理逻辑或实现SubPageProcessor接口中的processPage方法来区分不同的层级的处理逻辑,Scrapy是通过设定不同的回调方法来区分不同的层级处理逻辑。
总结:
整体上看两个框架的差别在于所用语言不一致,页面处理逻辑的代码书写方式不同,各自的生态环境也不同,如果要进行技术选型,还是需要根据自身的需求及架构进行评估。如果你不介意整体的复杂性,还是推荐 其他语言+ 中间件 + scrapy + scrapyd的方式来进行,例如 Java语言 + MySQL/MongoDB + scrapy + scrapyd,java语言发送一个http请求到scrapyd,然后爬虫开始工作,将数据写到存储中间件中,然后Java程序去存储中间件中去取回数据进行下一步的分析工作。
参考文献:
1. webmagic :GitHub - code4craft/webmagic: A scalable web crawler framework for Java.
2. Scrapy : GitHub - scrapy/scrapy: Scrapy, a fast high-level web crawling & scraping framework for Python.
3. webmagic: Introduction · WebMagic Documents
4. Scrapy Documentation: Scrapy 2.7 documentation — Scrapy 2.7.1 documentation