scrapy简单介绍,以及使用scrapy爬豆瓣音乐
基本概念介绍SpiderSelectorsitemitem pipelineDownloader Middlewarescrapy内置交互环境例子:爬取豆瓣音乐创建项目创建Item创建Spider创建pipline:将数据存储到csv文件加入一个middleware用于记录日志settings.py运行
基本概念介绍
Spider
Spider定义了网站是如何被扒取的,通过Spider可以决定哪些url可以被扒,决定解析response中的哪些数据。
Spider大致工作流程:
- 通过start_requests()方法执行第一个请求,可以不自定义start_requests方法,默认的实现是通过make_requests_from_url对start_urls中url生成request,并默认回调parse方法。
- 在回调方法里,通过xpath selector(或其他方式)解析html数据。回调方法返回Item对象或者request对象,或者两者的迭代。
- 最后,Item对象可以通过Item Pipeline存储到数据库,或者通过Feed exports导出为json或cvs等文件上。
Selectors
Selector用于从原始的html数据中提取出我们想要的数据。基于XPath和CSS表达式实现,可以通过response.XPath和response.CSS得到Selector对象(列表)。
Selector有4个基本方法
- xpath(xPathexpression):根据XPath规则返回Selector对象列表
- css(CSSexpression):根据CSS规则返回Selector对象列表
- extract():返回unicode字符串内容
- re():根据正则表达式,返回符合要求的unicode字符串
item
item用于存储扒下来的数据,类似于django中的model,但它更简单-只有一种field。scrapy还为item提供了跟操作字典一样的接口,因此你可以像操作dict那样操作item。
item pipeline
- 净化html数据
- 验证item的有效性,无效则返回DropItem忽略不处理
- 检查是否重复爬取了
- 把item存入数据库
- 把item导出到csv/xml。。。通过与ItemExport配合
Downloader Middleware
非常类似于django的Middleware,适合想在request前和收到response后做些处理。
scrapy内置交互环境
在终端中通过执行scrapy shell http://www.douban.com指令可以进入到scrapy的交互界面,用dir()可以看到内置变量,通过它们可以进行我们想要的操作,比如通过sel我们可以进行xpath提出元素。
例子:爬取豆瓣音乐
创建项目
xxxxxxxxxxscrapy startproject doubancrawler
创建Item
item.py
x
#items.pyimport scrapyclass AlbumItem(scrapy.Item): name=scrapy.Field() artist=scrapy.Field() intro=scrapy.Field() tag=scrapy.Field() musics=scrapy.Field() class TagItem(scrapy.Item): name=scrapy.Field()创建Spider
xxxxxxxxxx#douban_music.py# -*- coding: utf-8 -*-import scrapyfrom doubancrawler import items from scrapy.utils.response import get_base_urlimport urlparseclass DoubanMusicSpider(scrapy.Spider):name = "douban_music"allowed_domains = ["douban.com"]start_urls = ("http://music.douban.com/tag/",)def parse(self,response): self.log("%s,%d"%(response.url,response.status),level=scrapy.log.WARNING) tagLinks=response.xpath("//table[@class='tagCol']")[0].xpath(".//td/a") baseUrl=get_base_url(response) for tag in tagLinks: yield items.TagItem(name=tag.xpath("./text()").extract()[0]) absolutUrl=urlparse.urljoin(baseUrl,tag.xpath("./@href").extract()[0]) yield scrapy.Request(absolutUrl,callback=self.parse_album_list) def parse_album_list(self,response): for url in response.xpath("//tr[@class='item']/td/a/@href").extract(): yield scrapy.Request(url,callback=self.parse_album_detail)def parse_album_detail(self,response): item=items.AlbumItem() #name name=response.xpath("//div[@id='wrapper']/h1/span/text()").extract()[0] item["name"]=name.strip() #artist/tag info=response.xpath("//div[@id='info']") trans={ "表演者:":"artist", "流派:":"tag", } for infoitem in info.xpath(".//span[@class='pl']"): key=infoitem.xpath("./text()").extract()[0].strip() if not key in trans: continue value=infoitem.xpath("./a/text()").extract()[0] item[trans[key]]=value #intro introlist=response.xpath("//div[@id='link-report']/span/text()").extract() item["intro"]=introlist and introlist[0] or "" #musics musics=response.xpath("//li[@class='song-item']/div[1]/text()").extract() item["musics"]="|".join(musics) return item创建pipline:将数据存储到csv文件
#pipelines.pyfrom scrapy import signalsfrom scrapy.contrib.exporter import CsvItemExporterfrom items import AlbumItem,TagItemclass CvsPipline(object): def __init__(self): self.files = {} def from_crawler(cls, crawler): pipeline = cls() crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) return pipeline def spider_opened(self, spider): tagFile= open('%s_tags.csv' % spider.name, 'w+b') albumFile= open('%s_albums.csv' % spider.name, 'w+b') self.files[spider] = (tagFile,albumFile) self.tagExporter = CsvItemExporter(tagFile) self.albumExporter = CsvItemExporter(albumFile) self.tagExporter.start_exporting() self.albumExporter.start_exporting() def spider_closed(self, spider): self.tagExporter.finish_exporting() self.albumExporter.finish_exporting() tagFile,albumFile=self.files.pop(spider) tagFile.close() albumFile.close() def process_item(self, item, spider): if isinstance(item,TagItem): self.tagExporter.export_item(item) elif isinstance(item,AlbumItem): self.albumExporter.export_item(item) return item加入一个middleware用于记录日志
#middlewares.pyclass MyDownloadMiddleware(object): def process_response(self,request,response,spider): spider.log("%s,%d"%(response.url,response.status),level=scrapy.log.WARNING) import time print response.url,response.status,time.time() return responsesettings.py
在settings.py上配置middleware和pipline,以及反爬虫策略。
xxxxxxxxxxBOT_NAME = 'doubancrawler'SPIDER_MODULES = ['doubancrawler.spiders']NEWSPIDER_MODULE = 'doubancrawler.spiders'import sys reload(sys) sys.setdefaultencoding('gbk') LOG_LEVEL="WARNING"LOG_FILE="scrapy.log"ITEM_PIPELINES = { 'doubancrawler.pipelines.CvsPipline': 1000,}DOWNLOADER_MIDDLEWARES = { 'doubancrawler.middlewares.MyDownloadMiddleware': 543,}#防止爬虫被封DOWNLOAD_DELAY = 2RANDOMIZE_DOWNLOAD_DELAY = TrueUSER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36"COOKIES_ENABLES=False运行
cd到项目主目录,执行命令
xxxxxxxxxxscrapy crawl douban_music