A scalable web crawler framework for Java.

Overview

logo

Readme in Chinese

Build Status

A scalable crawler framework. It covers the whole lifecycle of crawler: downloading, url management, content extraction and persistent. It can simplify the development of a specific crawler.

Features:

  • Simple core with high flexibility.
  • Simple API for html extracting.
  • Annotation with POJO to customize a crawler, no configuration.
  • Multi-thread and Distribution support.
  • Easy to be integrated.

Install:

Add dependencies to your pom.xml:

<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-core</artifactId>
    <version>0.7.4</version>
</dependency>
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-extension</artifactId>
    <version>0.7.4</version>
</dependency>

WebMagic use slf4j with slf4j-log4j12 implementation. If you customized your slf4j implementation, please exclude slf4j-log4j12.

<exclusions>
    <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
</exclusions>

Get Started:

First crawler:

Write a class implements PageProcessor. For example, I wrote a crawler of github repository infomation.

public class GithubRepoPageProcessor implements PageProcessor {

    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);

    @Override
    public void process(Page page) {
        page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());
        page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString());
        page.putField("name", page.getHtml().xpath("//h1[@class='public']/strong/a/text()").toString());
        if (page.getResultItems().get("name")==null){
            //skip this page
            page.setSkip(true);
        }
        page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));
    }

    @Override
    public Site getSite() {
        return site;
    }

    public static void main(String[] args) {
        Spider.create(new GithubRepoPageProcessor()).addUrl("https://github.com/code4craft").thread(5).run();
    }
}
  • page.addTargetRequests(links)

    Add urls for crawling.

You can also use annotation way:

@TargetUrl("https://github.com/\\w+/\\w+")
@HelpUrl("https://github.com/\\w+")
public class GithubRepo {

    @ExtractBy(value = "//h1[@class='public']/strong/a/text()", notNull = true)
    private String name;

    @ExtractByUrl("https://github\\.com/(\\w+)/.*")
    private String author;

    @ExtractBy("//div[@id='readme']/tidyText()")
    private String readme;

    public static void main(String[] args) {
        OOSpider.create(Site.me().setSleepTime(1000)
                , new ConsolePageModelPipeline(), GithubRepo.class)
                .addUrl("https://github.com/code4craft").thread(5).run();
    }
}

Docs and samples:

Documents: http://webmagic.io/docs/

The architecture of webmagic (refered to Scrapy)

image

There are more examples in webmagic-samples package.

Lisence:

Lisenced under Apache 2.0 lisence

Thanks:

To write webmagic, I refered to the projects below :

Mail-list:

https://groups.google.com/forum/#!forum/webmagic-java

http://list.qq.com/cgi-bin/qf_invite?id=023a01f505246785f77c5a5a9aff4e57ab20fcdde871e988

QQ Group: 373225642 542327088

Related Project

  • Gather Platform

    A web console based on WebMagic for Spider configuration and management.

Issues
  • WebMagic-Avalon项目计划

    WebMagic-Avalon项目计划

    WebMagic-Avalon项目的目标是打造一个可配置、可管理的爬虫,以及一个可分享配置/脚本的平台,从而减少熟悉的开发者的开发量,并且让不熟悉Java技术的人也能简单的使用一个爬虫。

    ~~Part1:webmagic-scripts~~

    目标:使得可以用简单脚本的方式编写爬虫,从而为一些常用场景提供可流通的脚本。 例如:我需要抓github的仓库数据,可以这样写一个脚本(javascript):

    https://github.com/code4craft/webmagic/tree/master/webmagic-scripts

    这个功能目前实现了一部分,但最终结果仍在实验阶段。欢迎大家积极参与并提出意见。~~因为编写一个稳定的语言需要很多领域积累,后来决定先做后台。~~

    Part2:webmagic-pannel

    一个集成了加载脚本、管理爬虫的后台。目前在开发中。

    ~~Part3:webmagic-market~~

    一个可以分享、搜索和下载脚本的站点。计划中。

    如何参与

    webmagic目前由作者业余维护,仅仅为了分享和个人提高,没有任何盈利,也没有商业化打算。

    欢迎以下几种形式的贡献:

    1. 为webmagic项目本身提出改进意见,可以通过邮件组、qq、oschina或者在github提交issue(推荐)的方式。
    2. 参与WebMagic-Avalon计划的建设讨论,包括产品设计、技术选型等,可以直接回复这个issue。
    3. 参与webmagic代码开发,请fork一份代码,修改后提交pull request给我。请使用尽量新的版本,并说明修改内容。pull request接受后,我会将你加为committer,共同参与开发。
    newFeature suspend 
    opened by code4craft 30
  • Https下无法抓取只支持TLS1.2的站点

    Https下无法抓取只支持TLS1.2的站点

    WebMagic默认的HttpClient只会用TLSv1去请求,对于某些只支持TLS1.2的站点(例如 https://juejin.im/) ,就会报错:

    javax.net.ssl.SSLException: Received fatal alert: protocol_version
    	at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
    	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
    	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
    	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141)
    	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    	at us.codecraft.webmagic.downloader.HttpClientDownloader.download(HttpClientDownloader.java:85)
    

    现在的修改方式是在HttpClientGenerator中构建SSLConnectionSocketFactory时加上支持。

    bug 
    opened by code4craft 24
  • 代理需求征集和API改进

    代理需求征集和API改进

    之前的API设计并不是好用,想重新设计一套。

    enhancement major 
    opened by code4craft 14
  • [Bug] CountableThreadPool 类中 exec() 中是否存在线程安全问题

    [Bug] CountableThreadPool 类中 exec() 中是否存在线程安全问题

        if (threadAlive.get() >= threadNum) { // 1 感觉此处有线程安全问题
            try {
                reentrantLock.lock();
                while (threadAlive.get() >= threadNum) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                    }
                }
            } finally {
                reentrantLock.unlock();
            }
        }
        threadAlive.incrementAndGet();  // 2
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {
                    try {
                        reentrantLock.lock();
                        threadAlive.decrementAndGet();
                        condition.signal();
                    } finally {
                        reentrantLock.unlock();
                    }
                }
            }
        });
    

    比如,有两个线程,执行此任务。先假设 threadNum = 10threadAlive.get() = 9。线程1执行注释1处的判断得到 false,将会执行注释2的语句。但还没执行,就发生调度了,现线程2执行注释1处了。此时由于线程1没有执行 threadAlive.incrementAndGet(); 所以依旧判断为 false 。但是,这样的逻辑是不该的。

    我不知道我这样理解对不对,请大家解答。谢谢~

    我的一个修改

        // My modify
        try {
            reentrantLock.lock();
            if (threadAlive.get() >= threadNum)
                while (threadAlive.get() >= threadNum) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                    }
                }
            else
                threadAlive.incrementAndGet();
        } finally {
            reentrantLock.unlock();
        }
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {
                    try {
                        reentrantLock.lock();
                        threadAlive.decrementAndGet();
                        condition.signal();
                    } finally {
                        reentrantLock.unlock();
                    }
                }
            }
        });
    
    opened by INotWant 12
  • 0.71版本downloader的时候就会打印页面到控制台,给查看日志带来了不便

    0.71版本downloader的时候就会打印页面到控制台,给查看日志带来了不便

    0.71版本downloader的时候就会打印页面到控制台,这样就产生很多日志文件,在查看其他的日志时就很不方便,如果改变日记等级其他的日志我都看不到了,我觉得这个打印页面的不用要。

    question 
    opened by lidaoyang 11
  • 爬虫状态的监控

    爬虫状态的监控

    希望对某个任务下的已抓取、待抓取、失败数等状态进行监控。

    enhancement 
    opened by code4craft 11
  • download失败,添加请求,cookie失效

    download失败,添加请求,cookie失效

    大佬你好,我现在有一个问题,就是目前我们的PageProcessor里面addTargetRequest是在download success成功情况下才能添加新的请求,假设失败了就会重试,但是如果一直重试失败到达最大次数后,就不能添加新的request了,我尝试在Spider启动时直接addRequests添加构建所有请求,但是这样Request的cookie header就写死了,会出现请求cookie失效,无法灵活更新cookie,这个情况该如何处理呢,能否支持在失败时也可以添加新的Request

    question 
    opened by jason2015lxj 10
  • 第一个项目运行报错,com.google.common.collect.Table

    第一个项目运行报错,com.google.common.collect.Table

    我自己建了一个项目, 导入了 us.codecraft webmagic-core 0.5.3 us.codecraft webmagic-extension 0.5.3 运行之后报 Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Table at com.leozhou.webmagic.GithubRepoPageProcessor.(GithubRepoPageProcessor.java:14) at com.leozhou.webmagic.GithubRepoPageProcessor.main(GithubRepoPageProcessor.java:39) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Table at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 7 more

    opened by le0zh0u 10
  • Site类中的setHttpProxy()方法被废弃了吗?

    Site类中的setHttpProxy()方法被废弃了吗?

    0.5.2版本Site的setHttpProxy()方法被废弃了吗? HttpClientDownloader访问网页时,没有使用到我设置的代理 现在只能使用ProxyPool来设置代理

    bug 
    opened by SiQLuxe 9
  • PageProcessor里面怎么有效的更加自己的条件比如新闻Id 判断停止任务呢?

    PageProcessor里面怎么有效的更加自己的条件比如新闻Id 判断停止任务呢?

    PageProcessor里面怎么有效的更加自己的条件比如新闻Id 判断停止任务呢? 在下面方法里面怎么停止任务呢? public void process(Page page) { //列表页 if (page.getUrl().regex(URL_LIST).match()) { if (isFlag) { spider.stop(); }else{ page.addTargetRequests(page.getHtml().xpath("//div[@class="list-con"]").links().regex(URL_GET).all()); page.addTargetRequests(page.getHtml().links().regex(URL_LIST).all()); } } }

    opened by lidaoyang 9
  • 页面中需要执行一段js

    页面中需要执行一段js

    在采集一个页面的时候,里面又一些数据是加密的,需要调用页面中的一个js方法,方法很复杂,嵌套,目前我使用的是用chromedriver来运行这个方法,但是采集慢了很多,请问有什么方法,直接用默认的downloader,然后获取page对象后,可以运行页面中的js方法

    opened by huangjianfeng1 2
  • RedisScheduler should use `task.getSite().getDomain()` instead of `task.getUUID()` as the key in Redis database.

    RedisScheduler should use `task.getSite().getDomain()` instead of `task.getUUID()` as the key in Redis database.

    Problem

    Say there are multiple spiders distributed in different instances, and they are downloading web pages belonging to the same domain www.example.com.

    In the meanwhile, I expect each of them has a unique UUID as the identifier. For instance, I set Spider 1's UUID to be www.example.com_127.0.0.1_8081, Spider 2's UUID to be www.example.com_127.0.0.1_8082, etc. Following this, the key of the queue in Redis is split into two: queue_www.example.com_127.0.0.1_8081 and queue_www.example.com_127.0.0.1_8082.

    Ideally, the key should still be queue_www.example.com.

    Solution

    Use the domain name as the key in Redis for set and queue.

    public class RedisScheduler extends DuplicateRemovedScheduler implements MonitorableScheduler, DuplicateRemover {
    
    // ...
        protected String getSetKey(Task task) {
            return SET_PREFIX + task.getUUID(); // task.getSite().getDomain()
        }
    
        protected String getQueueKey(Task task) {
            return QUEUE_PREFIX + task.getUUID(); // task.getSite().getDomain()
        }
    
        protected String getItemKey(Task task) {
            return ITEM_PREFIX + task.getUUID(); // task.getSite().getDomain()
        }
    
    // ...
    }
    
    opened by thebirdandfish 0
  • 创建webDriverPool线程安全问题导致多线程情况下不关闭浏览器

    创建webDriverPool线程安全问题导致多线程情况下不关闭浏览器

    使用ChromeDriver模拟浏览器抓取页面时,如果指定了多线程同时抓取多个url时(例如设置thread=5),不会关闭Chrome浏览器(只关闭最后一次打开的浏览器进程)。

    Spider.create(goodsProcess)
            .addUrl(urls)
            .addPipeline(goodsPipeline)
            .setDownloader(downloader)
            .thread(5)
            .run();
    

    这是因为创建webDriverPool时线程不安全导致。需要双重验证,修改如下: 涉及方法:SeleniumDownloader#checkInit()

    private void checkInit() {
    	if (webDriverPool == null) {
    		synchronized (this) {
    			if (webDriverPool == null) {
    				webDriverPool = new SimpleWebDriverPool(poolSize);
    			}
    		}
    	}
    }
    
    opened by skyjilygao 0
  • 并发问题

    并发问题

    RedisScheduler BUG

    在RedisScheduler的pushWhenNoDuplicate()方法中,有可能在lpush之后hset之前其他线程调用poll来hget,会出现空指针异常。建议把lpush和hset调换一下顺序。

    @sutra

    opened by yuanshengjun-learn 0
  • PriorityScheduler为什么写的如此复杂?要3个queue去配合

    PriorityScheduler为什么写的如此复杂?要3个queue去配合

    PriorityScheduler源码如截图: image

    问题:为什么需要使用三个queue?直接把QueueScheduler的队列换成PriorityBlockingQueue就可以了吧?而且统计队列剩余数量好像是错的,只统计一个队列的,请作者看看。

    QueueScheduler源码如截图: image

    请作者指点一下,谢谢!

    opened by yuweiming2016 2
  • There is no crawling depth property

    There is no crawling depth property

    Can't find any crawler policy and\or property to restrict crawling depth. Is it missed and only way how we can restrict depth is by choosing suitable selector in PageProcessor?

    opened by meteoir 0
  • AbstractDownloader 类 的 onError方法 ,是否可以扩展下,把异常信息也带过去呢

    AbstractDownloader 类 的 onError方法 ,是否可以扩展下,把异常信息也带过去呢

    比如有些下载地址是因为网络波动 读取超时 。 这时onError有异常信息才能比较好即时处理

    opened by chouway 0
  • 这个项目不更新了吗

    这个项目不更新了吗

    这个项目不更新了吗

    opened by finalcreator 1
  • Add crawl with script with chromedriver in windows.

    Add crawl with script with chromedriver in windows.

    In webmagic-selenium project.

    1. Add test code using chromedriver in windows.
    2. Add test code using javascript with chromedriver.It is good practice to save time.
    opened by lxiaodao 0
Releases(WebMagic-0.7.3)
  • WebMagic-0.7.3(Jul 30, 2017)

    本次更新增加了Downloader模块的一些功能。

    #609 修复HttpRequestBody没有默认构造函数导致无法反序列化的bug。 #631 HttpRequestBody的静态构造函数不再抛出UnsupportedEncodingException受检异常。

    #571 Page对象增加bytes属性,用于获取二进制数据。下载纯二进制页面时,请设置request.setBinarayContent(true),这样对于二进制内容不会尝试转换为String,减小开销。

    #629 在HttpUriRequestConverter中会自动对一些导致URI异常的字符进行转移或过滤。

    #610 自动识别编码时,可以识别Content-Type中charset为大写的情况。 #627 支持为Request单独设置页面编码,兼容同一站点多种编码方式的情况。 #613 Page对象增加charset属性,其值为request/site中设置的charset,或者为自动检测的charset(未定义时)。

    #606 升级jsonpath到2.4.0 #608 升级jsoup到1.10.3

    Source code(tar.gz)
    Source code(zip)
    webmagic-0.7.3-all.tar.gz(5.07 MB)
  • WebMagic-0.7.2(Jun 17, 2017)

    此次更新修复了0.7.0-0.7.1版本的若干bug。

    1. #594 Request中的HttpRequestBody实现序列化接口。
    2. #596 修复0.7.0开始代理认证无法正确使用的问题。
    3. #601 完善页面状态异常时的错误信息。
    4. #605 修复0.7.0开始重复调用onSuccess和onError函数导致监控出错的问题。
    Source code(tar.gz)
    Source code(zip)
    webmagic-0.7.2-all.tar.gz(5.02 MB)
  • WebMagic-0.7.1(Jun 4, 2017)

    此次更新包含几个比较大的Bugfix,以及一些遗留问题的改进。

    • 修复0.7.0引入的RedisScheduler无法使用的bug。#583
    • 注解模式的JsonPath默认会指定source为RawText,不再会出现自动为头尾加了<html>标签导致无法解析的情况。#589
    • RegexSelector之前版本默认匹配group1,并通过对无捕获组的正则头尾加括号的形式来统一抽取内容。在0.7.1版本改为不再改变正则,而是通过匹配group0还是group1来实现匹配,见#559。新做法可以减少一些特殊用法的出错几率,例如零宽断言(#556)。
    • 重构了ObjectFormatter部分,修复了ObjectFormatter无法初始化参数的bug。 #570
    Source code(tar.gz)
    Source code(zip)
    webmagic-0.7.1-all.tar.gz(5.02 MB)
  • WebMagic-0.7.0(May 29, 2017)

    此次更新重写了HttpClientDownloader,完善了POST等其他Http Method的支持,并重写了代理API,更加简单和便于扩展。

    POST支持

    • 新的POST API,支持各种RequestBody #513
    Request request = new Request("http://xxx/path");
    request.setMethod(HttpConstant.Method.POST);
    request.setRequestBody(HttpRequestBody.json("{'id':1}","utf-8"));
    
    • 移除了老的在request.extra中设置NameValuePair的方式
    • POST请求不再进行去重 #484

    代理支持

    • 新的代理APIProxyProvider,支持自由扩展
    • 默认实现SimpleProxyProvider是一个简单的round-robin实现,可以添加任意个数的代理。
    HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
    SimpleProxyProvider proxyProvider = SimpleProxyProvider.from(new Proxy("127.0.0.1", 1087), new Proxy("127.0.0.1", 1088));
    httpClientDownloader.setProxyProvider(proxyProvider);
    
    • 移除了Site上关于代理配置的setProxy等,代理设置统一到HttpClientDownloader里。

    新的SimpleHttpClient

    • 用作简单的单次下载和解析时,使用SimpleHttpClient可以满足需求
    SimpleHttpClient simpleHttpClient = new SimpleHttpClient();
    GithubRepo model = simpleHttpClient.get("github.com/code4craft/webmagic",GithubRepo.class);
    

    其他改动

    • 为Page中增加状态码和Http头信息 #406
    • 支持Request级别设置Http Header和Cookie
    • 去掉Site.addStartRequest() , 用Spider.addStartRequest()代替 #494
    • HttpClientDownloader大幅重构,将Request转换抽象到HttpUriRequestConverter(之前继承HttpClientDownloader的实现可能需要做相应修改) #524
    • 将CycleRetry和statusCode的判断逻辑从Downloader中迁移到Spider中 #527
    • 通过Page.isDownloadSuccess而不是Page对象本身为空来判断是否下载失败
    • 为PageModel增加不发现新URL的功能 #575
    • 为Site增加了disableCookieManagement属性,在不想使用cookie时使用 #577
    Source code(tar.gz)
    Source code(zip)
    webmagic-0.7.0-all.tar.gz(4.52 MB)
  • webmagic-parent-0.6.1(Jan 21, 2017)

    本次更新修复了一些0.6.0的问题和一些小优化。

    • 修改默认策略为信任所有https证书 #444 @ckex
    • 修复使用startUrls添加url时,如果使用了cookie会出现空指针的问题 #438
    • PhantomJSDownloader支持crawl.js路径自定义 #414 @jsbd
    • POST请求支持302跳转 #443 @xbynet

    注:默认信任所有证书会有内容伪造的风险,但是考虑到爬虫的便利性还是加上了,使用者需要自己判断内容安全性。

    Source code(tar.gz)
    Source code(zip)
    webmagic-0.6.1-all.tar.gz(4.97 MB)
  • WebMagic-0.6.0(Dec 17, 2016)

    此次更新主要是一些依赖包的升级和bugfix。

    • #290 代理增加用户名密码认证 @hepan

    • #194 重构代理池部分代码,支持自定义代理池 @EdwardsBean

    • #314 修复低版本json-path依赖2.x的StringUtils导致报错的问题

    • #380 升级fastjson 到1.2.21

    • #301 修复JsonPath在注解模式不可用的问题 @Salon-sai

    • #377 修复监控模块在URL带有端口时会报错的问题

    • #400 修复FileCacheQueueScheduler的NullPointerException问题

    • #407 为PhantomJSDownloader添加新的构造函数,支持phantomjs自定义命令 @jsbd

    • #419 修复抓取https链接线程无法结束导致进程一直运行的问题 @cpaladin

    • #374 升级HttpClient到4.5.2,修复一些安全问题

    • #424 去掉Guava依赖

      因为Guava不同版本兼容性不好,经常导致demo无法运行,所以我最后决定去掉了Guava的依赖。如果使用了BloomFilterDuplicateRemover的用户,需要手动依赖Guava包。

    • #426 去掉Avalon相关包

      Avalon是之前计划的一站式抓取平台。因为有个朋友基于WebMagic做了类似的实现Gather Platform,所以Avalon放弃了,转而支持这个项目。WebMagic核心会专注于做应用内的框架。

    Source code(tar.gz)
    Source code(zip)
    webmagic-0.6.0-all.tar.gz(4.97 MB)
  • webmagic-0.5.3(Jan 21, 2016)

    时隔一年半,作者终于回归了。这个版本主要解决之前的一些BUG,后续会慢慢的继续完善功能。

    • 升级Xsoup到0.3.1,支持//div[contains(@id,'te')]语法。
    • #245 升级Jsoup到1.8.3,解决n-th selector二进制不兼容的问题。
    • #139 修复JsonFilePipeline保存路径的问题
    • #144 修复@TargetUrl增加SourceRegion后取不到链接的问题
    • #157 修复FileCacheQueueScheduler中去重偶尔不工作的问题 @zhugw
    • #188 增加重试的间隔时间,默认为1秒 [@edwardsbean](ht[tps* //github.com/edwardsbean)
    • #193 修复分页功能MultiPagePipeline可能出现的并发问题 edwardsbean
    • #198 修正site.setHttpProxy()不起作用的bug @okuc
    Source code(tar.gz)
    Source code(zip)
  • WebMagic-0.5.2(Jun 4, 2014)

    此次主要包括对于Selector部分的重构,以及一些功能的完善和一些Bugfix。

    • 重构了Selector部分,使得结构更清晰,并且能够更好的支持链式的XPath抽取了。 [Issue #113]

    • 支持对于选取出来的结果,进行外部迭代。例如:

      List<Selectable> divs = html.xpath("//div").nodes();
      for (Selectable div : divs) {
          System.out.println(div.xpath("//h2").get());
      }
      
    • 增强自动编码识别机制,现在除了从HTTP头中,还会从HTML Meta信息中判断编码,感谢@fengwuze @sebastian1118提交代码和建议。[Issue #126]

    • 升级Xsoup版本为0.2.4,增加了判断XPath最终抽取结果(是元素还是属性)的API,完善了一些特殊字符处理的功能。

    • 增加PageMapper功能,以后可以在任何地方使用注解模式来解析页面了![Issue #120] 例如:

      public void process(Page page) {
              //新建Mapper,GithubRepo是一个带注解的POJO
              PageMapper<GithubRepo> githubRepoPageMapper = new PageMapper<GithubRepo>(GithubRepo.class);
              //直接解析页面,得到解析后的结果
              GithubRepo githubRepo = githubRepoPageMapper.get(page);
              page.putField("repo",githubRepo);
          }
      
    • 增加多个代理以及智能切换的支持,感谢@yxssfxwzy 贡献代码,使用Site.setHttpProxyPool可开启此功能。[Pull #128]

      public void process(Page page) {
              Site site = Site.me().setHttpProxyPool(
                      Lists.newArrayList(
                              new String[]{"192.168.0.2","8080"},
                              new String[]{"192.168.0.3","8080"}));
          }
      

    Bugfix:

    • 修复了JsonFilePipeline不能自动创建文件夹的问题。[Issue #122]
    • 修复了Jsonp在removePadding时,对于特殊字符匹配不当的问题。[Issue #124]
    • 修复了当JsonPathSelector选取的结果是非String类型时,类型转换出错的问题。[Issue #129]
    Source code(tar.gz)
    Source code(zip)
    all-dependencies-0.5.2.tar.gz(6.14 MB)
    webmagic-core-0.5.2-sources.jar(54.57 KB)
    webmagic-core-0.5.2.jar(93.15 KB)
    webmagic-extension-0.5.2-sources.jar(45.77 KB)
    webmagic-extension-0.5.2.jar(91.68 KB)
    xsoup-0.2.4-sources.jar(14.89 KB)
    xsoup-0.2.4.jar(38.83 KB)
  • WebMagic-0.5.1(May 2, 2014)

    此次更新主要包括Scheduler的一些改动,对于自己定制过Scheduler的用户,强烈推荐升级。

    • 修复了RedisScheduler无法去重的BUG,感谢@codev777 仔细测试并发现问题。 #117
    • 对Scheduler进行了重构,新增了接口DuplicateRemover,将去重单独抽象出来,以便在同一个Scheduler中选择不同的去重方式。 #118
    • 增加了BloomFilter去重方式。BloomFilter是一种可以用极少的内存消耗完成大量URL去重的数据结构,缺点是会有少量非重复的URL被判断为重复,导致URL丢失(小于0.5%)。

    使用以下的方式即可将默认的HashSet去重改为BloomFilter去重:

    spider.setScheduler(new QueueScheduler()
    .setDuplicateRemover(new BloomFilterDuplicateRemover(10000000)) //10000000是估计的页面数量
    
    Source code(tar.gz)
    Source code(zip)
    all-dependencies-0.5.1.tar.gz(6.12 MB)
    webmagic-core-0.5.1-sources.jar(47.00 KB)
    webmagic-core-0.5.1.jar(77.53 KB)
    webmagic-extension-0.5.1-sources.jar(43.59 KB)
    webmagic-extension-0.5.1.jar(86.50 KB)
  • WebMagic-0.5.0(Apr 27, 2014)

    此次更新主要增加了监控功能,同时重写了多线程部分,使得多线程下性能有了极大的提升。另外还包含注解模式一些优化、多页面的支持等功能。

    项目总体进展:

    • 官网webmagic.io上线了!同时上线的还有详细版的官方文档http://webmagic.io/docs,从此使用更加简单!
    • 新增三名合作开发者@ccliangbo @ouyanghuangzheng @linkerlin ,一起参与项目的维护。
    • 官方论坛http://bbs.webmagic.io/和官方QQ群373225642上线,以后会更加重视社区的建设。

    监控部分:

    多线程部分:

    • 重写了多线程部分,修复了多线程下,主分发线程会被工作线程阻塞的问题,使得多线程下效率有了极大的提升,推荐所有用户升级。 #110
    • 为主线程等待新URL时的wait/notify机制增加了timeout时间,防止少数情况下发生的爬虫卡死的情况。 #111

    抽取API部分:

    • 增加了JSON的支持,现在可以使用page.getJson().jsonPath()来使用jsonPath解析AJAX请求,也可以使用page.getJson().removePadding().jsonPath()来解析JSONP请求。 #101
    • 修复一个Selectable的缓存导致两次取出的结果不一致的问题。 #73 感谢@seveniu 发现问题
    • 支持为一个Spider添加多个PageProcessor,并按照URL区分,感谢@sebastian1118 提交patch。使用示例:PatternProcessorExample #86
    • 修复不常用标签无法使用nth-of-type选择的问题(例如//div/svg[2]) 。#75
    • 修复XPath中包含特殊字符,即使转义也会导致解析失败的问题。#77

    注解模式:

    • 注解模式现在支持继承了!父类的注解将对子类也有效。#103
    • 修复注解模式下,一个Spider使用多个Model时,可能不生效的问题,感谢 @ccliangbo 发现此问题。#85
    • 修复sourceRegion中只有一个URL会被抽取出来的问题,感谢@jsinak 发现此问题。#107
    • 修复了自动类型转换Formatter的一个BUG,现在可以自定义Formatter了。如果你不了解Formatter可以看这里:注解模式下结果的类型转换 #100

    其他组件:

    • Downloader现在支持除了GET之外的其他几种HTTP请求了,包括POST、HEAD、PUT、DELETE、TRACE,感谢@usenrong 提出建议。 #108
    • Site中设置Cookie时,可以指定域名,而不是只能使用默认域名了。 #109
    • setScheduler()方法在调用时,如果之前Scheduler已有URL,会先转移到新的Scheduler,避免URL丢失。 #104
    • 在发布包中去掉了log4j.xml,避免与用户程序冲突,感谢@cnjavaer 发现问题。 #82
    Source code(tar.gz)
    Source code(zip)
    all-dependencies-0.5.0.tar.gz(6.12 MB)
    webmagic-core-0.5.0-sources.jar(45.19 KB)
    webmagic-core-0.5.0.jar(75.14 KB)
    webmagic-extension-0.5.0-sources.jar(43.58 KB)
    webmagic-extension-0.5.0.jar(86.42 KB)
  • webmaigc-0.4.3(Mar 12, 2014)

    Bugfix:

    • Fix cycleRetryTimes does not work #58 #60 #62 @yxssfxwzy
    • Fix NullPointerException in FileCachedQueueScheduler #53 @xuchaoo
    • Fix Selenium does not quit #57 @d0ngw

    Enhancement:

    • Enhance RegexSelector group check #51 @SimpleExpress
    • Add XPath syntax support: #64 contains,or/and,"|"
    • Add text attribute select to CssSelector #66
    • Change logger to slf4j #55
    • Update HttpClient version to 4.3.3 #59
    Source code(tar.gz)
    Source code(zip)
  • webmagic-0.4.2(Dec 3, 2013)

    Enhancement: #45 Remove multi option in ExtractBy. Auto detect whether is multi be field type. Bugfix: #46 Downloader thread hang up sometiems.

    Source code(tar.gz)
    Source code(zip)
  • webmagic-0.4.1(Nov 28, 2013)

    More support for ajax:

    • #39 Parsing html after page.getHtml()
    • #42 Add jsonpath support in annotation mode
    • #35 Add more http info to page
    • #41 Add more status monitor method to Spider
    Source code(tar.gz)
    Source code(zip)
  • webmagic-0.4.0(Nov 6, 2013)

    Improve performance of Downloader.

    • Update HttpClient to 4.3.1 and rewrite the code of HttpClientDownloader #32.
    • Use gzip by default to reduce the transport cost #31.
    • Enable HTTP Keep-Alive and connection persistence, fix the wrong usage of PoolConnectionManage r#30.

    The performance of Downloader is improved by 90% in my test.Test code: Kr36NewsModel.java.

    Add synchronzing API for small task #28.

            OOSpider ooSpider = OOSpider.create(Site.me().setSleepTime(100), BaiduBaike.class);
            BaiduBaike baike = ooSpider.<BaiduBaike>get("http://baike.baidu.com/search/word?word=httpclient&pic=1&sug=1&enc=utf8");
            System.out.println(baike);
    

    More config for site

    • Http proxy support by Site.setHttpProxy #22.
    • More http header customizing support by Site.addHeader #27.
    • Allow disable gzip by Site.setUseGzip(false).
    • Move Site.addStartUrl to Spider.addUrl because I think startUrl is more a Spider's property than Site.

    Code refactor in Spider

    • Refactor the multi-thread part of Spider and fix some concurrent problem.
    • Import Google Guava API for simpler code.
    • Allow add request with more information by Spider.addRequest() instead of addUrl #29.
    • Allow just downloading start urls without spawn urls extracted by Spider.setSpawnUrl(false).
    Source code(tar.gz)
    Source code(zip)
  • webmagic-0.3.2(Sep 23, 2013)

    • #13 Add class cast to annotation crawler.
    • Allow customize class caster by implementing ObjectFormatter and register it in ObjectFormatters.put().
    • Fix a thread pool reject exception when call Spider.stop()
    Source code(tar.gz)
    Source code(zip)
  • webmagic-parent-0.3.1(Sep 8, 2013)

    • #26 Bugfix: Annotation extractor does not work.
    • #25 Bugfix: UrlUtils.canonicalizeUrl does not work with "../../" path.
    • #24 Enhancement: Add stop method to Spider.
    Source code(tar.gz)
    Source code(zip)
  • webmagic-0.3.0(Sep 3, 2013)

    • Change default XPath selector from HtmlCleaner to Xsoup.

      Xsoup is an XPath selector based on Jsoup written by me. It has much better performance than HtmlCleaner.

      Time of processing a page is reduced from 7~9ms to 0.4ms.

      If Xsoup is not stable for your usage, just use Spider.xsoupOff() to turn off it and report an issue to me!

    • Add cycle retry times for Site.

      When cycle retry times is set, Spider will put the url which downloading failed back to scheduler, and retry after a cycle of queue.

    Source code(tar.gz)
    Source code(zip)
  • version-0.2.0(Aug 30, 2013)

    此次更新的主题是"方便"(之前的主题是"灵活")。

    增加了webmagic-extension模块。

    增加了注解方式支持,可以通过POJO+注解的方式编写一个爬虫,更符合Java开发习惯。以下是抓取一个博客的完整代码:

        @TargetUrl("http://my.oschina.net/flashsword/blog/\\d+")
        public class OschinaBlog {
    
            @ExtractBy("//title")
            private String title;
    
            @ExtractBy(value = "div.BlogContent",type = ExtractBy.Type.Css)
            private String content;
    
            @ExtractBy(value = "//div[@class='BlogTags']/a/text()", multi = true)
            private List<String> tags;
    
            public static void main(String[] args) {
                OOSpider.create(Site.me().addStartUrl("http://my.oschina.net/flashsword/blog"),
                new ConsolePageModelPipeline(), OschinaBlog.class)
                .scheduler(new RedisScheduler("127.0.0.1")).thread(5).run();
            }
    
        }
    

    增加一个Spider.test(url)方法,用于开发爬虫时进行调试。

    增加基于redis的分布式支持。

    增加XPath2.0语法支持(webmagic-saxon模块)。

    增加基于Selenium的浏览器渲染支持,用于抓取动态加载内容(webmagic-selenium模块)。

    修复了不支持https的bug。

    补充了文档:webmagic-0.2.0用户手册

    Source code(tar.gz)
    Source code(zip)
  • webmagic-parent-0.2.1(Aug 20, 2013)

    ComboExtractor support for annotation.

    Request priority support (using PriorityScheduler).

    Complete some I18n work (comments and documents).

    More convenient extractor API:

    • Add attribute name select for CSSSelector.

    • Group of regex selector can be specified.

    • Add OrSelector.

    • Add Selectors, import static Selectors.* for fluent API such as:

      or(regex("<title>(.*)</title>"), xpath("//title"), $("title")).select(s);
      
    • Add JsonPathSelector for Json parse.

    Source code(tar.gz)
    Source code(zip)
  • version-0.1.0(Jul 25, 2013)

    第一个稳定版本。

    修改了若干API,使得可扩展性更强,为每个任务分配一个ID,可以通过ID区分不同任务。

    重写了Pipeline接口,将抽取结果集包装到ResultItems对象,而不是通用一个Page对象,便于逻辑分离。

    增加下载的重试机制,支持gzip,支持自定义UA/cookie。

    增加多线程抓取功能,只需在初始化的时候指定线程数即可。

    增加jquery形式的CSS Selector API,可以通过page.getHtml().$("div.body")形式抽取元素。

    完善了文档,架构说明:webmagic的设计机制及原理-如何开发一个Java爬虫,Javadoc:http://code4craft.github.io/webmagic/docs

    Source code(tar.gz)
    Source code(zip)
An implementation of darcy-web that uses Selenium WebDriver as the automation library backend.

darcy-webdriver An implementation of darcy-ui and darcy-web that uses Selenium WebDriver as the automation library backend. maven <dependency> <gr

darcy framework 20 Aug 22, 2020
This is public repository for Selenium Learners at TestLeaf

Selenium WebDriver Course for March 2021 Online Learners This is public repository for Selenium Learners at TestLeaf. Week1 - Core Java Basics How Jav

TestLeaf 74 Sep 18, 2021
Concise UI Tests with Java!

Selenide = UI Testing Framework powered by Selenium WebDriver What is Selenide? Selenide is a framework for writing easy-to-read and easy-to-maintain

Selenide 1.4k Sep 18, 2021
jQuery-like cross-driver interface in Java for Selenium WebDriver

seleniumQuery Feature-rich jQuery-like Java interface for Selenium WebDriver seleniumQuery is a feature-rich cross-driver Java library that brings a j

null 70 Jun 15, 2021
jsoup: the Java HTML parser, built for HTML editing, cleaning, scraping, and XSS safety.

jsoup: Java HTML Parser jsoup is a Java library for working with real-world HTML. It provides a very convenient API for fetching URLs and extracting a

Jonathan Hedley 9k Sep 7, 2021
Automated driver management for Selenium WebDriver

WebDriverManager is a library which allows to automate the management of the drivers (e.g. chromedriver, geckodriver, etc.) required by Selenium WebDr

Boni García 1.7k Sep 13, 2021
A pure-Java Markdown processor based on a parboiled PEG parser supporting a number of extensions

:>>> DEPRECATION NOTE <<<: Although still one of the most popular Markdown parsing libraries for the JVM, pegdown has reached its end of life. The pro

Mathias 1.3k Sep 17, 2021
ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files.

ANTLR v4 Build status ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating

Antlr Project 10.6k Sep 13, 2021
Nokogiri (鋸) is a Rubygem providing HTML, XML, SAX, and Reader parsers with XPath and CSS selector support.

Nokogiri Nokogiri (鋸) makes it easy and painless to work with XML and HTML from Ruby. It provides a sensible, easy-to-understand API for reading, writ

Sparkle Motion 5.7k Sep 9, 2021
Elegant parsing in Java and Scala - lightweight, easy-to-use, powerful.

Please see https://repo1.maven.org/maven2/org/parboiled/ for download access to the artifacts https://github.com/sirthias/parboiled/wiki for all docum

Mathias 1.2k Sep 4, 2021