WebMagic Java Crawler Framework

repository·develop·Indexed 11 days ago

https://github.com/code4craft/webmagic

A scalable Java crawler framework for managing the full lifecycle of web crawling, including downloading, URL management, content extraction, and data persistence. It offers multiple development modes: a standard approach via the PageProcessor interface, a declarative approach using annotations (OOSpider) in the webmagic-extension module, and a scripting approach using JavaScript or Ruby via the webmagic-console. Extensions provide support for XPath 2.0 via Saxon, JSON, distributed crawling, and AJAX-heavy pages via Selenium integration.

Tokens
7.9K
Snippets
20
Records
31
Agent score
93%

What's inside WebMagic

  1. Overview of webmagic-core

    develop
    The webmagic-core module is the fundamental component of the WebMagic framework. It provides the essential building blocks for web crawling, including the core crawler engine and basic extractors. It is designed to serve as a textbook-like implementation of a web crawler, focusing on the core logic required to navigate and extract data from web pages.
  2. Overview of webmagic-extension

    develop

    The webmagic-extension module provides extended capabilities for the WebMagic framework. It includes support for:

    • Annotation-based Crawler Definition: Define crawlers using annotations instead of manual configuration.
    • JSON Support: Integration for handling JSON data formats.
    • Distributed Support: Capabilities for running crawlers in a distributed environment.
  3. Integrate WebMagic with Selenium for AJAX crawling

    develop
    The webmagic-extension package provides integration between WebMagic and Selenium. This is specifically designed to enable crawling of AJAX-heavy pages that require JavaScript execution. Because Selenium is a heavy dependency, it is provided as a separate extension rather than being bundled with the core WebMagic library.
  4. Use webmagic-extension for XPath 2.0 support via Saxon

    develop
    The webmagic-extension module provides advanced XPath 2.0 parsing capabilities for WebMagic by integrating the Saxon library. Because the Saxon dependency is large, it is not included in the default WebMagic installation and must be added as an extension if XPath 2.0 support is required.
  5. Understand WebMagic Project Structure and Modules

    develop

    WebMagic is modularized into several packages depending on your requirements:

    • webmagic-core: The core engine containing basic crawler modules and extractors. It is designed to be a textbook implementation of a web crawler.
    • webmagic-extension: Provides tools for easier crawler development, including annotation-based crawler definitions, JSON support, and distributed crawling support.
    • webmagic-saxon (External): Provides XPath 2.0 support via the Saxon library. Requires manual compilation from source.
    • webmagic-selenium (External): Provides support for crawling dynamic pages using Selenium. Requires manual compilation from source.
  6. Create a crawler using PageProcessor

    develop

    The standard way to build a crawler is to implement the PageProcessor interface. In the process(Page page) method, you can:

    • Use page.addTargetRequests(links) to add new URLs for the crawler to visit.
    • Use page.putField(key, value) to extract and store data.
    • Use page.setSkip(true) to skip the current page if certain conditions are met.
    • Access HTML content via page.getHtml() using regex or XPath.

    To run the crawler, use Spider.create(processor).addUrl(url).thread(n).run().

    public class GithubRepoPageProcessor implements PageProcessor {
    
        private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
    
        @Override
        public void process(Page page) {
            // Add new URLs to crawl using regex
            page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
            
            // Extract data using regex or xpath
            page.putField("author", page.getUrl().regex("https://github\.com/(\w+)/.*").toString());
            page.putField("name", page.getHtml().xpath("//h1[@class='public']/strong/a/text()").toString());
            
            // Skip page if data is missing
            if (page.getResultItems().get("name") == null){
                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();
        }
    }
  7. Create a crawler by implementing PageProcessor

    develop

    The PageProcessor interface is part of webmagic-core. To implement custom crawling logic, implement this interface and use the process(Page page) method to define how to extract data and find new URLs.

    Key methods within process:

    • page.getHtml().links().regex(pattern).all(): Finds new URLs matching a regex pattern.
    • page.addTargetRequests(links): Adds discovered URLs to the crawler's queue.
    • page.putField(key, value): Saves extracted data into the page object.
    • page.getHtml().xpath(expression): Extracts data using XPath.
    • page.getHtml().$(selector): Extracts data using CSS selectors.

    Use the Spider class to run your crawler.

    public class OschinaBlogPageProcessor implements PageProcessor {
    
        private Site site = Site.me().setDomain("my.oschina.net");
    
        @Override
        public void process(Page page) {
            // 1. Find new links and add them as targets
            List<String> links = page.getHtml().links().regex("http://my\.oschina\.net/flashsword/blog/\d+").all();
            page.addTargetRequests(links);
    
            // 2. Extract data and put it into fields
            page.putField("title", page.getHtml().xpath("//div[@class='BlogEntity']/div[@class='BlogTitle']/h1").toString());
            page.putField("content", page.getHtml().$("div.content").toString());
            page.putField("tags", page.getHtml().xpath("//div[@class='BlogTags']/a/text()").all());
        }
    
        @Override
        public Site getSite() {
            return site;
        }
    
        public static void main(String[] args) {
            Spider.create(new OschinaBlogPageProcessor())
                 .addUrl("http://my.oschina.net/flashsword/blog")
                 .addPipeline(new ConsolePipeline())
                 .run();
        }
    }
  8. Create a crawler using Annotations (webmagic-extension)

    develop

    For a more declarative approach, use the webmagic-extension module. You can define a POJO and use annotations to map HTML elements to class fields. This is often cleaner and allows the model to be reused in Pipelines.

    Key Annotations:

    • @TargetUrl(pattern): Defines the URL pattern this crawler targets.
    • @ExtractBy(value, type): Maps a field to an HTML element.
      • value: The XPath or CSS selector.
      • type: The extraction type (e.g., ExtractBy.Type.Css).
      • multi = true: Use this for fields that should receive a List<String> (e.g., when extracting multiple elements).

    Use OOSpider (or the appropriate extension entry point) to run the annotated crawler.

    @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(),
                new ConsolePageModelPipeline(), 
                OschinaBlog.class
            ).addUrl("http://my.oschina.net/flashsword/blog").run();
        }
    }
  9. Install WebMagic via Maven

    develop

    WebMagic uses Maven for dependency management. To use the core functionality and extensions, add the following dependencies to your pom.xml.

    Note: WebMagic uses slf4j-log4j12 as its SLF4J implementation. If your project uses a different SLF4J implementation, you must exclude it to avoid conflicts.

    <dependency>
        <groupId>us.codecraft</groupId>
        <artifactId>webmagic-core</artifactId>
        <version>${webmagic.version}</version>
    </dependency>
    <dependency>
        <groupId>us.codecraft</groupId>
        <artifactId>webmagic-extension</artifactId>
        <version>${webmagic.version}</version>
    </dependency>
    
    <!-- If you have a custom SLF4J implementation, exclude the default one -->
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
    </exclusions>
  10. Run webmagic-scripts via the webmagic-console

    develop

    The webmagic-scripts module allows you to write web crawlers using simple scripts (JavaScript or Ruby) instead of full Java development. You can execute these scripts using the webmagic-console.jar without needing to manage dependencies or write Java code manually.

    Installation

    Download the console package: http://code4craft.qiniudn.com/webmagic-console.tar.gz

    Execution Command

    Use the following command structure to run a script:

    java -jar -Dfile.encoding='utf-8' webmagic-console.jar -f <script_file> [-l <language>] [-t <threads>] [-s <interval_ms>] <url1> <url2> ...

    CLI Flags

    FlagDescription
    -fThe filename of the script to execute.
    -lThe scripting language. Supported: javascript (default), ruby.
    -tNumber of threads to use.
    -sCrawl interval in milliseconds.
    java -jar -Dfile.encoding='utf-8' webmagic-console.jar -f github.js -t 2 -s 0 https://github.com/code4craft
  11. Create a crawler using Annotations (OOSpider)

    develop

    For a more declarative approach, you can use annotations on a POJO to define your crawler. This avoids manual field mapping in a process method.

    Key annotations:

    • @TargetUrl(regex): Defines the URL pattern this class handles.
    • @HelpUrl(regex): Defines a help URL pattern.
    • @ExtractBy(xpath/css, notNull): Extracts data using XPath or CSS selectors.
    • @ExtractByUrl(regex): Extracts data from a URL matching the pattern.

    Use OOSpider.create(site, pipeline, targetClass) to initialize the crawler.

    @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();
        }
    }