文档章节

【最新更新支持频道分页、文章分页】【抛砖引玉】抓取OSC的问答数据展现垂直爬虫的能力

自风
 自风
发布于 2013/01/08 18:11
字数 3402
阅读 38219
收藏 135

更新提示(2013-03-13):最新版本更新:

  1. 支持定向抓取某频道
    <!--
      | name:目标名称	
    -->
    <target name="travel" isForceUseXmlParser="1">
        <!--
          | 限制目标URL的来源为网易旅游子频道,在spiderman里面把频道页叫做"来源url"
        -->
        <sourceRules policy="and">
            <rule type="regex" value="http://travel\.163\.com/special/cjgat(_\d+)?/">
            <!--
              | 定义如何在来源页面上挖掘新的 URL
            -->
            <digUrls>
                <field name="source_url" isArray="1">
                    <parsers>
                        <parser xpath="//div[@class='list-page']//a[@href]" attribute="href"/>
                    </parsers>
                </field>
                <!--
                  | 在spiderman里面把详细文章页叫做"目标url"
                -->
                <field name="target_url" isArray="1">
                    <parsers>
                        <parser xpath="//div[@class='list-item clearfix']//div[@class='item-top']//h2//a[@href]" attribute="href"/>
                        <parser exp="$this.replace('#p=891JUOOO17KK0006','')" />
                    </parsers>
                </field>
            </digUrls>
            </rule>
        </sourceRules>


  2. 支持分页抓取单篇文章
    <!--
      | 目标URL的规则
    -->
    <urlRules policy="and">
        <rule type="regex" value="http://travel\.163\.com/\d{2}/\d{4}/\d{2}/\w[^_]+\.html">
            <!--
             | 递归抓取详细页的分页,单篇文章的分页会按顺序抓取保证内容抓取的顺序跟页码一致
            -->
            <nextPage>
                <field name="next_url">
                    <parsers>
                        <!--
                          | 正如field的name=next_url意思一样,这里的规则主要是来解析"当前"页的下一页url是什么,我们都知道分页页面里面肯定都有"下一页"入口的,抓到这个,然后递归即可
                        -->
                        <parser xpath="//div[@class='ep-pages']//a[@class='ep-pages-ctrl']" attribute="href" />
                    </parsers>
                </field>
            </nextPage>
        </rule>
    </urlRules>
    <!--
      | 另外还需要在<model>下的<field>多添加一个参数 isAlsoParseInNextPage="1" 告诉爬虫该字段需要在分页里继续解析的,比如下面这个content字段,是需要在“下一页”里继续解析的
    -->
    <model name="travel-article">
        <field name="content" isArray="1" isAlsoParseInNextPage="1">

  3. 支持站点内多host
    <!--
      | 告诉爬虫仅抓取以下这些host的链接,多数是应对二级或多级域名的情况
    -->
    <validHosts>
        <validHost value="travel.163.com" />
        <validHost value="wwww.163.com" />
    </validHosts>

  4. 支持多个种子链接
    <!--
      | 配置多个种子链接
      | url:种子链接
    -->
    <seeds>
        <seed url="" />
    </seeds>

  5. HTML页面也可以强制使用XPath轴、XPath各种函数解析
    <!--
      | isForceUseXmlParser 当解析的页面是HTML时,除了XPath基本功能外很多XPath功能都不支持,例如XPath轴、其他高级函数等,将此参数设置为 1 即可让其支持,但是会带来某些不确定的问题【暂时未发现】
    -->
    <target name="travel" isForceUseXmlParser="1">

  6. 其他
    <!--
      | skipStatusCode:设置哪些状态码需要忽略,多个用逗号隔开,一旦设置了,那么爬虫将会忽略掉一些错误的statusCode,并且继续解析返回的内容
      | userAgent:设置爬虫标识
      | includeHttps:是否抓取https页
    -->
    <site skipStatusCode="500,501" userAgent="Spiderman[https://gitcafe.com/laiweiwei/Spiderman]" includeHttps="0">

更新提示(2013-01-10):最新版本的spiderman-plugin针对<field>的解析器<parser>配置做了修改,主要是需要增加一个<parsers>父节点包裹,因为支持多个parser的链式解析了,上一个parser的结果作为下一个parser的$this.因此配置文件所有的<field>外面都需要添加<fields>包裹着。例如:


<target>
    <model>
        <field name="title">
            <parsers>
                <parser xpath="//div[@class='QTitle']/h1/text()"/>
            </parsers>
        </field>
    </model>
</target>

核心提示:本文介绍了如何使用垂直类网络爬虫#Spiderman#抓取目标网站 “感兴趣” 的数据,这里简单地演示了如何抓取OSC【本站】的问答数据,引出后文对另外一个复杂的团购网站内容的抓取,该网站的团购信息中,我们需要在JS代码里抓取过期时间、需要过滤团购的一些描述信息【保留一些标签,去掉一些标签,去掉属性等】、需要获取好几个地方的图片、需要获取团购的价格、购买人数等。关键的地方在于前面所述的这一切都将通过一个配置文件解决,无需编写一句代码。

所使用的爬虫工具介绍:

#Spiderman#,Java开源垂直类网络爬虫,使用XPath、正则、表达式引擎让你轻松地抓取任何目标网站你“感兴趣”的内容。基于多线程、微内核、插件式的架构。

Spiderman的正式版本还没有发布,但是在github里面有最新的代码可以取下来并且使用maven构建。

Spiderman依赖于EWeb4J的xml读写功能,因此还需要把最新的EWeb4J源码从github拉下来构建。

下面介绍如何抓取OSC的问答数据:


  1. 首先,我们来看看目标网页长什么样子的:)

    图中红色区域就是我们“感兴趣”的内容,从上到下依次为:标题,作者,问题内容,问题关联的标签,答案列表 一共五个属性。
  2. 然后,从spiderman-sample里拷贝一份xml配置文件按照上述需求编辑之后:
    先看没有注释的“简洁版”:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
    	<site name="oschina" url="http://www.oschina.net/question" reqDelay="1s" enable="1" charset="utf-8" schedule="1h" thread="2" waitQueue="10s">
    		<queueRules policy="and">
    			<rule type="!regex" value="^.*\.(jpg|png|gif).*$" />
    		</queueRules>
    		<targets>
    			<target name="deal">
    				<urls policy="and">
    					<rule type="regex" value="http://www\.oschina\.net/question/\d+_\d+" />
    				</urls>
    				<model>
    					<field name="title">
    						<parser xpath="//div[@class='QTitle']/h1/text()"/>
    					</field>
    					<field name="content">
    						<parser xpath="//div[@class='Content']//div[@class='detail']" exp="$Tags.xml($output($this)).rm('div').Attrs().rm('style').ok()" />
    					</field>
    					<field name="author">
    						<parser xpath="//div[@class='stat']//a[@target='_blank']/text()"/>
    					</field>
    					<field name="tags" isArray="1">
    						<parser xpath="//div[@class='Tags']//a/text()"/>
    					</field>
    					<field name="answers" isArray="1">
    						<parser xpath="//li[@class='Answer']//div[@class='detail']/text()" />
    					</field>
    				</model>
    			</target>
    		</targets>
    		<plugins>
    			<plugin enable="1" name="spider_plugin" version="0.0.1" desc="这是一个官方实现的默认插件,实现了所有扩展点。">
    				<extensions>
    					<extension point="task_poll">
    						<impl type="" value="spiderman.plugin.impl.TaskPollPointImpl" sort="0"/>
    					</extension>
    					<extension point="begin">
    						<impl type="" value="spiderman.plugin.impl.BeginPointImpl" sort="0"/>
    					</extension>
    					<extension point="fetch">
    						<impl type="" value="spiderman.plugin.impl.FetchPointImpl" sort="0"/>
    					</extension>
    					<extension point="dig">
    						<impl type="" value="spiderman.plugin.impl.DigPointImpl" sort="0"/>
    					</extension>
    					<extension point="dup_removal">
    						<impl type="" value="spiderman.plugin.impl.DupRemovalPointImpl" sort="0"/>
    					</extension>
    					<extension point="task_sort">
    						<impl type="" value="spiderman.plugin.impl.TaskSortPointImpl" sort="0"/>
    					</extension>
    					<extension point="task_push">
    						<impl type="" value="spiderman.plugin.impl.TaskPushPointImpl" sort="0"/>
    					</extension>
    					<extension point="target">
    						<impl type="" value="spiderman.plugin.impl.TargetPointImpl" sort="0"/>
    					</extension>
    					<extension point="parse">
    						<impl type="" value="spiderman.plugin.impl.ParsePointImpl" sort="0"/>
    					</extension>
    					<extension point="end">
    						<impl type="" value="spiderman.plugin.impl.EndPointImpl" sort="0"/>
    					</extension>
    				</extensions>
    				<providers>
    					<provider>
    						<orgnization name="" website="" desc="">
    							<author name="weiwei" website="" email="l.weiwei@163.com" weibo="http://weibo.com/weiweimiss" desc="一个喜欢自由、音乐、绘画的IT老男孩" />
    						</orgnization>
    					</provider>
    				</providers>
    			</plugin>
    		</plugins>
    	</site>
    </beans>
    下面这个是加了注释的版本,便于理解:)
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
      | Spiderman Java开源垂直网络爬虫 
      | author: l.weiwei@163.com
      | blog: http://laiweiweihi.iteye.com
      | qq: 493781187
      | time: 2013-01-08 16:12
    -->
    <beans>
    	<!--
    	  | name:名称
    	  | url:种子链接
    	  | reqDelay:{n}s|{n}m|{n}h|n每次请求之前延缓时间
    	  | enable:0|1是否开启本网站的抓取
    	  | charset:网站字符集
    	  | schedule:调度时间,每隔多长时间重新从种子链接抓取
    	  | thread:分配给本网站爬虫的线程数
    	  | waitQueue:当任务队列空的时候爬虫等待多长时间再索取任务
    	-->
    	<site name="oschina" url="http://www.oschina.net/question" reqDelay="1s" enable="1" charset="utf-8" schedule="1h" thread="2" waitQueue="10s">
    		<!--
    		  | HTTP Header
    		<headers>
    			<header name="" value="" />
    		</headers>-->
    		<!--
    		  | HTTP Cookie
    		<cookies>
    			<cookie name="" value="" domain="" path="" />
    		</cookies>-->
    		<!--
    		  | 进入任务队列的URL规则
    		  | policy:多个rule的策略,暂时只实现了and,未来会有or
    		-->
    		<queueRules policy="and">
    			<!--
    			  | 规则
    			  | type:规则类型,包括 regex | equal | start | end | contains 所有规则可以在前面添加 "!" 表示取反
    			  | value:值
    			-->
    			<rule type="!regex" value="^.*\.(jpg|png|gif).*$" />
    		</queueRules>
    		<!--
    		  | 抓取目标
    		-->
    		<targets>
    			<!--
    			  | name:目标名称	
    			-->
    			<target name="deal">
    				<!--
    				  | 目标URL匹配规则
    				-->
    				<urls policy="and">
    					<!--
    					  | 同前面的队列规则
    					-->
    					<rule type="regex" value="http://www\.oschina\.net/question/\d+_\d+" />
    				</urls>
    				<!--
    				  | 目标网页的数据模型
    				-->
    				<model>
    					<!--
    					  | 属性的配置
    					  | name:属性名称
    					  | parser:针对该属性的解析规则
    					-->
    					<field name="title">
    						<!--
    						  | xpath: XPath规则,如果目标页面是XML,则可以使用2.0语法,否则HTML的话暂时只能1.0
    						  | attribute:当使用XPath解析后的内容不是文本而是一个Node节点对象的时候,可以给定一个属性名获取其属性值例如<img src="" />
    						  | regex:当使用XPath(包括attribute)规则获取到的文本内容不满足需求时,可以继续设置regex正则表达式进行解析
    						  | exp:当使用XPath获取的文本(如果获取的不是文本则会先执行exp而不是regex否则先执行regex)不满足需求时,可以继续这是exp表达式进行解析
    						  |     exp表达式有几个内置对象和方法:
    						  |     $output(Node): 这个是内置的output函数,作用是输出某个XML节点的结构内容。参数是一个XML节点对象,可以通过XPath获得
    						  |     $this: 当使用XPath获取到的是Node节点时,这个表示节点对象,否则表示Java的字符串对象,可以调用Java字符串API进行处理
    						  |     $Tags: 这个是内置的用于过滤标签的工具类 
    						  |            $Tags.xml($output($this)).rm('p').ok()
    						  |            $Tags.xml($this).rm('p').empty().ok()
    						  |     $Attrs: 这个是内置的用于过滤属性的工具类
    						  |            $Attrs.xml($this).rm('style').ok()
    						  |            $Attrs.xml($this).tag('img').rm('src').ok()
    						  |     
    						  |            $Tags和$Attrs可以一起使用: 
    						  |            $Tags.xml($this).rm('p').Attrs().rm('style').ok()
    						  |            $Attrs.xml($this).rm('style').Tags().rm('p').ok()
    						-->
    						<parser xpath="//div[@class='QTitle']/h1/text()"/>
    					</field>
    					<field name="content">
    						<parser xpath="//div[@class='Content']//div[@class='detail']" exp="$Tags.xml($output($this)).rm('div').Attrs().rm('style').ok()" />
    					</field>
    					<field name="author">
    						<parser xpath="//div[@class='stat']//a[@target='_blank']/text()"/>
    					</field>
    					<field name="tags" isArray="1">
    						<parser xpath="//div[@class='Tags']//a/text()"/>
    					</field>
    					<field name="answers" isArray="1">
    						<parser xpath="//li[@class='Answer']//div[@class='detail']/text()" />
    					</field>
    				</model>
    			</target>
    		</targets>
    		<!--
    		  | 插件
    		-->
    		<plugins>
    			<!--
    			  | enable:是否开启
    			  | name:插件名
    			  | version:插件版本
    			  | desc:插件描述
    			-->
    			<plugin enable="1" name="spider_plugin" version="0.0.1" desc="这是一个官方实现的默认插件,实现了所有扩展点。">
    				<!--
    				  | 每个插件包含了对若干扩展点的实现
    				-->
    				<extensions>
    					<!--
    					  | point:扩展点名它们包括  task_poll, begin, fetch, dig, dup_removal, task_sort, task_push, target, parse, pojo, end
    					-->
    					<extension point="task_poll">
    						<!--
    						  | 扩展点实现类
    						  | type: 如何获取实现类 ,默认通过无参构造器实例化给定的类名,可以设置为ioc,这样就会从EWeb4J的IOC容器里获取
    						  | value: 当时type=ioc的时候填写IOC的bean_id,否则填写完整类名
    						  | sort: 排序,同一个扩展点有多个实现类,这些实现类会以责任链的方式进行执行,因此它们的执行顺序将变得很重要
    						-->
    						<impl type="" value="spiderman.plugin.impl.TaskPollPointImpl" sort="0"/>
    					</extension>
    					<extension point="begin">
    						<impl type="" value="spiderman.plugin.impl.BeginPointImpl" sort="0"/>
    					</extension>
    					<extension point="fetch">
    						<impl type="" value="spiderman.plugin.impl.FetchPointImpl" sort="0"/>
    					</extension>
    					<extension point="dig">
    						<impl type="" value="spiderman.plugin.impl.DigPointImpl" sort="0"/>
    					</extension>
    					<extension point="dup_removal">
    						<impl type="" value="spiderman.plugin.impl.DupRemovalPointImpl" sort="0"/>
    					</extension>
    					<extension point="task_sort">
    						<impl type="" value="spiderman.plugin.impl.TaskSortPointImpl" sort="0"/>
    					</extension>
    					<extension point="task_push">
    						<impl type="" value="spiderman.plugin.impl.TaskPushPointImpl" sort="0"/>
    					</extension>
    					<extension point="target">
    						<impl type="" value="spiderman.plugin.impl.TargetPointImpl" sort="0"/>
    					</extension>
    					<extension point="parse">
    						<impl type="" value="spiderman.plugin.impl.ParsePointImpl" sort="0"/>
    					</extension>
    					<extension point="end">
    						<impl type="" value="spiderman.plugin.impl.EndPointImpl" sort="0"/>
    					</extension>
    				</extensions>
    				<providers>
    					<provider>
    						<orgnization name="" website="" desc="">
    							<author name="weiwei" website="" email="l.weiwei@163.com" weibo="http://weibo.com/weiweimiss" desc="一个喜欢自由、音乐、绘画的IT老男孩" />
    						</orgnization>
    					</provider>
    				</providers>
    			</plugin>
    		</plugins>
    	</site>
    </beans>

  3. 编写代码启动爬虫:
    import java.io.File;
    import java.util.List;
    import java.util.Map;
    
    import org.eweb4j.config.EWeb4JConfig;
    import org.eweb4j.spiderman.spider.SpiderListener;
    import org.eweb4j.spiderman.spider.SpiderListenerAdaptor;
    import org.eweb4j.spiderman.spider.Spiderman;
    import org.eweb4j.spiderman.task.Task;
    import org.eweb4j.util.CommonUtil;
    import org.eweb4j.util.FileUtil;
    import org.junit.Test;
    
    public class TestSpider {
    	
    	private final Object mutex = new Object();
    	
    	@Test
    	public void test() throws Exception {
    		
    		//启动EWeb4J框架
    		String err = EWeb4JConfig.start();
    		if (err != null)
    			throw new Exception(err);
    		
    		SpiderListener listener = new SpiderListenerAdaptor(){
    			public void onInfo(Thread thread, Task task, String info) {
    				System.out.print("[SPIDERMAN] "+CommonUtil.getNowTime("HH:mm:ss")+" [INFO] ~ ");
    				System.out.println(info);
    			}
    			public void onError(Thread thread, Task task, String err, Exception e) {
    				e.printStackTrace();
    			}
    			
    			public void onParse(Thread thread, Task task, List<Map<String, Object>> models) {
    //				System.out.print("[SPIDERMAN] "+CommonUtil.getNowTime("HH:mm:ss")+" [INFO] ~ ");
    //				System.out.println(CommonUtil.toJson(models.get(0)));
    				synchronized (mutex) {
    					String content = CommonUtil.toJson(models.get(0));
    					
    					try {
    						File dir = new File("d:/jsons/"+task.site.getName());
    						if (!dir.exists())
    							dir.mkdirs();
    						File file = new File(dir+"/count_"+task.site.counter.getCount()+"_"+CommonUtil.getNowTime("yyyy_MM_dd_HH_mm_ss")+".json");
    						FileUtil.writeFile(file, content);
    						System.out.print("[SPIDERMAN] "+CommonUtil.getNowTime("HH:mm:ss")+" [INFO] ~ ");
    						System.out.println(file.getAbsolutePath() + " create finished...");
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		};
    		
    		//启动爬虫
    		Spiderman.me()
    			.init(listener)//初始化
    			.startup()//启动
    			.keep("15s");//存活时间,过了存活时间后马上关闭
    		
    		//------拿到引用后你还可以这样关闭-------------------------
    		//spiderman.shutdown();//等待正在活动的线程都死掉再关闭爬虫
    		//spiderman.shutdownNow();//马上关闭爬虫
    	}
    }
    原谅我写的比较啰嗦的代码 :)
    大概解释下上述代码的意义
    首先,因为依赖了EWeb4J框架的XML读写模块以及Properties模块,因此需要先启动EWeb4J:
    //启动EWeb4J框架
    String err = EWeb4JConfig.start();
    if (err != null)
        throw new Exception(err);
    然后,编写一个爬虫监听器,这里我们使用了内置的监听适配器选择性的实现了其中三个方法,第一个是打印INFO的,第二个是打印异常的,第三个比较重要:
    public void onParse(Thread thread, Task task, List<Map<String, Object>> models) {
        synchronized (mutex) {
            String content = CommonUtil.toJson(models.get(0));
            try {
                File dir = new File("d:/jsons/"+task.site.getName());
                if (!dir.exists())
                    dir.mkdirs();
                    File file = new File(dir+"/count_"+task.site.counter.getCount()+"_"+CommonUtil.getNowTime("yyyy_MM_dd_HH_mm_ss")+".json");
                    FileUtil.writeFile(file, content);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    这个方法在爬虫成功的抓取并解析了一个目标网页内容之后被回调,从代码可以看到一个List<Map>对象被传递了进来,这个对象就是我们想要的数据。因此我们将它格式化为JSON串后写入到D盘的文件里。

    准备好了监听器之后,接下来需要启动爬虫:
    //启动爬虫
    Spiderman.me()
        .init(listener)//初始化
        .startup()//启动
        .keep("15s");//存活时间,过了存活时间后马上关闭
    不知道各位客观是否喜欢这种链式API,俺倒是挺喜欢的:)

    PS:那个keep("15s") 是对OSC的一种敬重,虽然OSC不怎么怕“测试” :) @红薯

    如果你不想等15s,可以这样关闭爬虫:
    //------拿到引用后你还可以这样关闭-------------------------
    spiderman.shutdown();//等待正在活动的线程都死掉再关闭爬虫
    spiderman.shutdownNow();//马上关闭爬虫

    接下来,运行这个Test,观察文件夹以及控制台:



  4. 补充
    因为使用了reqDelay="1s"的配置,相当于一秒一次请求的频率,所以可以看到15秒抓取的页面【经过匹配后的】不是特别多 :) 

  5. 好了,最后看看抓取出来的JSON进行格式化后的效果:

以上是“抛砖”之举 :) (红薯别介意哈,OSC一直都很优秀,绝没有“砖”的意思),下面就是“引玉”之时了!


突然尿急,这个“引玉”看来还得放到后面来做......【待续 :)】

© 著作权归作者所有

自风

自风

粉丝 251
博文 5
码字总数 6065
作品 2
深圳
架构师
私信 提问
加载中

评论(100)

lailaiping
lailaiping
分析到位
mack_ky
mack_ky

引用来自“自风”的评论

引用来自“mack_ky”的评论

可以抓取图片吗?

有人曾经用spiderman把caoliu所有图片都抓下来了。0

@自风 有实战过程吗
自风
自风 博主

引用来自“mack_ky”的评论

可以抓取图片吗?

有人曾经用spiderman把caoliu所有图片都抓下来了。0
mack_ky
mack_ky
可以抓取图片吗?
自风
自风 博主

引用来自“风云王”的评论

我在运行的提供的TestSpider时提示java.lang.RuntimeException: there is no website to fetch...

请问具体是什么原因?谢谢~!

[DEBUG] 2015-08-01 18:24:47 [config] ~ (EWeb4JConfig.java:164) EWeb4JConfig.start
start-config-xml-path --> D:\MyEclipse 10\spiderman-sample\target\test-classes\eweb4j-start-config.xml
${RootPath} --> D:\MyEclipse 10\spiderman-sample\
ConfigBean [reload=0, debug=0, properties=Properties [file=[Prop [id=spiderman, path=spiderman.properties, global=0]]], locales=I18N [locale=[zh_CN]], ioc=ConfigIOC [open=1, logs=LogsConfigBean [log=[LogConfigBean [console=0, level=debug, file=logs/logs.log, insert=, size=5]]], iocXmlFiles=IOCXmlFiles [path=[ioc.xml]]], orm=ConfigORM [open=0, logs=LogsConfigBean [log=[LogConfigBean [console=0, level=debug, file=logs/logs.log, insert=, size=5]]], dataSource=com.mchange.v2.c3p0.ComboPooledDataSource, scanPojoPackage=ScanPojoPackage [path=[AP:${RootPath}/target/classes, .]], ormXmlFiles=ORMXmlFiles [path=[]], dbInfoXmlFiles=DBInfoXmlFiles [path=[mysql.xml]]], m
需要至少一个网站配置文件生效才能启动爬虫,让某个xml的
风云王
风云王
我在运行的提供的TestSpider时提示java.lang.RuntimeException: there is no website to fetch...

请问具体是什么原因?谢谢~!

[DEBUG] 2015-08-01 18:24:47 [config] ~ (EWeb4JConfig.java:164) EWeb4JConfig.start
start-config-xml-path --> D:\MyEclipse 10\spiderman-sample\target\test-classes\eweb4j-start-config.xml
${RootPath} --> D:\MyEclipse 10\spiderman-sample\
ConfigBean [reload=0, debug=0, properties=Properties [file=[Prop [id=spiderman, path=spiderman.properties, global=0]]], locales=I18N [locale=[zh_CN]], ioc=ConfigIOC [open=1, logs=LogsConfigBean [log=[LogConfigBean [console=0, level=debug, file=logs/logs.log, insert=, size=5]]], iocXmlFiles=IOCXmlFiles [path=[ioc.xml]]], orm=ConfigORM [open=0, logs=LogsConfigBean [log=[LogConfigBean [console=0, level=debug, file=logs/logs.log, insert=, size=5]]], dataSource=com.mchange.v2.c3p0.ComboPooledDataSource, scanPojoPackage=ScanPojoPackage [path=[AP:${RootPath}/target/classes, .]], ormXmlFiles=ORMXmlFiles [path=[]], dbInfoXmlFiles=DBInfoXmlFiles [path=[mysql.xml]]], m
自风
自风 博主

引用来自“番茄mc”的评论

您好,我现在想抓取第3级或者更深层次的页面要怎么配置?
<sourceRules policy="and">
  <rule type="regex" value="http://www.feiku.com">
          <digUrls>
            <field name="target_url">
              <parsers>
                <parser xpath="//div[@class='section clearfix']1//div[@class='book_top_wrap clearfix']/div[@class='book_top_page']/ol//li//a" attribute="href" />
              </parsers>
            </field>
          </digUrls>
        </rule>
      </sourceRules>
     <target name="feiKuBook">
        <urlRules policy="and">
          <rule type="regex" value="http://novel\.feiku.com/\d+" />
        </urlRules>
        <model>        
          <field name="watchBookURL" isForDigNewUrl="1">
            <parsers>
              <parser xpath="/body/div2/div2/div[@class='book_content fl']/div4/ul/li1/a" attribute="href"/>
            </parsers>
          </field>
        </model>
      </target>
<target name="feiKuBookDetail">
        <urlRules policy="and">
          <rule type="regex" value="http://novel\.feiku.com/\d+/\d+" />
        </urlRules>
  </target>
    </targets>
这是我的部分配置文件,现在只能抓取第一二页面,麻烦帮我看看83
        
继续配置第三级页面的target, 且把第二级页面的URL地址在sourceRules里面也配置一个规则进去匹配, 这样爬虫就能把二级页面识别为来源页, 同时采集到新配置的目标页面, 如果你不把二级页面URL的正则规则配置到sourceRules里面,那爬虫就算拿到第三级页面的采集任务会跳过,因为没有第三级页面找不到任何来源, 除非你配置了
番茄mc
番茄mc
您好,我现在想抓取第3级或者更深层次的页面要怎么配置?
<sourceRules policy="and">
  <rule type="regex" value="http://www.feiku.com">
          <digUrls>
            <field name="target_url">
              <parsers>
                <parser xpath="//div[@class='section clearfix']1//div[@class='book_top_wrap clearfix']/div[@class='book_top_page']/ol//li//a" attribute="href" />
              </parsers>
            </field>
          </digUrls>
        </rule>
      </sourceRules>
     <target name="feiKuBook">
        <urlRules policy="and">
          <rule type="regex" value="http://novel\.feiku.com/\d+" />
        </urlRules>
        <model>        
          <field name="watchBookURL" isForDigNewUrl="1">
            <parsers>
              <parser xpath="/body/div2/div2/div[@class='book_content fl']/div4/ul/li1/a" attribute="href"/>
            </parsers>
          </field>
        </model>
      </target>
<target name="feiKuBookDetail">
        <urlRules policy="and">
          <rule type="regex" value="http://novel\.feiku.com/\d+/\d+" />
        </urlRules>
  </target>
    </targets>
这是我的部分配置文件,现在只能抓取第一二页面,麻烦帮我看看83
        
Spider_M
Spider_M
这个有字数限制,qq发给你了,有时间帮忙看看呗83
Spider_M
Spider_M
<targets>
      <sourceRules policy="and">
        <rule type="regex" value="http://app2\.sfda\.gov\.cn/datasearchp/all.do?page=d+&name=%C6%CF%CC%D1%CC%C7%D7%A2%C9%E4%D2%BA&tableName=TABLE25&formRender=cx&searchcx=&paramter0=&paramter1=&paramter2=">
          <digUrls isForceUseXmlParser="1">
            <field name="page_url" isArray="1">
              <parsers>
                <parser xpath="//html//body//center//table3//tbody//tr//td//table//tbody//tr//td//table2//tbody//tr//td2//table//tbody//tr//td2/a[@href]" attribute="href"
                  exp="'http://app2.sfda.gov.cn/datasearchp/'+$this" />
              </parsers>
            </field>
            <field name="target_url" isArray="1">
              <parsers>
                <parser xpath="//html//body//center//table3//tbody//tr//td//table//tbody//tr//td//table1//tbody//tr//td[2]//a[@href]" attribute="href"
                   exp="'http://app2.sfda.gov.cn/datasearchp/'+$this" />
              </parsers>
            </field>
          </digUrls>
        </rule>
        <rule type="regex" value
【开源访谈】 Spiderman作者赖伟威访谈实录

【作者简介】 赖伟威 毕业刚满一年的Java Coder,立志做可靠的系统架构师。大学期间与几位志同道合的同学创办CFuture工作室。现在深圳打拼中。 【软件简介】 Spiderman 是一个基于微内核+插件...

丫头潘潘
2013/06/26
3K
12
垂直爬虫工作流程详解

在垂直搜索的索引建立之前,我们需要到垂直网站上抓取资源并做一定的处理。垂直搜索与通用搜索不同之处在于,通用搜索不需要理会网站哪些资源是需要的,哪些是不需要的,一并抓取并将其文本部...

Carlos_Tse
2013/05/05
6K
2
Python爬虫:大规模爬取喜马拉雅电台详细音频数据

喜马拉雅 一:前言 本次爬取的是喜马拉雅的热门栏目下全部电台的每个频道的信息和频道中的每个音频数据的各种信息,然后把爬取的数据保存到mongodb以备后续使用。这次数据量在70万左右。音频...

布咯咯_rieuse
2017/06/18
0
0
分布式爬虫--CrawlerDemon

CrawlerDemon 是垂直应用爬虫,基于akka+okHttp+spring+jsoup ,配置简单,上手容易,支持配置动态参数,动态代理,http自动重试。 特点 基于 akka 高性能分布式框架 使用 spring 配置请求参...

demon
2015/10/14
2.1K
0
程序人生:dedecms伪静态的实现方法

操作如下: 1、后台-系统参数-核心设置-是否使用伪静态:选择“是”; 注:你的网站空间是否支持伪静态,你可以与空间的IDC商联系一 下,如果是自己的服务器,那就更好办了,自己动手,丰衣足...

qq_42302805
2018/11/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

用Javascript评估用户输入密码的强度

密码已经是我们生活工作中必不可少的工具,但一个不安全的密码有又有可能会给我们造成不必要的损失。作为网站设计者,如果我们在网页中能对用户输入的密码进行安全评估,并显示出相应的提示信息...

花漾年华
29分钟前
0
0
Python 打开目录与指定文件

Python打开外部文件有很多方法, os.popen打开外部程序,但发现只能打开文件所在目录的文件 os.system可打开外部文件os.system(command) command 要执行的命令,相当于在Windows...

shzwork
31分钟前
2
0
Leetcode # 118:Pascal's Triangle 杨辉三角

118:Pascal's Triangle 杨辉三角 Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. 给定一个非负整数 *numRows,*生成杨辉三角的前 numRows 行。 ......

iCodeBugs
41分钟前
1
0
IntelliJ IDEA导入Gradle项目

1.File > Open 找到项目后选择build.gradle文件,点击ok image 2.点击Open as Project image 3.选择本地Gradle以及JDK image 4.点OK完成...

青峰Jun19er
46分钟前
2
0
Python实现斐波那契数列

斐波那契数列大家都很熟悉吧,咱们在高中学数学的时候,老师会讲这个定律以及算法,其实数据结构和数学息息相关,数学思维好的往往逻辑思维就比较好,今天小猿圈带大家学习一下python的斐波那...

小猿圈加加
47分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部