Crawler4j с приложением Grails

#grails #groovy #crawler4j

#grails #groovy #crawler4j

Вопрос:

Я создаю приложение для сканирования в Groovy на Grails. Я использую Crawler4j и следую этому руководству.

  1. Я создал новый проект Grails
  2. Поместите файл BasicCrawlController.groovy в controllers->package
  3. Не создавал никакого представления, потому что я ожидал, что при выполнении run-app мои данные сканирования появятся в моем crawlStorageFolder (пожалуйста, поправьте меня, если мое понимание неверно)

После этого я просто запустил приложение, выполнив run-app , но я нигде не видел никаких сканируемых данных.

  1. Правильно ли я ожидаю, что какой-либо файл будет создан в местоположении crawlStorageFolder, которое я указал как C:/crawl/crawler4jStorage ?
  2. Нужно ли мне создавать какое-либо представление для этого?
  3. Если я хочу вызвать этот контроллер сканера из какого-либо другого представления при нажатии кнопки отправки формы, могу ли я просто написать <g:form name="submitWebsite" url="[controller:'BasicCrawlController ']"> ?

Я спросил об этом, потому что у меня нет никакого метода в этом контроллере, так правильно ли вызывать этот контроллер?

Мой код выглядит следующим образом:

 //All necessary imports  



    public class BasicCrawlController {
        static main(args) throws Exception {
            String crawlStorageFolder = "C:/crawl/crawler4jStorage";
            int numberOfCrawlers = 1;
            //int maxDepthOfCrawling = -1;    default
            CrawlConfig config = new CrawlConfig();
            config.setCrawlStorageFolder(crawlStorageFolder);
            config.setPolitenessDelay(1000);
            config.setMaxPagesToFetch(100);
            config.setResumableCrawling(false);
            PageFetcher pageFetcher = new PageFetcher(config);
            RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
            RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
            CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer);
            controller.addSeed("http://en.wikipedia.org/wiki/Web_crawler")
            controller.start(BasicCrawler.class, 1);

        }
    }


    class BasicCrawler extends WebCrawler {

    final static Pattern FILTERS = Pattern
    .compile(".*(\.(css|js|bmp|gif|jpe?g"  "|png|tiff?|mid|mp2|mp3|mp4"  
             "|wav|avi|mov|mpeg|ram|m4v|pdf"  "|rm|smil|wmv|swf|wma|zip|rar|gz))$")

    /**
     * You should implement this function to specify whether the given url
     * should be crawled or not (based on your crawling logic).
     */
    @Override
    boolean shouldVisit(WebURL url) {
        String href = url.getURL().toLowerCase()
        !FILTERS.matcher(href).matches() amp;amp;       href.startsWith("http://en.wikipedia.org/wiki/Web_crawler/")
    }

    /**
     * This function is called when a page is fetched and ready to be processed
     * by your program.
     */
    @Override
    void visit(Page page) {
        int docid = page.getWebURL().getDocid()
        String url = page.getWebURL().getURL()
        String domain = page.getWebURL().getDomain()
        String path = page.getWebURL().getPath()
        String subDomain = page.getWebURL().getSubDomain()
        String parentUrl = page.getWebURL().getParentUrl()
        String anchor = page.getWebURL().getAnchor()

        println("Docid: ${docid} ")
        println("URL: ${url}  ")
        println("Domain: '${domain}'")
        println("Sub-domain: ' ${subDomain}'")
        println("Path: '${path}'")
        println("Parent page:${parentUrl}  ")
        println("Anchor text: ${anchor} " )

        if (page.getParseData() instanceof HtmlParseData) {
            HtmlParseData htmlParseData = (HtmlParseData) page.getParseData()
            String text = htmlParseData.getText()
            String html = htmlParseData.getHtml()
            List<WebURL> links = htmlParseData.getOutgoingUrls()

            println("Text length: "   text.length())
            println("Html length: "   html.length())
            println("Number of outgoing links: "   links.size())
        }
        Header[] responseHeaders = page.getFetchResponseHeaders()
        if (responseHeaders != null) {
            println("Response headers:")
            for (Header header : responseHeaders) {
                println("t ${header.getName()} : ${header.getValue()}")
            }
        }
        println("=============")
    }
}
 

Комментарии:

1. Участники, проголосовавшие против, пожалуйста, укажите причину, по которой вы проголосовали против, если вы не можете помочь.

2. ИМХО, этот код не принадлежит ни одному контроллеру. Вам лучше перенести его в службу Grails. Но в целом я не понимаю вашего списка. Это не контроллер Grails. И почему вы используете main метод внутри контроллера?

3. Может быть, будет полезнее, если вы опишете, чего вы пытаетесь достичь. Что должно делать ваше веб-приложение?

4. Таким образом, пользователь должен иметь возможность отправлять URL-адрес в ваше веб-приложение Grails, которое затем запускает процесс обхода этого URL. Но что происходит тогда? Каков ответ для пользователя? Не могли бы вы уточнить свой вариант использования. То, чего вы, возможно, хотите достичь, — это двухэтапный процесс. 1-й — отправка URL-адреса, 2-й — сканирование и, возможно, 3-й — отображение или сохранение просмотренных данных. Поскольку сканирование может занять некоторое время, вы можете использовать асинхронный обход. Пожалуйста, предоставьте дополнительную информацию о вашем варианте использования.

5. Ваш код немного перепутан с копированием и вставкой (без обид). Вы новичок в Grails? Я попытался очистить код контроллера. Пожалуйста, взгляните на мой ответ.

Ответ №1:

Я попытаюсь перевести ваш код в стандарт Grails.

Используйте это в grails-app/controller

 class BasicCrawlController {

   def index() {
        String crawlStorageFolder = "C:/crawl/crawler4jStorage";
        int numberOfCrawlers = 1;
        //int maxDepthOfCrawling = -1;    default
        CrawlConfig crawlConfig = new CrawlConfig();
        crawlConfig.setCrawlStorageFolder(crawlStorageFolder);
        crawlConfig.setPolitenessDelay(1000);
        crawlConfig.setMaxPagesToFetch(100);
        crawlConfig.setResumableCrawling(false);
        PageFetcher pageFetcher = new PageFetcher(crawlConfig);
        RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
        RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
        CrawlController controller = new CrawlController(crawlConfig, pageFetcher, robotstxtServer);
        controller.addSeed("http://en.wikipedia.org/wiki/Web_crawler")
        controller.start(BasicCrawler.class, 1);

        render "done crawling"

    }
}
 

Используйте это в src/groovy

 class BasicCrawler extends WebCrawler {

final static Pattern FILTERS = Pattern
.compile(".*(\.(css|js|bmp|gif|jpe?g"  "|png|tiff?|mid|mp2|mp3|mp4"  
         "|wav|avi|mov|mpeg|ram|m4v|pdf"  "|rm|smil|wmv|swf|wma|zip|rar|gz))$")

/**
 * You should implement this function to specify whether the given url
 * should be crawled or not (based on your crawling logic).
 */
@Override
boolean shouldVisit(WebURL url) {
    String href = url.getURL().toLowerCase()
    !FILTERS.matcher(href).matches() amp;amp;       href.startsWith("http://en.wikipedia.org/wiki/Web_crawler/")
}

/**
 * This function is called when a page is fetched and ready to be processed
 * by your program.
 */
@Override
void visit(Page page) {
    int docid = page.getWebURL().getDocid()
    String url = page.getWebURL().getURL()
    String domain = page.getWebURL().getDomain()
    String path = page.getWebURL().getPath()
    String subDomain = page.getWebURL().getSubDomain()
    String parentUrl = page.getWebURL().getParentUrl()
    String anchor = page.getWebURL().getAnchor()

    println("Docid: ${docid} ")
    println("URL: ${url}  ")
    println("Domain: '${domain}'")
    println("Sub-domain: ' ${subDomain}'")
    println("Path: '${path}'")
    println("Parent page:${parentUrl}  ")
    println("Anchor text: ${anchor} " )

    if (page.getParseData() instanceof HtmlParseData) {
        HtmlParseData htmlParseData = (HtmlParseData) page.getParseData()
        String text = htmlParseData.getText()
        String html = htmlParseData.getHtml()
        List<WebURL> links = htmlParseData.getOutgoingUrls()

        println("Text length: "   text.length())
        println("Html length: "   html.length())
        println("Number of outgoing links: "   links.size())
    }
    Header[] responseHeaders = page.getFetchResponseHeaders()
    if (responseHeaders != null) {
        println("Response headers:")
        for (Header header : responseHeaders) {
            println("t ${header.getName()} : ${header.getValue()}")
        }
    }
    println("=============")
  }
}
 

Комментарии:

1. Большое вам спасибо. Это сработало для меня 🙂 Это отличная помощь для новичка. 🙂

2. У меня есть сомнения. В моем BasicCrawl.groovy внутри должна быть функция посещения, я хочу использовать значение, которое будет передано с моего контроллера (значение, введенное пользователем). Как я могу передать это значение из контроллера в этот класс groovy?

3. Пожалуйста, задайте новый вопрос.