本文将从以下几个方面讲解Scrapy爬虫的基本操作
- Scrapy爬虫介绍
- Scrapy安装
- Scrapy实例——爬取1905电影网
- 相关资料
Scrapy 爬虫介绍
Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。
Scrapy 使用 Twisted这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求。整体架构如下图所示:
从上图中可以看到,Scrapy已经帮我们处理好了Downloader以及Scheduler。作为轻量级用户,我们完全不用关心爬虫是如何调度及下载的,只需要关注爬虫的爬去规则(Spiders)以及如何存储(Item Pipeline)。
Scrapy的安装
网上有许多关于Scrapy安装的博客,大家自行搜索,我是采用pip的安装方式
pip install scrapy
如果使用pip安装时遇到 KeyError: u’\u6e29’ 的问题,可以参考我的博客
python2.7 pip install 报错KeyError: u’\u6e29’解决方案
Scrapy 实例
爬虫任务介绍
这次要爬去1905电影网的所有中国电影,共14499部电影
下图为目录页,每个目录页有30个电影,共有486个目录页
下图为需要保存的电影页面,我们将其保存到本地,以后再解析
我们观察到目录页url是有规律的,
第一页 http://www.1905.com/mdb/film/list/country-China/o0d0p0.html
第二页 http://www.1905.com/mdb/film/list/country-China/o0d0p1.html
最后页 http://www.1905.com/mdb/film/list/country-China/o0d0p484.html
因此我们每次替换上面url中黑体的部分即可。
整个爬虫的逻辑为
1. 构建所有目录页url
2. 爬取目录页,并分析出当前目录页中的电影页url
3. 爬取电影页,并保存
创建爬虫
在开始爬取之前,必须创建一个新的Scrapy项目。 利用cmd进入打算存储代码的目录中,然后输入命令scrapy startproject movie1905
构建爬虫项目,其中 movie1905 项目名,可自定义。
该命令将会创建包含下列内容的movie1905目录:
movie1905/
scrapy.cfg
movie1905/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
其中settings.py是项目的配置文件,spiders目录是放置爬虫的目录,pipelines.py是用于存数据的文件,items.py是爬虫爬取数据的容器
定义Item
item 是保存爬取到的数据的容器,我们根据自己的需要定义Item
import scrapy
class Movie1905Item(scrapy.Item):
url = scrapy.Field() # url
html = scrapy.Field() # 爬取下来的网页内容
filename = scrapy.Field() # 网页存储在本地的文件名
撰写爬虫
这个爬虫需要在spiders目录里新建一个.py文件
class Movie(scrapy.Spider):
name = "chineseMovie"
allowed_domains = ["1905.com"]
其中name 是用于在命令行调用爬虫时作为爬虫区分的标识,简单说就是爬虫的名字,该名字必须唯一!
allowed_domains 是爬虫允许爬去的域名,如果不在该域名中则不爬取。
应该来说还应有一个start_urls 作为Spider在启动时进行爬取的url列表,但考虑到我们需要爬取的url有一定的规则,因此用一个中间件代替,如下所示:
def start_requests(self):
basic_url = "http://www.1905.com/mdb/film/list/country-China/o0d0p%s.html"
start,end = 0,485
for i in range(start,end):
url = basic_url.replace("%s",str(i))
yield scrapy.http.Request(url,self.parse)
分析网页时对于目录页与电影页需要区别对待。
对于目录页的处理
首先对于目录页我们需要分析出当前目录页中的电影页url,并将该url交给scrapy去进行接下来的处理
def parse(self, response):
sel = Selector(response)
urls = sel.xpath('//ul[@class="inqList pt18"]/li/a/@href').extract()
for url in urls:
url = "http://www.1905.com" + url
yield scrapy.http.Request(url,self.parse_movie)
注意到,提取url标签时我们采用xpath进行标签定位,关于xpath的介绍可以看这里
这里还有一种更简单的xpath定位方法,我们使用chrome浏览器,右键审查元素找到我们想要的标签,在该标签上邮件copy,选择copy xpath,根据该结果进行适当调整即可,如下图所示:
对于电影页的处理
根据前面所说,我们暂时不分析电影页中的内容,仅仅是将其存入本地
def parse_movie(self, response):
item = Movie1905Item()
item['url'] = response.url
item['html'] = response.body
item['filename'] = "movie_" + hashlib.sha1(response.url).hexdigest() + ".txt"
print response.url
return item
保存数据
爬虫处理完数据后,返回一个item,scrapy看到返回结果是个item就会根据配置文件将其交给相应的pipeline的process_item方法进行数据的保存工作,这里没有什么太多可说的,大家根据自己的定义写就可以了
class Movie1905Pipeline(object):
db = "movie" # 数据库名
filePath = "E://crawlerFile//movie//" # 爬去下来的文件保存目录地址
def __init__(self):
self.SQLconn = SqlConnector(db=self.db) # 我自己封装的数据库类
def process_item(self, item, spider):
self.save_in_File(item)
self.save_in_DB(item)
return item
# 存入文件
def save_in_File(self,item):
file_object = open(self.filePath + item['filename'],'w')
file_object.write(item['html'])
file_object.close()
# 存入数据库
def save_in_DB(self,item):
query = "insert into movie(url,filename) values(%s,%s)"
query = self.SQLconn.generateQuery(query,[item['url'],item["filename"]])
self.SQLconn.insert(query)
配置文件
我们可以利用配置文件对我们的爬虫进行深层定制,现在这个spider只需要增加两个配置
DOWNLOAD_HANDLERS = {'s3': None,}
ITEM_PIPELINES=['movie1905.pipelines.Movie1905Pipeline']
第一行我暂时也不知道是做什么用的,但没有这行爬虫不会运行
第二行是定义爬虫的Pipeline
爬虫运行
在cmd内进入同scrapy.cfg同一级目录中,运行
scrapy crawl chineseMovie
运行结果如下图所示