Scrapy Learning笔记(四)- Scrapy双向爬取

摘要:介绍了使用Scrapy进行双向爬取(对付分类信息网站)的方法。

所谓的双向爬取是指以下这种情况,我要对某个生活分类信息的网站进行数据爬取,譬如要爬取租房信息栏目,我在该栏目的索引页看到如下页面,此时我要爬取该索引页中的每个条目的详细信息(纵向爬取),然后在分页器里跳转到下一页(横向爬取),再爬取第二页中的每个条目的详细信息,如此循环,直至最后一个条目。

这样来定义双向爬取:

  • 水平方向 – 从一个索引页到另一个索引页
  • 纯直方向 – 从一个索引页到条目详情页

 

在本节中,

提取索引页到下一个索引页的xpath为:‘//*[contains(@class,"next")]//@href‘

提取索引页到条目详情页的xpath为:‘//*[@itemprop="url"]/@href‘

manual.py文件的源代码地址:

https://github.com/Kylinlin/scrapybook/blob/master/ch03%2Fproperties%2Fproperties%2Fspiders%2Fmanual.py

 

把之前的basic.py文件复制为manual.py文件,并做以下修改:

  • 导入Request:from scrapy.http import Request
  • 修改spider的名字为manual
  • 更改starturls为‘http://web:9312/properties/index00000.html‘
  • 将原料的parse函数改名为parse_item,并新建一个parse函数,代码如下:
#本函数用于提取索引页中每个条目详情页的超链接,以及下一个索引页的超链接
def parse(self, response):
        # Get the next index URLs and yield Requests
        next_selector = response.xpath(‘//*[contains(@class,"next")]//@href‘)
        for url in next_selector.extract():
            yield Request(urlparse.urljoin(response.url, url))#Request()函数没有赋值给callback,就会默认回调函数就是parse函数,所以这个语句等价于
yield Request(urlparse.urljoin(response.url, url), callback=parse)

        # Get item URLs and yield Requests
        item_selector = response.xpath(‘//*[@itemprop="url"]/@href‘)
        for url in item_selector.extract():
            yield Request(urlparse.urljoin(response.url, url),
                          callback=self.parse_item)

如果直接运行manual,就会爬取全部的页面,而现在只是测试阶段,可以告诉spider在爬取一个特定数量的item之后就停止,通过参数:-s CLOSESPIDER_ITEMCOUNT=10

运行命令:$ scrapy crawl manual -s CLOSESPIDER_ITEMCOUNT=10

它的输出如下:

 

spider的运行流程是这样的:首先对start_url中的url发起一个request,然后下载器返回一个response(该response包含了网页的源代码和其他信息),接着spider自动将response作为parse函数的参数并调用。

parse函数的运行流程是这样的:

1. 首先从该response中提取class属性中包含有next字符的标签(就是分页器里的“下一页”)的超链接,在第一次运行时是:‘index_00001.html‘。

2. 在第一个for循环里首先构建一个完整的url地址(’http://web:9312/scrapybook/properties/index_00001.html‘),把该url作为参数构建一个Request对象,并把该对象放入到一个队列中(此时该对象是队列的第一个元素)。

3. 继续在该respone中提取属性itemprop等于url字符的标签(每一个条目对应的详情页)的超链接(譬如:‘property_000000.html‘)。

4. 在第二个for循环里对提取到的url逐个构建完整的url地址(譬如:’http://web:9312/scrapybook/properties/ property_000000.html’),并使用该url作为参数构建一个Request对象,按顺序将对象放入到之前的队列中。

5. 此时的队列是这样的


Request(http://…index_00001.html)


Request(http://…property_000000.html)



Request(http://…property_000029.html)

6. 当把最后一个条目详情页的超链接(property_000029.html)放入队列后,调度器就开始处理这个队列,由后到前把队列的最后一个元素提取出来放入下载器中下载并把response传入到回调函数(parse_item)中处理,直至到了第一个元素(index_00001.html),因为没有指定回调函数,默认的回调函数是parse函数本身,此时就进入了步骤1,这次提取到的超链接是:‘index_00002.html‘,然后就这样循环下去。

这个parse函数的执行过程类似于这样:

next_requests = []
for url in...
    next_requests.append(Request(...))
for url in...
    next_requests.append(Request(...))
return next_requests

可以看到使用后进先出队列的最大好处是在处理一个索引页时马上就开始处理该索引页里的条目列表,而不用维持一个超长的队列,这样可以节省内存,有没有觉得上面的parse函数写得有些让人难以理解呢,其实可以换一种更加简单的方式,对付这种双向爬取的情况,可以使用crawl的模板。

首先在命令行里按照crawl的模板生成一个名为easy的spider

$ scrapy genspider -t crawl easy web

打开该文件

...
class EasySpider(CrawlSpider):
    name = ‘easy‘
    allowed_domains = [‘web‘]
    start_urls = [‘http://www.web/‘]
    rules = (
        Rule(LinkExtractor(allow=r‘Items/‘), callback=‘parse_item‘, follow=True),
    )
    def parse_item(self, response):
        ...

可以看到自动生成了上面的那些代码,注意这个spider是继承了CrawlSpider类,而CrawlSpider类已经默认提供了parse函数的实现,所以我们并不需要再写parse函数,只需要配置rules变量即可

rules = (
    Rule(LinkExtractor(restrict_xpaths=‘//*[contains(@class,"next")]‘)),
    Rule(LinkExtractor(restrict_xpaths=‘//*[@itemprop="url"]‘),
         callback=‘parse_item‘)
)

运行命令:$ scrapy crawl easy -s CLOSESPIDER_ITEMCOUNT=90

这个方法有以下不同之处:

  • 这两个xpath与之前使用的不同之处在于没有了a和href这两个约束字符,因为LinkExtrator是专门用来提取超链接的,所以会自动地提取标签中的a和href的值,当然可以通过修改LinkExtrator函数里的参数tags和attrs来提取其他标签或属性里的超链接。
  • 还要注意的是这里的callback的值是字符串,而不是函数的引用。
  • Rule()函数里设置了callback的值,spider就默认不会跟踪目标页里的其他超链接(意思是说,不会对这个已经爬取过的网页使用xpaths来提取信息,爬虫到这个页面就终止了)。如果设置了callback的值,也可以通过设置参数follow的值为True来进行跟踪,也可以在callback指定的函数里return/yield这些超链接。
时间: 2024-08-03 21:19:06

Scrapy Learning笔记(四)- Scrapy双向爬取的相关文章

爬虫(十七):Scrapy框架(四) 对接selenium爬取京东商品数据

1. Scrapy对接Selenium Scrapy抓取页面的方式和requests库类似,都是直接模拟HTTP请求,而Scrapy也不能抓取JavaScript动态谊染的页面.在前面的博客中抓取JavaScript渲染的页面有两种方式.一种是分析Ajax请求,找到其对应的接口抓取,Scrapy同样可以用此种方式抓取.另一种是直接用 Selenium模拟浏览器进行抓取,我们不需要关心页面后台发生的请求,也不需要分析渲染过程,只需要关心页面最终结果即可,可见即可爬.那么,如果Scrapy可以对接S

初识scrapy,美空网图片爬取实战

这俩天研究了下scrapy爬虫框架,遂准备写个爬虫练练手.平时做的较多的事情是浏览图片,对,没错,就是那种艺术照,我骄傲的认为,多看美照一定能提高审美,并且成为一个优雅的程序员.O(∩_∩)O~ 开个玩笑,那么废话不多说,切入正题吧,写一个图片爬虫. 设计思路:爬取目标为美空网模特照片,利用CrawlSpider提取每张照片的url地址,并将提取的图片url写入一个静态html文本作为存储,打开即可查看图片. 我的环境是win8.1, python2.7+Scrapy 0.24.4,如何配环境我

Scrapy爬虫案例01——翻页爬取

之前用python写爬虫,都是自己用requests库请求,beautifulsoup(pyquery.lxml等)解析.没有用过高大上的框架.早就听说过Scrapy,一直想研究一下.下面记录一下我学习使用Scrapy的系列代码及笔记. 安装 Scrapy的安装很简单,官方文档也有详细的说明 http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/install.html .这里不详细说明了. 创建工程 我是用的是pycharm开发,打开pycharm

(4)分布式下的爬虫Scrapy应该如何做-规则自动爬取及命令行下传参

本次探讨的主题是规则爬取的实现及命令行下的自定义参数的传递,规则下的爬虫在我看来才是真正意义上的爬虫. 我们选从逻辑上来看,这种爬虫是如何工作的: 我们给定一个起点的url link ,进入页面之后提取所有的ur 链接,我们定义一个规则,根据规则(用正则表达式来限制)来提取我们想要的连接形式,然后爬取这些页面,进行一步的处理(数据提取或者其它动作),然后循环上述操作,直到停止,这个时候有一个潜在的问题,就是重复爬取,在scrapy 的框架下已经着手处理了这些问题,一般来说,对于爬取过滤的问题,通

【图文详解】scrapy安装与真的快速上手——爬取豆瓣9分榜单

写在开头 现在scrapy的安装教程都明显过时了,随便一搜都是要你安装一大堆的依赖,什么装python(如果别人连python都没装,为什么要学scrapy-.)wisted, zope interface,pywin32---现在scrapy的安装真的很简单的好不好! 代码我放github上了,可以参考: https://github.com/hk029/doubanbook 为什么要用scrapy 我之前讲过了requests,也用它做了点东西,([图文详解]python爬虫实战--5分钟做

python scrapy简单爬虫记录(实现简单爬取知乎)

之前写了个scrapy的学习记录,只是简单的介绍了下scrapy的一些内容,并没有实际的例子,现在开始记录例子 使用的环境是python2.7, scrapy1.2.0 首先创建项目 在要建立项目的目录下执行命令scrapy startproject tutorial scrapy会帮你建立好项目,接着创建蜘蛛scrapy genspider zhuhuSpider zhihu.com 当前的文件结构是 --tutorial --spiders --__init__.py --zhihuSpid

scrapy请求传参,提高爬取效率,fake-useragent

scrapy请求传参 """ # 1 传参 :yield Request(url,callback=self.parser_detail,meta={'item':item}) # 2 取参:response.meta.get('item') """ 提高爬取效率的方式 """ - 在配置文件中进行相关的配置即可:(默认还有一套setting) #1 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增

python3下scrapy爬虫(第八卷:循环爬取网页多页数据)

之前我们做的数据爬取都是单页的现在我们来讲讲多页的 一般方式有两种目标URL循环抓取 另一种在主页连接上找规律,现在我用的案例网址就是 通过点击下一页的方式获取多页资源 话不多说全在代码里(因为刚才写这篇文章时电脑出现点问题所以没存下来,所以这一版本不会那么详细) 来 看下结果522*35条连接页面的数据爬取: 是不是很爽 原文地址:https://www.cnblogs.com/woshiruge/p/8398229.html

Scrapy基础(十四)————Scrapy实现知乎模拟登陆

模拟登陆大体思路见此博文,本篇文章只是将登陆在scrapy中实现而已 之前介绍过通过requests的session 会话模拟登陆:必须是session,涉及到验证码和xsrf的写入cookie验证的问题:在scrapy中不需担心此问题,因为Request会保证这是一个会话,并且自动传递cookies原理想通,因为验证码识别的问题,这里先使用cookie模拟登陆 1 # -*- coding: utf-8 -*- 2 3 import scrapy 4 import json 5 import