前言
本期我们正式开始我们的爬虫开发之路,在这个资本主义的时代我们还是要随大流。Scrapy框架作为爬虫领域的一大宠儿,今天就熟悉它的开发模式并用它完成我们第一个爬虫
一、Scrapy工厂之美
在开始爬虫编写之前按照基本的礼仪,来!将镜头给我们的主角!看看官方的架构图
说到爬虫必然要提起它,因为它能够提升爬虫的开发效率,从而让我们更好的实现爬虫。大家都知道工厂里面的流水线生产就好比Scrapy框架的工作流程。
它是一个为了采集网页数据、抽取结构化数据而基于Pythony编写的应用框架,框架封装并且包含:Request异步调度处理、Downloader多线程下载器、Selector解析器的Xpath提取功能和、Twisted框架的异步处理。对于网站爬取的速度还是非常快的
说到这里可能会有一些小伙伴会问:既然已经有这么好的爬虫框架了,为什么还要使用 Requests 库请求网页数据开发爬虫呢?其实吧,Requests它同样是一个功能十分强大的库,它能够满足大部分网页数据获取的需求。其工作原理是向服务器发送数据请求,至于数据的下载和解析,都需要自己处理,因而灵活性高,而由于 Scrapy 框架的封装,使得其灵活性降低。
至于使用哪种方式开发爬虫,完全取决于个人的实际需求。今天我们就先讲Scrapy框架开发爬虫,其实对于初学者来说先学习Reuqests库开发爬虫是最好的开始。
二、第一个爬虫工程
为了更加直观的了解Scrapy爬虫开发模式,我这里找了一个北京4S店的网站做了一个简单的demo。
下图是网站的页面,我们本次爬虫!采集目标选了三个字段信息(店家名称、电话、地址)还有就是翻页采集
创建Scrapy项目:scrappy startproject qieche(项目名)
接着进入到我们创建好的Project文件内创建我们的爬虫文件:
scrapy genspider dealer url(网站地址)
这是一个静态网页…简直就是So easy!!每一位开发爬虫、或者是做网页分析的人,相信都会在定位元素、获取Xpath上花费大量的时间,因为当我们使用的爬虫框架成熟之后(比如Scrapy),基本上大量的时间都花费在了页面的解析上、反爬上面了。如果没有一些辅助工具的话,我们只能通过搜索html源代码,定位一些元素去找到对应的位置,非常的麻烦以及耗时,而且我们并不能保证写的提取规则一次性能完美的运行而让你感动。
https://chrome.google.com/webstore/detail/hgimnogjllphhhkhlmebbmlgjoejdpjl(Chrom安装地址)
在咱们浏览器的扩展程序中打开它、开始写我们的Xpath吧
这个网站的翻页同样跟很多传统的静态网站基本一个套路,都是URL上的一些变动实现翻页功能,比如常见的一些网站你会发现它的翻页URL中可能是page=1这样一直叠加实现翻页操作
註:当然这是简单的,有些URL中还会夹杂很多其他参数
三、编写Scrapy工程文件
首先打开item.py文件,定制我们需要采集的数据存储字段
# -*- coding: utf-8 -*-
import scrapy
class QicheItem(scrapy.Item):
shop_name = scrapy.Field()
phone = scrapy.Field()
site = scrapy.Field()
定制完采集字段以后,这个时候就可以开始编写我们的爬虫了,代码如下:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request
from qiche.items import QicheItem
import json
green = "\033[1;32;40m %s \033[0m"
class DealerSpider(scrapy.Spider):
name = 'dealer'
start_urls = ['http://dealer.autohome.com.cn/beijing/#pvareaid=103416/']
def parse(self, response):
times = response.meta.get("num",2)
#提取店铺名称Xpath
shop = response.xpath('//ul[@class="info-wrap"]/li[@class="tit-row"]/a/span/text()').extract()
#提取联系电话Xpath
phone_ele = response.xpath('//li/span[@class="tel"]/text()').extract()
#提取地址信息Xpath
site_name =response.xpath('//li/span[@class="info-addr"]/text()').extract()
for shop,phone_ele,site_name in zip(shop,phone_ele,site_name):
item = QicheItem()
item['shop_name']=shop
item['phone'] = phone_ele
item['site'] = site_name
print green % json.dumps(dict(item),ensure_ascii=False, indent=4)
yield item
if site_name:
#翻页URL
next_page = 'http://dealer.autohome.com.cn/beijing?countyId=0&brandId=0 \
&seriesId=0&factoryId=0&pageIndex=%s&kindId=1&orderType=0' % times
print 'Next Page: {}'.format(next_page)
yield Request(next_page,callback=self.parse,meta={"num":times+1})
爬虫逻辑:爬虫运行后将会访问上面的start_urls、这里的start_urls是我们上面创建爬虫文件命令行预先传进来的,当然我们也可以自己重写start_requests方法。爬虫访问start_urls以后产生的response会返回给我们的parse函数,所以这一步你感觉其实用Requests写也只是一行代码的事…
拿到了response我们就开始解析我们想要的数据、或者在parse函数内进行一些其它的操作都可以,页面中产生的URL我们要怎么加入到队列中循环采集呢?我们把页面提取数据的解析规则写好以后、开始寻找我们的下一页入口、这里我们的下一页入口URL其实是固定的,page参数控制翻页,所以num做为一个计数器,凑成完成的URL。最后将翻页的URL跟num交给Scrapy的callback回调函数就可以完美闭环。
上面代码中的meta参数说明:
- meta它是一个字典,主要用于解析函数之间传递值
- Request对象接受meta参数,也就是字典对象,同样Response的对象有一个meta属性可以取到相应Request传过来的meta
註:这就是它们的传递、接收方式
当item在spider中被收集以后、它将被传递到pipeline,它决定此数据(item)是丢弃还是存储,而pipeline的典型应用场景有:检查item字段是否缺失、重复数据检查、数据存储(文件系统、数据库系统…)
# -*- coding: utf-8 -*-
from codecs import open
import json
import redis
class QichePipeline(object):
def __init__(self,*args,**kwards):
super(QichePipeline,self).__init__(*args,**kwards)
self.db = redis.Redis(host='localhost',port=6379,db=0)
def process_item(self, item, spider):
#write db
#write file
self.db.set(item['shop_name'],item['phone'])
return item
process_item函数可以完成我们对item数据集的操作,item对象就是数据流,存储方式我这里用了一下Redis做测试,真正爬虫业务肯定是不能这么做!所以可以根据自己需求定制。
pipeline文件写完就好啦?当然不行
默认是在settings.py文件关闭pipeline管道的。如果要使用自定义的管道文件,我们需要在settings.py文件启用pipeline(打开注释),如果你在pipeline定义了多个管道的类,在settings.py中可以写多个pipeline的类,通过数字优先取决优先级。优先级的取值范围为0到1000。数值越小优先级越高
四、数据之美
让我们启动第一只爬虫看看采集的效果
en~~~
我们下期再见高级硬核讲解!!!!!
谢谢您能抽出宝贵的时间阅读,创作不易,如果您喜欢的话,点个关注再走吧。您的支持是我创作的动力,希望今后能带给大家更多优质的文章。