SeimiCrawler一個敏捷強大的Java爬蟲框架 — SeimiCrawler 0.2.6 文檔

jopen 8年前發布 | 40K 次閱讀 網絡爬蟲

SeimiCrawler一個敏捷強大的Java爬蟲框架?

An agile,powerful,standalone,distributed crawler framework.

SeimiCrawler的目標是成為Java世界最好用最實用的爬蟲框架。

1.簡介 ?

SeimiCrawler是一個敏捷的,獨立部署的,支持分布式的Java爬蟲框架,希望能在最大程度上降低新手開發一個可用性高且性能不差的爬蟲系統的門檻,以及提升開發爬蟲系統的開發效率。在SeimiCrawler的世界里,絕大多數人只需關心去寫抓取的業務邏輯就夠了,其余的Seimi幫你搞定。設計思想上SeimiCrawler受Python的爬蟲框架Scrapy啟發很大,同時融合了Java語言本身特點與Spring的特性,并希望在國內更方便且普遍的使用更有效率的XPath解析HTML,所以SeimiCrawler默認的HTML解析器是JsoupXpath(獨立擴展項目,非jsoup自帶),默認解析提取HTML數據工作均使用XPath來完成(當然,數據處理亦可以自行選擇其他解析器)。

2.社區討論 ?

大家有什么問題或建議現在都可以選擇通過下面的郵件列表討論,首次發言前需先訂閱并等待審核通過(主要用來屏蔽廣告宣傳等,給大家創造良好的討論環境)

  • 訂閱:請發郵件到 seimicrawler+subscribe@googlegroups.com
  • 發言:請發郵件到 seimicrawler@googlegroups.com
  • 退訂:請發郵件至 seimicrawler+unsubscribe@googlegroups.com

3.快速開始 ?

添加maven依賴(中央maven庫最新版本0.2.6):

<dependency>
    <groupId>cn.wanghaomiao</groupId>
    <artifactId>SeimiCrawler</artifactId>
    <version>0.2.6</version>
</dependency>

在包crawlers下添加爬蟲規則,例如:

@Crawler(name = "basic")
public class Basic extends BaseSeimiCrawler {
    @Override
    public String[] startUrls() {
        return new String[]{"http://www.cnblogs.com/"};
    }
    @Override
    public void start(Response response) {
        JXDocument doc = response.document();
        try {
            List<Object> urls = doc.sel("http://a[@class='titlelnk']/@href");
            logger.info("{}", urls.size());
            for (Object s:urls){
                push(new Request(s.toString(),"getTitle"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void getTitle(Response response){
        JXDocument doc = response.document();
        try {
            logger.info("url:{} {}", response.getUrl(), doc.sel("http://h1[@class='postTitle']/a/text()|//a[@id='cb_post_title_url']/text()"));
            //do something
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后隨便某個包下添加啟動Main函數,啟動SeimiCrawler:

public class Boot {
    public static void main(String[] args){
        Seimi s = new Seimi();
        s.start("basic");
    }
}

以上便是一個最簡單的爬蟲系統開發流程。

4.原理 ?

4.1.基本原理 ?

SeimiCrawler原理圖

4.2.集群原理 ?

SeimiCrawler集群原理圖

5.如何開發 ?

5.1.約定 ?

之所以要有一些約定,主要目的是讓使用SeimiCrawler開發的爬蟲系統的源碼更加的規范可讀,大家都遵守一個約定,那么在團隊成員相互協作開發的過程中,業務工程的代碼在團隊成員間就會更加的易讀,易改。不至于某人開發了一個業務邏輯,另一個接手的人連到哪里去找他的類都很困難,這不是我們要的。我們要強大,簡單,好用。最后,有約定不代表SeimiCrawler不夠靈活。

  • 由于SeimiCrawler的context基于spring實現,所以支持幾乎所有spring格式的配置文件和spring通常用法。SeimiCrawler會掃描工程classpath下所有xml格式配置文件,但是只有文件名以seimi開頭的xml配置文件能被SeimiCrawler識別并加載。
  • SeimiCrawler的日志使用slf4j,可自行配置具體的實現。
  • Seimi開發時要注意的約定,會在下面的開發要點中一一介紹。

5.2.第一個爬蟲規則類-crawler ?

爬蟲規則類是使用SeimiCrawler開發爬蟲最核心的部分,快速開始中的Basic類就是一個基本的爬蟲類。寫一個crawler需注意一下幾點:

  • 需繼承BaseSeimiCrawler
  • 需打上@Crawler注解,注解中name屬性是可有可無的,如果設置了,那么這個crawler則以你定義的名字命名,否則默認使用你創建的類名。
  • 所有想要被SeimiCrawler掃描到的crawler需放在crawlers包下,如:cn.wanghaomiao.xxx.crawlers,也可以參考項目附帶的demo工程。 初始化好Crawler后,你需要實現兩個最基本的方法public String[] startUrls();public void start(Response response),實現后一個簡單的爬蟲就算寫完了。

5.2.1.注解@Crawler ?

目前@Crawler注解有下面幾個屬性:

  • name 自定義一個爬蟲規則的名字,一個SeimiCrawler可掃描范圍內的工程中不能有同名的。默認使用類名。
  • proxy 告訴Seimi這個爬蟲是否使用代理,以及使用什么樣的代理。目前支持三種格式http|https|socket://host:port,這一版還沒支持帶用戶名和密碼的代理。
  • useCookie 是否啟用cookies,啟用后即可像瀏覽器一樣保持你的請求狀態,同樣的也會被追蹤。
  • queue 指定當前這個爬蟲要使用的數據隊列,默認的是本地隊列實現DefaultLocalQueue.class,也可以配置使用默認的redis版實現或是自行基于其他隊列系統的實現,這個后面會進行更為詳細的介紹。
  • delay 設置請求抓取的時間間隔單位為秒,默認為0即沒有間隔。

5.2.2.實現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的處理。

5.2.3.實現start(Response response) ?

這個方法是針對startURL的回調函數,即告訴Seimi如何處理請求startURL返回的數據。

5.2.4.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)進行存儲或做其他操作。

5.2.5.回調函數 ?

使用默認的一個回調函數顯然是不能滿足你的要求的,如果你還想把startURL頁面中的某些URL提取出來再進行請求獲取數據并進行處理的話,你就需要自定義回調函數了。注意點如下:

  • 在回調函數里的產生的Request可以指定其他回調函數也可以指定自己為回調函數。
  • 作為回調函數需滿足這個格式:public void callbackName(Response response),即方法是公有的,有且只能有一個參數Response,沒有返回值。
  • Request設置一個回調函數只需提供這個回調函數的String類型的名稱即可,如:快速開始中那個getTitle
  • 繼承了BaseSeimiCrawler的Crawler可以在回調函數內直接調用父類的push(Request request)將新的抓取請求發送掉請求隊列。
  • 可以通過new Request()或是Request.build()創建Request

5.2.6.自定義UserAgent(可選) ?

SeimiCrawler的默認UA為SeimiCrawler/JsoupXpath,如果想自定義UserAgent可以覆蓋BaseSeimiCrawlerpublic String getUserAgent(),每次處理請求時SeimiCrawler都會獲取一次UserAgent,所以如果你想偽裝UserAgent的話可以自行實現一個UA庫,每次隨機返回一個。

5.2.7.啟用cookies(可選) ?

在介紹@Crawler注解時已經對其介紹過了,這里再次強調主要是方便快速瀏覽這些基本功能,是否啟用cookies是通過@Crawler注解中的useCookie屬性來進行配置。

5.2.8.啟用proxy(可選) ?

通過@Crawler注解中的proxy屬性來進行配置,具體請參考@Crawler的介紹,如果希望能動態的指定proxy,請移步下文“設置動態代理”

5.2.9.設置delay(可選)* ?

通過@Crawler注解中的delay屬性來進行配置,設置請求抓取的時間間隔單位為秒,默認為0即沒有間隔。在很多情況下內容方都會把請求頻率的限制作為反爬蟲的一種手段,所以需要的情況可以自行調整添加這個參數來實現更好的抓取效果。

5.2.10.設置請求URL白名單匹配規則 ?

通過override BaseSeimiCrawlerpublic String[] allowRules()來設置URL請求白名單規則,規則為正則表達式,匹配到任意一條即放行。

5.2.11.設置請求URL黑名單匹配規則 ?

通過override BaseSeimiCrawlerpublic String[] denyRules()來設置URL請求黑名單規則,規則為正則表達式,匹配到任意一條即阻止請求。

5.2.12.設置動態代理 ?

通過override BaseSeimiCrawlerpublic String proxy()來告訴Seimi某一次請求使用哪個代理地址,這里可以自行從已有代理庫用順序或是隨機返回一個代理地址。且只要這個代理地址非空,那么在@Crawlerproxy屬性設置則失效。

5.2.13.是否開啟系統去重 ?

通過@Crawler注解中的useUnrepeated屬性來控制是否開啟系統去重,默認開啟

5.2.14.關于自動跳轉 ?

目前SeimiCrawler支持301、302以及meta refresh跳轉,對于這類跳轉URL,可以通過Response對象的getRealUrl()獲取內容對應重定向或是跳轉后的真實連接

5.2.15.啟動爬蟲系統 ?

有了爬蟲規則,就可以啟動爬蟲系統進行抓取了。要啟動爬蟲系統,您需要一個main函數,最好獨立的一個啟動類,就像demo工程中的那樣。在main函數中,初始化Seimi這個對象,例如:

public class Boot {
    public static void main(String[] args){
        Seimi s = new Seimi();
        s.start("basic");
    }
}

Seimi包含了三個啟動函數,分別是:

  • public void start(String... crawlerNames)指定一個或多個Crawler開始執行抓取。
  • public void startAll()啟動全部被加載到的Crawler。
  • public void startWithHttpd(int port,String... crawlerNames)指定一個Crawler開始執行抓取,并為之啟動一個指定端口的http服務,可通過/push/crawlerName推送一個抓取請求給對應的Crawler,接收參數為req,支持POST和GET。
  • public void startWorkers()只初始化所有被加載到的Crawler,并監聽抓取請求。這個啟動函數主要用來在分布式部署的情況下啟動一個或多個單純的worker系統,這在后面關于如何進行以及支持分布式部署時會有更為細致的介紹

在工程下執行下面的命令打包并輸出整個工程,

Windows下為了避免在windows控制臺下日志輸出亂碼,請自行修改logback配置文件中控制臺輸出格式為GBK,默認UTF-8
mvn clean package&&mvn -U compile dependency:copy-dependencies -DoutputDirectory=./target/seimi/&&cp ./target/*.jar ./target/seimi/

這時在工程的target目錄下會有一個叫做seimi的目錄,這個目錄就是我們最終編譯好的可部署的工程,然后執行下面的命令進行啟動,

Windows下:

java -cp .;./target/seimi/* cn.wanghaomiao.main.Boot

Linux下:

java -cp .:./target/seimi/* cn.wanghaomiao.main.Boot

以上可以自行寫入腳本,目錄也可以看自行情況進行調整,上面僅是針對demo工程做的一個樣例。

</div>

5.3.工程化打包部署 ?

上面介紹的可以方便的用來開發或是調試,當然也可以成為生產環境下一種啟動方式。但是,為了便于工程化部署與分發,SeimiCrawler提供了專門的打包插件用來對SeimiCrawler工程進行打包,打好的包可以直接分發部署運行了。你只需做如下幾件事即可:

pom中添加添加plugin

<plugin>
    <groupId>cn.wanghaomiao</groupId>
    <artifactId>maven-seimicrawler-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <!--<configuration>-->
        <!-- 默認target目錄 -->
        <!--<outputDirectory>/some/path</outputDirectory>-->
    <!--</configuration>-->
</plugin>

執行mvn clean package即可,打好包目錄結構如下:

.
├── bin             # 相應的腳本中也有具體啟動參數說明介紹,在此不再敖述
│   ├── run.bat    # windows下啟動腳本
│   └── run.sh     # Linux下啟動腳本
└── seimi
    ├── classes     # Crawler工程業務類及相關配置文件目錄
    └── lib         # 工程依賴包目錄

接下來就可以直接用來分發與部署了。

5.4.自動解析Bean ?

如果你希望定義一個Bean,SeimiCrawler可以根據你定義的規則自動將數據提取出來并填充到相應的字段上,這時你就需要這個功能了。

5.4.1.注解@Xpath ?

先看個例子:

public class BlogContent {
    @Xpath("http://h1[@class='postTitle']/a/text()|//a[@id='cb_post_title_url']/text()")
    private String title;
    //也可以這么寫 @Xpath("http://div[@id='cnblogs_post_body']//text()")
    @Xpath("http://div[@id='cnblogs_post_body']/allText()")
    private String content;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}

BlogContent即是你定義的一個目標Bean,@Xpath需打在你想要注入數據的字段上,并為之配置一個XPath提取規則,不要求字段的私有與公有,亦不要求一定存在getter與setter。

5.4.2.使用 ?

準備好Bean后,在回調函數中就可以使用Response內置函數public <T> T render(Class<T> bean)獲取填充好數據的Bean對象。

</div>

5.5.攔截器 ?

SeimiCrawler還支持給特定或所有的回調函數添加攔截器。實現一個攔截器需注意如下幾點:

  • 需打上@Interceptor注解
  • 需實現SeimiInterceptor接口
  • 所有想要被掃描生效的攔截器需放在interceptors包下,如cn.wanghaomiao.xxx.interceptors,demo工程中也有樣例。
  • 需自定義注解用來標記哪些函數需要被攔截或是全部攔截。

5.5.1.注解@Interceptor ?

這個注解用來告訴Seimi,被它標注的類可能是一個攔截器(因為作為一個真正的Seimi攔截器還要符合上述其他約定)。它有一個屬性,

  • everyMethod 默認false,用來告訴Seimi這個攔截器是否要對所有回調函數進行攔截。

5.5.2.接口SeimiInterceptor ?

直接上接口,

public interface SeimiInterceptor {
    /**
     * 獲取目標方法應標記的注解
     * @return Annotation
     */
    public Class<? extends Annotation> getTargetAnnotationClass();
    /**
     * 當需要控制多個攔截器執行的先后順序時可以重寫這個方法
     * @return 權重,權重越大越在外層,優先攔截
     */
    public int getWeight();
    /**
     * 可以在目標方法執行之前定義一些處理邏輯
     */
    public void before(Method method,Response response);
    /**
     * 可以在目標方法執行之后定義一些處理邏輯
     */
    public void after(Method method,Response response);
}

注釋中已經解釋的很清楚了,這里就不在多說了。

5.5.3.攔截器樣例 ?

參考demo工程中的DemoInterceptor,gitHub地址直達

</div>

5.6.關于SeimiQueue ?

SeimiQueue是SeimiCrawler進行數據中轉以及系統內部和系統間相互通信的唯一通道。系統默認采用的SeimiQueue是基于本地的一個線程安全的阻塞隊列的一個實現。同時SeimiCrawler也支持了一個基于redis的SeimiQueue的實現–DefaultRedisQueue,當然也可以自行實現符合Seimi約定的SeimiQueue,具體使用時可以通過注解@Crawler中的queue屬性來指定一個Crawler到底使用哪一種實現。

5.6.1.配置使用DefaultRedisQueue ?

Crawler的注解設置為@Crawler(name = "xx",queue = DefaultRedisQueue.class),默認DefaultRedisQueue的redis配置信息獲取方式為spring的取值表達式:

@Value("${redis.host:127.0.0.1}")
private String host;
@Value("${redis.port:6379}")
private int port;
@Value("${redis.password:}")
private String password;

所以還需要配置相應屬性注入到spring的環境中,在項目的classpath下建立配置文件seimi.xml,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--配置Seimi默認的基于redis數據隊列的網絡相關配置-->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:**/*.properties</value>
            </list>
        </property>
    </bean>
</beans>

再在classpath下(demo中為resources/config/seimi.properties)建立seimi.properties,配置:

redis.host=192.168.1.100
redis.port=6379
redis.password=

這樣在系統啟動后,redis的配置信息就會被注入到DefaultRedisQueue中。

5.6.2.自行實現SeimiQueue ?

通常來講,SeimiCrawler自帶的兩個實現基本足夠應付絕大多數的使用場合,但是實在有應付不了的,那么您亦可自行實現SeimiQueue并配置使用。自行實現需要注意的事項有:

  • 需打上@Queue注解,用來告訴Seimi這個被標記的類可能是一個SeimiQueue(成為SeimiQueue還要滿足其他條件)。
  • 需實現SeimiQueue接口,如下:
/**
 * 定義系統隊列的基本接口,可自由選擇實現,只要符合規范就行。
 * @author 汪浩淼 et.tw@163.com
 * @since 2015/6/2.
 */
public interface SeimiQueue {
    /**
     * 阻塞式出隊一個請求
     * @return
     */
    Request bPop(String crawlerName);
    /**
     * 入隊一個請求
     * @param req
     * @return
     */
    boolean push(Request req);
    /**
     * 任務隊列剩余長度
     * @return
     */
    int len(String crawlerName);
}
  • 所有想要被掃描生效的SeimiQueue需放在queues包下,如cn.wanghaomiao.xxx.queues,demo工程中也有樣例。 滿足以上要求,寫好自己的SeimiQueue后,通過注解@Crawler(name = "xx",queue = YourSelfRedisQueueImpl.class)來配置使用。

5.6.3.SeimiQueue樣例 ?

參考demo工程中的DefaultRedisQueueEG(github直達鏈接)和SelfConfigRedisQueueEG(github直達鏈接)

</div>

5.7.集成主流數據持久化 ?

由于SeimiCrawler使用spring來管理bean以及進行依賴注入,所以很容易就能集成現有的主流數據持久化方案,如Mybatis,Hibernate,Paoding-jade等,在這里采用Paoding-jade(想進一步了解請移步Paoding-rose||文檔)做示例介紹。

5.7.1.準備工作 ?

添加paoding-jade以及數據庫連接相關依賴:

<dependency>
    <groupId>net.paoding</groupId>
    <artifactId>paoding-rose-jade</artifactId>
    <version>2.0.u01</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.4.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
</dependency>

添加一個xml配置文件seimi-jade.xml(還記得配置文件都要以seimi打頭對吧)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
       <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
           <property name="driverClassName" value="${database.driverClassName}" />
           <property name="url" value="${database.url}" />
           <property name="username" value="${database.username}" />
           <property name="password" value="${database.password}" />
       </bean>
       <!-- 啟用Jade -->
       <bean class="net.paoding.rose.jade.context.spring.JadeBeanFactoryPostProcessor" />
</beans>

由于demo工程中存在統一配置文件seimi.properties,所以數據庫連接相關信息也通過properties注入進去,當然這里你也可以直接寫進去的。properties配置如下:

database.driverClassName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://127.0.0.1:3306/xiaohuo?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&autoReconnectForPools=true&zeroDateTimeBehavior=convertToNull
database.username=xiaohuo
database.password=xiaohuo

工程上到目前為止已經準備好了,剩下需要你創建一個數據庫和表,用來存儲實驗的信息,demo工程給出了表的結構,庫名可以自行調整:

CREATE TABLE `blog` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(300) DEFAULT NULL,
  `content` text,
  `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.7.2.寫一個DAO ?

創建一個paoding-jade的DAO文件:

@DAO
public interface StoreToDbDAO {
    @ReturnGeneratedKeys
    @SQL("insert into blog (title,content,update_time) values (:1.title,:1.content,now())")
    public int save(BlogContent blog);
}

jade用起來還是挺方便快捷的吧

5.7.3.開始使用DAO ?

在相應的Crawler中直接注入即可,如:

@Crawler(name = "storedb")
public class StoreInDB extends BaseSeimiCrawler {
    @Autowired
    private StoreToDbDAO storeToDbDAO;
    @Override
    public String[] startUrls() {
        return new String[]{"http://www.cnblogs.com/"};
    }
    @Override
    public void start(Response response) {
        JXDocument doc = response.document();
        try {
            List<Object> urls = doc.sel("http://a[@class='titlelnk']/@href");
            logger.info("{}", urls.size());
            for (Object s:urls){
                push(Request.build(s.toString(),"renderBean"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void renderBean(Response response){
        try {
            BlogContent blog = response.render(BlogContent.class);
            logger.info("bean resolve res={},url={}",blog,response.getUrl());
            //使用神器paoding-jade存儲到DB
            int blogId = storeToDbDAO.save(blog);
            logger.info("store sus,blogId = {}",blogId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

當然,如果業務很復雜的話,建議再封裝一層service,然后將service注入到Crawler中。

</div>

5.8.分布式 ?

當你的業務量與數據量達到一定程度的時候,你自然就需要水平擴展多臺機器構建一個集群服務來提高處理能力,這是SeimiCrawler在設計之初就考慮的問題。所以SeimiCrawler先天就是支持分布式部署的。在上文介紹SeimiQueue相信聰明的你已經知道如何進行分布式部署了。SeimiCrawler實現分布式部署需啟用DefaultRedisQueue作為默認的SeimiQueue并在每臺要部署的機器上為之配置相同的redis連接信息,具體上文已有說明這里就不再啰嗦了。啟用DefaultRedisQueue后,在作為worker的機器上通過new Seimi().startWorkers()初始化seimi的處理器,Seimi的worker進程就會開始監聽消息隊列,當主服務發出抓取請求后,整個集群就開始通過消息隊列進行通信,分工合作、熱火朝天的干活了。

5.9.內嵌http服務接口 ?

SeimiCrawler可以通過選擇啟動函數指定一個端口開始內嵌http服務用來通過httpAPI接收抓取請求或是查看對應的Crawler抓取狀態。

5.9.1.發送抓取請求 ?

通過http接口發送給SeimiCrawler的Json格式的Request請求。http接口接收到抓取請求進行基本校驗沒有問題后就會與處理規則中產生的請求一起處理了。

5.9.1.1.接口描述 ?

  • 請求地址: http://host:port/push/${YourCrawlerName}
  • 調用方式: GET/POST
  • 輸入參數:
參數名稱 是否必選 參數類型 參數說明
req true str 內容為Request請求的json形式
  • 參數結構示例:
{
  "callBack": "start",
  "maxReqCount": 3,
  "meta": {
    "listPageSomeKey": "xpxp"
  },
  "params": {
    "paramName": "xxxxx"
  },
  "stop": false,
  "url": "http://www.github.com"
}

結構字段說明:

Json字段 是否必選 字段類型 字段說明
url true str 請求目標地址
callBack true str 針對對應請求結果的回調函數
meta false map 可選擇向下文傳遞的一些自定義數據
params false map 針對當前請求可能需要的請求參數
stop false bool 如果為true,那么收到該請求的工作線程會停止工作
maxReqCount false int 如果這個請求處理異常,允許的最大重新處理次數

</div>

5.9.2.查看抓取狀態 ?

請求地址:/status/${YourCrawlerName} 即可查看一些基本的關于所指定Crawler的當前抓取狀態,數據格式為Json。

</div> </div>

6.未來TODO ?

  • 持續改進完善中敬請期待
  • </ul> </div>

    7.項目源碼 ?

    Github

    BTW: 如果您覺著這個項目不錯,到github上 star一下,我是不介意的 ^_^
    </div>

    來自: http://seimi.wanghaomiao.cn/

     本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!