GVKun编程网logo

匍匐(crawler)(匍匐怎么读)

30

本篇文章给大家谈谈匍匐,以及crawler的知识点,同时本文还将给你拓展awesome-crawler、AWSGlueCrawler和大小写混合的JSON数据、crawler、Crawler4j+js

本篇文章给大家谈谈匍匐,以及crawler的知识点,同时本文还将给你拓展awesome-crawler、AWS Glue Crawler 和大小写混合的 JSON 数据、crawler、Crawler4j+jsoup 爬虫等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

匍匐(crawler)(匍匐怎么读)

匍匐(crawler)(匍匐怎么读)

蜘蛛程序(spider)是查找引擎的一部分,担任在互联网上定位和索引每个网页,这样就可以呼应查找者的查找要求,成功的查找引擎营销依赖于爬在一个网站上找到简直全部的网页。

awesome-crawler

awesome-crawler

awesome-crawler 介绍

互联网爬虫,蜘蛛,数据采集器,网页解析器的汇总,因新技术不断发展,新框架层出不穷 

Python

Scrapy - 一种高效的屏幕,网页数据采集框架。

django-dynamic-scraper - 基于Scrapy内核由django Web框架开发的爬虫。

Scrapy-Redis - 基于Scrapy内核采用Redis组件的爬虫。

scrapy-cluster - 基于Scrapy内核采用Redis 和 Kafka 开发的分布式爬虫框架。

distribute_crawler - 基于Scrapy内核采用redis,mongodb开发的分布式爬虫框架。

pyspider - 一个强大纯python的数据采集系统.

cola - 一个分布式的爬虫框架.

Demiurge - 基于PyQuery的微型爬虫框架.

Scrapely - 一个纯python的html页面捕捉库.

Feedparser - 一个通用的Feed解析器.

you-get - 静默网站爬去下载器.

Grab - 网站采集框架.

MechanicalSoup - 一个自动化的互动网站Python库.

portia - 基于Scrapy的可视化数据采集框架.

crawley - 基于非阻塞通信(NIO)的Python爬虫框架.

Robobrowser - 一个简单的,不基于Web浏览器的基于Python的Web 浏览器.

MSpider - 一个基于gevent(协程网络库)的Python爬虫.

brownant - 一个轻量级的网络数据抽取框架.

Java

Apache Nutch - 用于生产环境的高度可扩展的高度可扩展的网络爬虫.

anthelion - 一个基于Apache Nutch抓取语义注释在html页面插件.

Crawler4j - 简单和轻量级的网络爬虫.

JSoup - 采集,分析,处理和清洗html页面.

websphinx - html网站特定的处理、信息提取.

Open Search Server - 全套搜索功能,建立你自己的索引策略。分析、提取全文数据,这个框架可以索引的一切.

Gecco - 一个易于使用的轻量级网络爬虫.

WebCollector -简单的抓取网页的界面,可以在不到5分钟内部署一个多线程的网络爬虫.

Webmagic -一个可扩展的爬虫框架.

Spiderman -一个可扩展的,多线程的网络爬虫.

Spiderman2 - 分布式网络爬虫框架,支持JavaScript渲染.

Heritrix3 - 可扩展,大规模的网络爬虫项目.

SeimiCrawler - 一个敏捷的分布式爬虫框架.

StormCrawler - 基于开放源代码、构建低延迟的网络资源采集框架,基于Apache Storm.

Spark-Crawler - 基于Apache Nutch 的网络爬虫,可以运行于Spark.

C#

ccrawler - 一个简单的Web内容分类方案,它可以根据其内容分开网页,基于C#3.5.

SimpleCrawler - 简单的多线程网络爬虫,基于REG表达式.

DotnetSpider - 基于C#开发的一个轻量级,交叉平台的网络爬虫.

Abot - 具有很好效率和可扩展性的C#网络爬虫.

Hawk -  用 C#/WPF开发的网络爬虫,具有简单的ETL功能.

SkyScraper - 一个支持异步网络和有很好扩展性的网络爬虫.

JavaScript

scraperjs - 基于js的一个功能齐全的网络爬虫.

scrape-it - 基于Node.js的网络爬虫.

simplecrawler - 基于事件驱动开发的网络爬虫.

node-crawler - 提供简单API,适于二次开发的网络爬虫.

js-crawler - 基于Node.js,支持HTTP(S)的网络爬虫.

x-ray - 支持分页的网络爬虫.

node-osmosis - 基于Node.js适于解析html结构的网络爬虫.

PHP

Goutte - 基于PHP的网页截屏和爬取程序.

laravel-goutte - 基于Laravel 5 的网络爬虫.

dom-crawler - 易于抽取DOM文件的网络爬虫.

pspider - 基于PHP的并发网络爬虫.

PHP-spider - 一个基于PHP的高可扩展的网络爬虫.

C++

open-source-search-engine - 基于C/C++开发的网络爬虫和搜索引擎.

C

httrack - 全部网站整体复制工具。 ## Ruby

upton - 一个易于上手的爬虫框架集合,支持css选择器.

wombat - 基于Ruby天然的支持DSL的网络爬虫,易于提取网页正文数据.

RubyRetriever - 基于Ruby的网站数据采集和全网数据收割机.

Spidr - 全站数据采集,支持无限的网站链接地址采集.

Cobweb - 非常灵活,易于扩展的网络爬虫,可以单点部署使用.

mechanize - 自动采集网站数据的框架.

R

rvest - 基于R开发的简单网络爬虫.

Erlang

ebot - 一个分布式,高可扩展的网络爬虫.

Perl

web-scraper - 方便使用html、css、XPath选择器的网络爬虫。

Go

pholcus - 一个分布式,支持高并发的网络爬虫.

gocrawl - 一个高并发的,轻量级,遵守道德的网络爬虫.

fetchbot -一个遵守robots.txt规则和延迟规则的轻量级网络爬虫.

go_spider - 一个非常好的高并发网络爬虫.

dht -支持DHT协议的网络爬虫.

ants-go - 基于Golang的高并行网络爬虫.

scrape - 一个简单的提供很好开发接口的网络爬虫.

Scala

crawler - 基于Scala DSL的网络爬虫.

scrala - 由Scala开发基于scrapy内核的网络爬虫.

ferrit - 基于Scala开发使用了Akka,Spray,Cassandra的网络爬虫.

GitHub:https://github.com/BruceDone/awesome-crawler

网站描述:爬虫技术资源汇总

awesome-crawler官方网站

官方网站:

如果觉得小编网站内容还不错,欢迎将小编网站 推荐给程序员好友。

AWS Glue Crawler 和大小写混合的 JSON 数据

AWS Glue Crawler 和大小写混合的 JSON 数据

如何解决AWS Glue Crawler 和大小写混合的 JSON 数据?

我们正在将 JSON 文件发送到 S3,稍后由 glue Crawler 解析,然后在 Athena 中使用。

问题是某些文件带有小写的属性名称,而其他文件带有 CamelCase 属性名称。

Crawler 基本上将两个模式作为单独的模式添加,所以最后我在同一个表中有这样的内容:

structobject: struct
StructObject: struct

后来 Athena 拒绝查询抛出 GENERIC_INTERNAL_ERROR: Ambiguous field 错误。

有没有办法告诉 Crawler 在涉及架构时使用不区分大小写的比较?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

crawler

crawler

#!/usr/bin/perl
use strict;
use warnings;
 
use threads;
use threads::shared;
use Thread::Queue;
use Thread::Semaphore;
 
use Bloom::Filter;
use URI;
use URI::URL;
use Web::Scraper;
use LWP::Simple;
 
use LWP::UserAgent;
use HTTP::Cookies;
 
#use HTTP::Cookies::Guess;
 
use String::Diff;
use String::Diff qw(diff_fully diff diff_merge diff_regexp) ;
use URI::Split qw(uri_split uri_join) ;
 
my $fid : shared; #下载的页面以递增的数字命名
share( $fid );    #多线程共享该变量
$fid =0;
 
#crawling with signed cookie
my $cookie_jar = '.mozilla/firefox/bg146ia6.default/cookies.sqlite' ;
 
my $tmp_ua = LWP::UserAgent->new;    #UserAgent用来发送网页访问请求
$tmp_ua ->timeout(15);                ##连接超时时间设为15秒
$tmp_ua ->protocols_allowed( [ 'http' , 'https' ] ); ##只允许http和https协议
$tmp_ua ->agent(
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727;.NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
   )
   ; ##用来在header中告诉服务器你用的是什么"浏览器",设置文件头的User-Agent
 
$tmp_ua ->cookie_jar(HTTP::Cookies->new( 'file' => "$ENV{'HOME'}/$cookie_jar" , 'autosave' =>1));
# 设置cookie,在运行过程中必须执行两个方法,extract_cookies($request) 和 add_cookie_header($response)。在运行的过程中实际用到了HTTP::Cookies模块。如:
# $ua->cookie_jar({ file => "$ENV{HOME}/.cookies.txt" });
# 等价于
# require HTTP::Cookies;
# $ua->cookie_jar(HTTP::Cookies->new(file => "$ENV{HOME}/.cookies.txt"));
 
push @{ $tmp_ua ->requests_redirectable}, 'POST' ; #告诉LWP在POST请求发送后如果发生重新定向就自动跟随
 
my $max_threads = 5;
 
my $base_url = $ARGV [0] || 'http://www.cnblogs.com/zhangchaoyang/' ;
my $host = URI::URL->new( $base_url )->host;
print "Host Name: $host.\n" ;
 
my $queue = Thread::Queue->new( );       #线程队列,每个线程负责去处理一个url
 
my $semaphore = Thread::Semaphore->new( $max_threads );
my $mutex = Thread::Semaphore->new( 1 );
 
 
#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
#my $logfile = "crawler".($year+1900).($mon+1).$mday.$hour.$min.$sec.".log";
#open(BANLOG,">>$logfile") or die("can't open logfile:$!\n");
 
# Bloom::Filter使用更少的内存采用一种基于概率的算法来进行存在性测试。
my $filter = shared_clone( Bloom::Filter->new( capacity => 1000000, error_rate => 0.001) );
 
$queue ->enqueue( $base_url );        #放入线程队列的URL就要被线程所处理
$filter ->add( $base_url );           #放入filter中好判断该URL是否已经存在
 
my @tmp_url = ();                   #@tmp_url存在处理过的url
push ( @tmp_url , $base_url );
 
while ( 1 )
{
     # join所有可以被join的线程
     #my $joined = 0;
     foreach ( threads->list(threads::joinable) )
     {
         #$joined ++;
         $_ -> join ( );
     }
     #print $joined," joinedn";
 
     # if there are no url need process.
     my $item = $queue ->pending(); #返回队列中url的个数
     # 线程队列为空
     if ( $item == 0 )
     {
         my $active = threads->list(threads::running);
         # 已经没有active线程了,结束所有的工作
         if ( $active == 0 )
         {
             print "All done!\n" ;
             last ;
         }
         # 如果还有活动线程,那么主线程sleep,等待处理URL的子线程结束
         else
         {
             #print "[MAIN] 0 URL,but $active active threadn";
             sleep 1;
             next ;
         }
     }
 
     # 线程队列不为空,信号量减1,占用一个线程来处理url
     #print "[MAIN] $item URLn";
     $semaphore ->down;
     #print "[MAIN]Create thread.n";
     threads->create( \ &ProcessUrl );
}
 
# join all threads which can be joined
foreach ( threads->list() )
{
     $_ -> join ( );
}
 
sub ProcessUrl
{
     my $scraper = scraper
     {
             process '//a' , 'links[]' => '@href' ; #根据XPath表达式寻找所有的标签a,把href属性存到散列的value中
     };
 
     my $res ;
     my $link ;
 
     while ( my $url = $queue ->dequeue_nb() )
     {
         eval #eval BLOCK,BLOCK只会被解析一次,并且在编译时进行代码语法检查。
        {
             print "开始下载" ,URI->new( $url )->as_string, "\t\$fid=$fid\n" ;
             LWP::Simple::getstore(URI->new( $url )->as_string, "$ENV{'HOME'}/master/cnblog/cn$fid" ) or print "Can't download the web page." ;
             $fid +=1;
             $scraper ->user_agent( $tmp_ua ); #设置$scraper的user_agent
             $res = $scraper ->scrape( URI->new( $url ) )->{ 'links' }; #把URI传给scrape函数。scrape函数返回一个数组引用,因为links是数组
         };
         if ( $@ ) # 当BLOCK中有语法错误、运行时错误遇到 die 语句, eval 将返回 undef 。错误码被保存在 $@ 中。
         {
             warn "$@\n" ;
             next ;
         }
         next if (! defined $res ); #如果HTML文档中没有发现a标签
 
         #print "there are ".scalar(threads->list(threads::running))." threads,",$queue->pending()," urls need process.n";
 
         foreach ( @{ $res } )
         {
             # $_ => URI->new("http://example.com/")     所以要调用sa_string来获取"http://example.com/"
             $link = $_ ->as_string;
             $link = URI::URL->new( $link , $url );
             #$u1 = URI::URL->new($str,$base);
             #$u2 = $u1->abs;
 
             # not http and not https?
             next if ( $link ->scheme ne 'http' && $link ->scheme ne 'https' );
             #The three forms of URI reference Syntax are summarized as follows:
             #<scheme>:<scheme-specific-part>#<fragment>
             #<scheme>://<authority><path>?<query>#<fragment>
             #<path>?<query>#<fragment>
             #可以通过URL::Split把名个部分分离出来
             # another domain?
             # next if( $link->host ne $host );
 
             #search for the sub domain
             next if (!( $link ->host =~ / $host /));
 
             $link = $link -> abs ->as_string; #获得绝对路径
 
             if ( $link =~ /(.*?) #(.*)/ )#去除书签锚点,即#以后的内容
             {
                 $link = $1;
             }
 
             next if ( $link =~ /RSS|.(jpg|png|bmp|mp3|wma|wmv|gz|zip|rar|iso|pdf)$/i ); #这些文件格式我们不抓取
 
 
             #print "test:$link\n";
 
             #EscapeUrl,skip query form values
             my $tmp_link = &EscapeUrl ( $link ); #$tmp_link中已经把查询参数的值去掉了
             #print "Escape:".$tmp_link."\n";
 
             $mutex ->down(); #互质体减1,进入线程临界资源区
             my $tmp_mark = 0;
 
             #print "test start:$link\n";
             if ( ! $filter ->check( $tmp_link ) )    #如果$tmp_link不在$filter中
             {
                 #print "Test filter ok:$tmp_link\n";
 
                 #DiffUrl,diff $link from queue with number
 
                 foreach ( @tmp_url )
                 {
                     #print "Test Queue:".$tmpurl."\n";
                     #print "test-1:$_\ntest-2:$tmp_link\n";
                     if ( &DiffUrl ( $_ , $link )) #如果发现@tmp_url中的url和当前页面中的一个链接url仅是在某些数字上不同(很可能是查询参数值不同),则跳过该链接,即跳到else里面去。
                     {
                         $tmp_mark = 2;
                         last ;
                     }
                 }
 
                 if ( $tmp_mark != 2 )
                 {
                     $queue ->enqueue( $link );      #把页面上的链接$link交给线程进行处理
                     #print "add queue:$link\n";
                     $filter ->add( $tmp_link ); #$tmp_link放入$filter
                     #print "add filter:$tmp_link\n";
                     #print BANLOG $filter->key_count()," ",$link,"\n";
                     #print $filter->key_count(),"\n";
 
                     push ( @tmp_url , $link ); #把$link放入已处理的url数组@tmp_url
                 }
                 else
                 {
                     #print "pass:$link\n";#$link被忽略
                 }
             }
             #print "pass:$link\n";
 
             $mutex ->up(); #互斥信号量加1
             undef $link ;
         }
         undef $res ; #清除创建的一些object,否则在while循环中这些object越积越多
     }
     undef $scraper ;
     $semaphore ->up( ); ##普通信号量加1
}
 
#close(BANLOG);
print "ALL DONE.\n" ;
 
#把URL尾部的request参数置为空
#比如http://category.dangdang.com/?ref=www-0-C&name=orisun-zhang#ref=www-0-C被处理为http://category.dangdang.com/?ref=&name=
sub EscapeUrl
{
     my $urlold = shift ;
     my ( $scheme , $auth , $path , $query , $frag ) = uri_split( $urlold ); #把一个url的各部分分离出来
     my $urlnew = uri_join( $scheme , $path );
 
     my $u = URI->new( $urlold );
     my @tmp_array = $u ->query_form();
     my $tmp = '' ;
     my $i = 0;
     for ( $i =0; $i < @tmp_array ; $i +=2) #把request参数的值去掉
     {
         $tmp .= $tmp_array [ $i ]. "=&" ;
     }
     if ( @tmp_array != 0)
     {
         $tmp =~ s/&$//;
         $urlnew .= "?" . $tmp ;
     }
     undef $u ; #清除子例程中创建的object
     #print $urlnew."\n";
     return $urlnew ;
}
 
sub DiffUrl
{
     my $urlold = shift ;
     my $urlnew = shift ;
     my $urloldx = &EscapeUrl ( $urlold );
     my $urlnewx = &EscapeUrl ( $urlnew );
 
     my ( $old , $new ) = String::Diff::diff( $urloldx , $urlnewx );
     #my($old,$new) = String::Diff::diff($urlold,$urlnew);
     if (( $old =~ m/(\[\d+\])/i) && ( $new =~ m/{\d+}/i))         #如果两个url仅是在某些数字上不同
     #if ($new =~ m/{\d+}/i)
     {
         #print "test num success.\n";
         return 1;
     }
     else
     {
         #print "test num Failed.\n";
         return 0;
     }
}

Crawler4j+jsoup 爬虫

Crawler4j+jsoup 爬虫

第一步:如果读者使用过maven,可以很轻松的使用maven引入即可。

如果你没有用过maven那么,你需要把源码打成jar包,然后引入jar包,使用即可。

第二步:创建一个crawler类继承WebCrawler ,并重写两个方法,如下:

public class MyCrawler2 extends WebCrawler {
    @Override
    public boolean shouldVisit(Page referringPage, WebURL url) {
        //这个方法的作用是过滤不想访问的url
        //return false时  url被过滤掉不会被爬取
        return super.shouldVisit(referringPage, url);
    }
    @Override
    public void visit(Page page) {
        //这个方法的作用是当shouldVisit方法返回true时,调用该方法,获取网页内容,已被封装到Page对象中
        super.visit(page);
    }
}


第三步:创建一个controller类(实际任意类都行),创建main方法,根据官方文档,只需修改线程数量和url就行了。该url可以被称为种子,只要传入一个url,crawler4j就会根据url中的内容获取页面中所有的url然后再次爬取,周而复始,但重复的网址不会重复爬取,不会出现死循环。

public class Controller {
    public static void main(String[] args) throws Exception {
        String crawlStorageFolder = "/data/crawl/root";//文件存储位置
        int numberOfCrawlers = 7;//线程数量
 
        CrawlConfig config = new CrawlConfig();
        config.setCrawlStorageFolder(crawlStorageFolder);//配置对象设置
 
        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://www.ics.uci.edu/~lopes/");//传入的url
 
        controller.start(MyCrawler.class, numberOfCrawlers);//开始执行爬虫
    }
}


启动main方法就可以完成网页的爬取了。

下面写一个实例,爬取欧洲黄页的企业信息

1.控制器

public class CrawlerController {
    public static void main(String[] args) throws Exception {
        String crawkStirageFolder = "E:/CRAWLER/jd/test1";//定义爬虫数据存储位置
        int numberOfCrawlers=1;//定义1个爬虫,也就是1个线程,爬虫数量不可以超出cpu的线程
        CrawlConfig config=new CrawlConfig();//定义爬虫配置
        config.setCrawlStorageFolder(crawkStirageFolder);
        /*
        实例化爬虫控制器
        */
        PageFetcher pageFetcher=new PageFetcher(config);//实例化页面获取器
        RobotstxtConfig robotstxtConfig=new RobotstxtConfig();//实例化爬虫机器人配置
        // 实例化爬虫机器人对目标服务器的配置,每个网站都有一个robots.txt文件
        // 规定了该网站哪些页面可以爬,哪些页面禁止爬,该类是对robots.txt规范的实现
        RobotstxtServer robotstxtServer=new RobotstxtServer(robotstxtConfig,pageFetcher);
        //实例化爬虫控制器
        CrawlController controller=new CrawlController(config,pageFetcher,robotstxtServer);
        controller.addSeed("https://www.europages.cn/qiyeminglu.html");//传入种子 要爬的网站
        controller.start(MyCrawler2.class,numberOfCrawlers);//开始执行爬虫

    }
}

2.爬虫类,这里的两个实现方法尤为重要,控制器只是一个访问的入口,具体访问规则和访问结果的获取都是在这两个方法中实现。

查看欧洲黄页关html规则,发现目录都在<li>标签中

继续展开<li>标签,看到该目录的具体信息,这里笔者爬取的是一级菜单,其他信息依然可以根据读者需求自定义爬取

public class MyCrawler2 extends WebCrawler {
    //自定义过滤规则
    private final static Pattern FILTERS=Pattern.compile(".*(\\.(css|js|gif|jpg|png|mp3|mp4|zip|gz))$");
    @Override
    public boolean shouldVisit(Page referringPage, WebURL url){
       /* return super.shouldVisit(referringPage,url);*/
        String href = url.getURL().toLowerCase();//爬取的网址 转小写
        //这里定义过滤的网址,我的需求是只爬取一级菜单
        boolean b =!FILTERS.matcher(href).matches()&&href.startsWith("https://www.europages.cn/qiyeminglu.html");
        return b;
    }
    @Override
    public void visit(Page page){
        /*super.visit(page);*/
        String url = page.getWebURL().getURL();
        System.out.println(url);
        //判断page是否为真正的网页
        if (page.getParseData() instanceof HtmlParseData) {
            HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
            String html = htmlParseData.getHtml();//页面html内容
            Document doc= Jsoup.parse(html);//将html解析成一个Document类

            //使用选择器的时候需要了解网页中的html规则,自己去网页中F12一下,
            Elements content=doc.getElementsByClass("title test_actvLink");
            if (content.size()==0){
                return;
            }
            //Elements elements =  doc.select(".gl-item");
            int num=0;
            for (Element element: content) {
                String text=element.text();
                String weburl=element.attr("href");
                System.out.println(text);
                System.out.println(weburl);
                num++;
            }
            System.out.println("分类总算为"+num);
        }
    }
}

看一下运行结果,我选择输出一级分类名,和对应网址

这个文章写的相对粗糙,周末有空在好好整理一下吧

推荐博文 https://blog.csdn.net/qq_34337272/article/details/78815547

我们今天的关于匍匐crawler的分享已经告一段落,感谢您的关注,如果您想了解更多关于awesome-crawler、AWS Glue Crawler 和大小写混合的 JSON 数据、crawler、Crawler4j+jsoup 爬虫的相关信息,请在本站查询。

本文标签: