Item Pipeline介绍

Item对象是一个简单的容器,用于收集抓取到的数据,其提供了类似于字典(dictionary-like)的API,并具有用于声明可用字段的简单语法。

Scrapy的Item Pipeline(项目管道)是用于处理数据的组件。

当Spider将收集到的数据封装为Item后,将会被传递到Item Pipeline(项目管道)组件中等待进一步处理。Scrapy犹如一个爬虫流水线,Item Pipeline是流水线的最后一道工序,但它是可选的,默认关闭,使用时需要将它激活。如果需要,可以定义多个Item Pipeline组件,数据会依次访问每个组件,执行相应的数据处理功能。

Item Pipeline的典型应用:
 ·清理数据。
 ·验证数据的有效性。
 ·查重并丢弃。
 ·将数据按照自定义的格式存储到文件中。
 ·将数据保存到数据库中。

  编写自己的Item Pipeline组件其实很简单,它只是一个实现了几个简单方法的Python类。当建立一个项目后,这个类就已经自动创建了。打开项目qidian_hot下的pipelines.py,发现自动生成了如下代码:

class LianjiaPipeline(object):def process_item(self, item, spider):return item        

LianjiaPipeline是自动生成的Item Pipeline类,它无须继承特定的基类,只需要实现某些特定的方法,如process_item()、open_spider()和close_spider()。注意,方法名不可改变。process_item()方法是Item Pipeline类的核心方法,必须要实现,用于处理Spider爬取到的每一条数据(Item)。它有两个参数:item:待处理的Item对象。spider:爬取此数据的Spider对象。方法的返回值是处理后的Item对象,返回的数据会传递给下一级的Item Pipeline(如果有)继续处理。

爬取长沙链家二手房

https://cs.lianjia.com/ershoufang/

我们爬取二手房的标题、地点、价格以及其他一些房屋基本信息。点击房屋标题进入详情页面,可以查看详细信息。

我们还要爬取详情页面房屋配备电梯情况以及产权年限。

编写爬虫文件

爬虫文件是我们用Scrapy爬虫主要要编写的文件,其作用主要有两个:

  1. 向网页发起请求
  2. 向其他组件发送响应/数据

我们可以利用命令行scrapy genspider 爬虫名称 网页域名自动生成爬虫文件,也可以手动创建爬虫文件。

这里在spiders子目录文件夹下手动创建一个名为lianjia_spider.py的爬虫文件

导入需要用到的库文件,命名爬虫名称

import scrapy
from scrapy import Request
from lianjia.items import LianjiaItem
class HomespiderSpider(scrapy.Spider):name = 'home'

重写start_requests()方法

def start_requests(self):url = 'https://cs.lianjia.com/ershoufang/'yield Request(url,callback=self.parse)

Request方法的callback参数用于指定爬虫响应的解析方法,默认为parse方法。

解析页面,使用XPath提取数据

打开开发者工具,可以看到与房屋有关的信息都在< div class="info clear" >下面,包括标题、地址、基本信息、价格等。我们首先定位到<div class="info clear">这个节点,然后再在这个节点下提取各种信息。

def parse(self, response):roomList = response.xpath('//ul/li/div[@class="info clear"]')

首先提取标题和地点,使用xpath helper这个插件可以很方便编写xpath表达式。

输入xpath表达式,右边会显示提取到的信息,同时网页中对应的信息会高亮,可以验证xpath是否正确。所以我们提取到标题的完整xpath就是://ul/li/div[@class="info clear"]/div[@class="title"]/a,但是我们之前已经定位到<div class="info clear">这个节点,只需要在这个节点之下的xpath表达式就可以提取标题了。同理,提取位置和其他基本信息。

for oneList in roomList:title = oneList.xpath('./div[@class="title"]/a/text()').extract_first()place = oneList.xpath('./div[@class="flood"]//a[1]/text()').extract_first()+'- '+oneList.xpath('./div[@class="flood"]//a[2]/text()').extract_first()houseInfo = oneList.xpath('./div[@class="address"]/div/text()').extract_first() 

由于房屋的基本信息包含多项以“ | ”分隔的信息:1室1厅 | 39.98平米 | 北 | 精装 | 中楼层(共28层) | 2008年建 | 板楼。我们需要提取其中的户型、面积、楼层、朝向并分别保存:

houseInfoList = houseInfo.split("|")
type = houseInfoList[0]
area = houseInfoList[1]
direction = houseInfoList[2]
floor = houseInfoList[4]

提取单价和总价:

unitPrice = oneList.xpath('./div[@class="priceInfo"]/div[@class="unitPrice"]/span/text()').extract_first()
totalPrice = oneList.xpath('./div[@class="priceInfo"]/div[@class="totalPrice"]/span/text()').extract_first()+oneList.xpath('./div[@class="priceInfo"]/div[@class="totalPrice"]/text()').extract_first()

至此,基本信息都提取完了,接下来需要保存数据,提取详情页面的数据。

使用Item保存数据

打开items.py 建立item成员变量,也就是我们需要提取的信息

import scrapy
class LianjiaItem(scrapy.Item):# -*- coding: utf-8 -*-title = scrapy.Field()place = scrapy.Field()type = scrapy.Field()area = scrapy.Field()direction = scrapy.Field()floor = scrapy.Field()unitPrice = scrapy.Field()totalPrice = scrapy.Field()elevator = scrapy.Field()propertyYears = scrapy.Field()

回到爬虫文件,初始化item类,并且将提取的信息保存到item中:

item = LianjiaItem()
item["title"] = title
item["place"] = place
item["type"] = type
item["area"] = area
item["direction"] = direction
item["floor"] = floor
item["unitPrice"] = unitPrice
item["totalPrice"] = totalPrice

获取详情页面链接并解析


可以看到详情面的链接是我们之前提取的标题所在的a标签的href属性

# 获取详情链接
clearUrl = oneList.xpath('./div[@class="title"]/a/@href').extract_first()
# print(clearUrl)
yield Request(clearUrl,meta={"item":item},callback=self.clearUrlParse)

获取详情页面连接后,像爬虫发起爬取请求,注意这里的meta参数和callback参数。

meta用于传递用户参数,我们之前提取的信息保存在item中,这里将item一并传递出去
callback用于指定解析函数,这里不能采用默认的parse,需要编写新的解析函数。

# 详情链接解析函数
def clearUrlParse(self,response):elevator = response.xpath('//div[@class="base"]//ul/li[last()-1]/text()').extract_first()propertyYears = response.xpath('//div[@class="base"]//ul/li[last()]/text()').extract_first()item = response.meta["item"]item["elevator"] = elevatoritem["propertyYears"] = propertyYearsyield item

获取下一页链接

获取下一页有两种方法,

  • 直接提取下一页的相对链接,直至为None,表明到了最后一页。
  • 提取总页数,修改下一页的链接 例如第二页的链接https://cs.lianjia.com/ershoufang/pg2/ pg后面的数字代表当前页,修改该数字即可。

方法一:

next = response.xpath('//div[@class="page-box house-lst-page-box"]/a[last()]/@href').extract_first()
nextUrl = 'https://cs.lianjia.com'+next
if nextUrl:yield Request(nextUrl, callback=self.parse)

方法二:

def __init__(self):self.currentPage = 1self.totalPage = 1
self.currentPage += 1
nextUrl = 'https://cs.lianjia.com/ershoufang/pg%d'%self.currentPage
self.totalPage = response.xpath('//div[@class="leftContent"]//div[@class="page-box house-lst-page-box"]/a[last()-1]/text()').extract_first()
print(self.totalPage)
if self.currentPage < self.totalPage:yield Request(nextUrl,callback=self.parse)

至此,爬虫文件已经编写完成了,设置一下代理和robots协议就可以直接运行爬虫导出数据了

但是我们希望爬取的信息按照指定的顺序排列保存,当前的顺序是随机的。此外单价一栏下的信息是“单价12106元/平米”,正常来讲应该去掉单价二字。所以接下来使用Item Pipeline进行数据二次处理。

使用Item Pipeline处理并保存数据

打开pipelines.py,默认生成了一个LianjiaPipeline类,其中有一个process方法,我们就是在这个方法中处理数据的。

处理数据

import re
class LianjiaPipeline(object):def process_item(self, item, spider):item["unitPrice"]=re.sub("单价",'',item["unitPrice"])return item

用到正则表达式导入re库,去掉单价信息中的“单价”二字。

按一定格式保存数据

class csvPipeline(object):def __init__(self):self.index = 0self.file = Nonedef open_spider(self,spider):self.file = open("home.csv", "a", encoding="utf-8")def process_item(self,item,spider):if self.index == 0:columnName = "title,place,type,area,direction,floor,unitPrice,totalPrice,elevator,propertyYears\n"self.file.write(columnName)self.index = 1homeStr = item["title"]+","+item["place"]+","+item["type"]+","+item["area"]+","+item["direction"]+","+ \item["floor"]+","+item["unitPrice"]+","+item["totalPrice"]+","+item["elevator"]+","+item["propertyYears"]+"\n"self.file.write(homeStr)return itemdef close_spider(self,spider):self.file.close()

再定义一个csvPipeline类,其中除了process方法,还有open_spider方法和close_spider方法用于打开和关闭爬虫,再次highlight函数名不能随意更改

配置Item Pipeline


默认是'lianjia.pipelines.LianjiaPipeline': 300,这里再将csvPipeline加入,后面的数字400代表优先级,数字越小优先级越高,代表Pipeline处理item中数据的顺序。

运行爬虫

使用命令行运行爬虫比较麻烦,可以编写一个start.py文件运行爬虫

from scrapy import  cmdline
cmdline.execute("scrapy crawl home".split())

可以看到提取的信息按照我们设定的顺序排列,并且将单价信息进行了处理。

完整的爬虫文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#@Time  : 2020/2/21 18:07
#@Author: bz
#@File  : lianjia_spider.pyimport scrapy
from scrapy import Request
from lianjia.items import LianjiaItemclass HomespiderSpider(scrapy.Spider):name = 'home'def __init__(self):self.currentPage = 1self.totalPage = 1def start_requests(self):url = 'https://cs.lianjia.com/ershoufang/'yield Request(url,callback=self.parse)def parse(self, response):roomList = response.xpath('//ul/li/div[@class="info clear"]')for oneList in roomList:title = oneList.xpath('./div[@class="title"]/a/text()').extract_first()place = oneList.xpath('./div[@class="flood"]//a[1]/text()').extract_first()+'- '+oneList.xpath('./div[@class="flood"]//a[2]/text()').extract_first()houseInfo = oneList.xpath('./div[@class="address"]/div/text()').extract_first()houseInfoList = houseInfo.split("|")type = houseInfoList[0]area = houseInfoList[1]direction = houseInfoList[2]floor = houseInfoList[4]unitPrice = oneList.xpath('./div[@class="priceInfo"]/div[@class="unitPrice"]/span/text()').extract_first()totalPrice = oneList.xpath('./div[@class="priceInfo"]/div[@class="totalPrice"]/span/text()').extract_first()+oneList.xpath('./div[@class="priceInfo"]/div[@class="totalPrice"]/text()').extract_first()item = LianjiaItem()item["title"] = titleitem["place"] = placeitem["type"] = typeitem["area"] = areaitem["direction"] = directionitem["floor"] = flooritem["unitPrice"] = unitPriceitem["totalPrice"] = totalPrice# 获取详情链接clearUrl = oneList.xpath('./div[@class="title"]/a/@href').extract_first()# print(clearUrl)yield Request(clearUrl,meta={"item":item},callback=self.clearUrlParse)# 获取下一页链接self.currentPage += 1nextUrl = 'https://cs.lianjia.com/ershoufang/pg%d'%self.currentPageself.totalPage = response.xpath('//div[@class="leftContent"]//div[@class="page-box house-lst-page-box"]/a[last()-1]/text()').extract_first()if self.currentPage < self.totalPage:yield Request(nextUrl,callback=self.parse)# 详情链接解析函数def clearUrlParse(self,response):elevator = response.xpath('//div[@class="base"]//ul/li[last()-1]/text()').extract_first()propertyYears = response.xpath('//div[@class="base"]//ul/li[last()]/text()').extract_first()item = response.meta["item"]item["elevator"] = elevatoritem["propertyYears"] = propertyYearsyield item

Python爬虫框架Scrapy入门(三)爬虫实战:爬取长沙链家二手房相关推荐

  1. 简单python脚本 爬取杭州链家二手房 房价信息

    爬取链家房价信息 主要使用以下库: requests BeautifulSoup 相关问题 当爬取次数太多的时候,可能会遇到被封的情况或者验证码, 大佬们可以自行解决,这个脚本里面我就不掺和了,毕竟我 ...

  2. python数据分析案例2-1:Python练习-Python爬虫框架Scrapy入门与实践

    本文建立在学习完大壮老师视频Python最火爬虫框架Scrapy入门与实践,自己一步一步操作后做一个记录(建议跟我一样的新手都一步一步进行操作). 主要介绍: 1.scrapy框架简介.数据在框架内如 ...

  3. Python爬虫框架 scrapy 入门经典project 爬取校花网资源、批量下载图片

    ####1.安装scrapy 建议:最好在新的虚拟环境里面安装scrapy 注意:博主是在 Ubuntu18.04 + Python3.6 环境下进行开发的,如果遇到安装scrapy不成功请自行百度/ ...

  4. 用Python爬取2020链家杭州二手房数据

    起源于数据挖掘课程设计的需求,参考着17年这位老兄写的代码:https://blog.csdn.net/sinat_36772813/article/details/73497956?utm_medi ...

  5. scrapy由浅入深(三) selenium模拟爬取ajax动态页面(智联招聘)

    爬取智联招聘的网址:https://sou.zhaopin.com/?pageSize=60&jl=489&kw=python&kt=3 上一篇博客爬取了前程无忧的职位招聘信息 ...

  6. 最流行的python爬虫框架_Python最火爬虫框架Scrapy入门与实践

    Scrapy框架简介Scrapy 是用 Python 实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 通常我 ...

  7. python 爬虫框架scrapy 入门 爬取博客园新闻(代码)

    1.代码jobbole.py写爬取策略, 2.settings.py  配置pipelines.配置图片下载.配置是否遵循robote协议.数据库配置等 3.pipelines.py 主要是配置数据存 ...

  8. 【学习笔记】爬虫框架Scrapy入门

    一. Scrapy简介.架构.数据流和项目结构 二. Scrapy入门 1. Scrapy架构由哪些部分组成? 1.1 Scrapy简介 Scrapy是:由Python语言开发的一个快速.高层次的屏幕 ...

  9. 爬虫框架Scrapy入门——爬取acg12某页面

    1.安装 1.1自行安装python3环境 1.2ide使用pycharm 1.3安装scrapy框架 2.入门案例 2.1新建项目工程 2.2配置settings文件 2.3新建爬虫app 新建ap ...

最新文章

  1. 谷歌Android运用商铺下架染辣手机软件
  2. 二十二、“此生无悔入华夏,来世还在种花家”(2021.7.1)
  3. JDK8的排序大法!!
  4. mysql查询不重复记录数_mysql查询不重复的行内容,不重复的记录数.count,distinct
  5. 概率论和数理统计 - 01
  6. linux命令dh f,linux 下 find 命令的高级用法
  7. XP pro下安装Windows XP Tablet PC 2005组件教程
  8. 《童趣》——《所见》《小儿垂钓》《村居》《浮生六记·童趣》 ——诗文诵读教学设计
  9. LED背光源技术特点
  10. c语言求数组中绝对值最小值,整数数组中两两之差绝对值最小的值
  11. 基于Unity的VR迷宫游戏项目技术分享
  12. 视频号计划,撑得起微博下一个十年?
  13. mysql 不会丢失数据吗_讨论MySQL丢失数据的几种情况
  14. Repeated measures ANOVA with R
  15. 计算机专业的高考要考什么科,高考技术科目考什么内容
  16. Nginx Sticky的使用及踩过的坑(nginx-sticky-module)
  17. AcWing 1145. 北极通讯网络 题解
  18. 万花尺matlab仿真(圆内旋轮线,异形齿轮)
  19. openwrt fota
  20. linux cacti监控tomcat,Cacti监控Tomcat服务器实现过程

热门文章

  1. 【兴趣书签】为什么观测之后量子态会坍塌
  2. 浅谈多重积分及其计算
  3. 服务器虚拟化vmware hyper-v,浅谈Hyper-v与VMware服务器虚拟化比较
  4. Android三方依赖冲突及Gradle的exclude使用
  5. h5压缩图片 亲测有效
  6. 维图PDMS切图软件
  7. 基于微信小程序电影交流平台源码成品(微信小程序毕业设计)
  8. 由酷6员工猝死想到的:IT民工 我该拿什么拯救你
  9. insyde H2OFFT cannot run on battery power
  10. 内网服务器(不通外网)访问高德在线地图服务的方法