
使用Scrapy爬取数据的时候,可以用genspider命令通过模板快速创建,命令格式如下:
scrapy genspider -t template <name> <domain>
其中 -t template可选用以下四个默认模板:
basic 提供基础构架,继承于Spider类
crawl 提供更灵活的提取方式,继承于CrawlSpider类
csvfeed 提供提取CSV格式文件的方式,继承于CSVFeedSpider类
xmlfeed 用于提取XML文件,继承于XMLFeedSpider类
basic模板
创建命令
scrapy genspider -t basic basicCrawl www.mirthsoft.com
执行后,会自动生成下面的代码框架:
# -*- coding: utf-8 -*-
import scrapy
class BasiccrawlSpider(scrapy.Spider):
name = 'basicCrawl'
allowed_domains = ['www.mirthsoft.com']
start_urls = ['http://www.mirthsoft.com/']
def parse(self, response):
#pass
其中:
name 是爬虫的名称,使用crawl执行时用到
allowed_domains 允许爬取的域名范围
start_urls 启动链接
parse(self, response) 用于处理爬取的数据
crawl模板
创建命令
scrapy genspider -t crawl crawlCrawl www.mirthsoft.com
执行后,会自动生成下面的代码框架:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class CrawlcrawlSpider(CrawlSpider):
name = 'crawlCrawl'
allowed_domains = ['www.mirthsoft.com']
start_urls = ['http://www.mirthsoft.com/']
rules = (
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
def parse_item(self, response):
item = {}
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
这个模板生成的代码比basic模板生成的要复杂不少,其中:
rules 用于提取页面中的链接
parse_item 用于提取爬取的数据
与basic模板相比,多出来的rules,用于提取链接,例如,当有爬取的网站有文章、相册时,可以定义多个Rule:
rules = (
Rule(LinkExtractor(allow=r'article/'), callback='parse_article', follow=True),
Rule(LinkExtractor(allow=r'album/'), callback='parse_album', follow=True),
)
每个回调函数只处理一种数据,这样可以简化回调函数的复杂度。
而使用crawl模板时,不应该重写parse函数,parse对crawl模板有重要意义,它负责处理crawl的整个过程,重写后将和普通的basic无差异。
csvfeed模板
创建命令
scrapy genspider -t csvfeed csvfeedCrawl www.mirthsoft.com
执行后,会自动生成下面的代码框架:
# -*- coding: utf-8 -*-
from scrapy.spiders import CSVFeedSpider
class CsvfeedcrawlSpider(CSVFeedSpider):
name = 'csvfeedCrawl'
allowed_domains = ['www.mirthsoft.com']
start_urls = ['http://www.mirthsoft.com/feed.csv']
# headers = ['id', 'name', 'description', 'image_link']
# delimiter = '\t'
# Do any adaptations you need here
#def adapt_response(self, response):
# return response
def parse_row(self, response, row):
i = {}
#i['url'] = row['url']
#i['name'] = row['name']
#i['description'] = row['description']
return i
其中:
headers 定义csv每列的名称
delimiter 列与列的分割符
parse_row(self, response, row) 用于提取每行CSV数据
假设有下面的csv文件:
这个例子是首行为标题的,可以这样处理:
delimiter = ','#列的分割符
def parse_row(self, response, row):
i = {}
i['name'] = row['图书'] #默认为标题的内容
i['price'] = row['价格']
print(i)
运行打开的结果是:
{'name': '零基础学Python(全彩版)', 'price': '73.4'}
{'name': 'Python编程 从入门到实践', 'price': '59.7'}
{'name': '深度学习', 'price': '112.6'}
{'name': '鸟哥的Linux私房菜', 'price': '93.2'}
{'name': '深度学习的数学', 'price': '51.4'}
{'name': 'Python项目开发案例集锦', 'price': '117.8'}
{'name': '计算机网络:自顶向下方法(原书第7版)', 'price': '70.3'}
{'name': '数学之美(第二版)', 'price': '38.7'}
{'name': '计算机科学中的数学:信息与智能时代的必修课', 'price': '127.7'}
{'name': '图解机器学习', 'price': '38.6'}
如果首行不是标题的,可以这样设置:
headers = ['name', 'price'] #定义列
delimiter = ','#列的分割符
def parse_row(self, response, row):
i = {}
i['name'] = row['name'] #为headers中定义的名称
i['price'] = row['price']
print(i)
运行的结果是:
{'name': '图书', 'price': '价格'}
{'name': '零基础学Python(全彩版)', 'price': '73.4'}
{'name': 'Python编程 从入门到实践', 'price': '59.7'}
{'name': '深度学习', 'price': '112.6'}
{'name': '鸟哥的Linux私房菜', 'price': '93.2'}
{'name': '深度学习的数学', 'price': '51.4'}
{'name': 'Python项目开发案例集锦', 'price': '117.8'}
{'name': '计算机网络:自顶向下方法(原书第7版)', 'price': '70.3'}
{'name': '数学之美(第二版)', 'price': '38.7'}
{'name': '计算机科学中的数学:信息与智能时代的必修课', 'price': '127.7'}
{'name': '图解机器学习', 'price': '38.6'}
另外,在测试的时候发现,如果cvs编码不是utf-8时,中文会出现编码,暂时未找以具体的解决办法,这个以后再补充。
xmlfeed模板
创建命令
scrapy genspider -t xmlfeed xmlfeedCrawl www.mirthsoft.com
执行后,会自动生成下面的代码框架:
# -*- coding: utf-8 -*-
from scrapy.spiders import XMLFeedSpider
class XmlfeedcrawlSpider(XMLFeedSpider):
name = 'xmlfeedCrawl'
allowed_domains = ['www.mirthsoft.com']
start_urls = ['http://www.mirthsoft.com/feed.xml']
iterator = 'iternodes' # you can change this; see the docs
itertag = 'item' # change it accordingly
def parse_node(self, response, selector):
item = {}
#item['url'] = selector.select('url').get()
#item['name'] = selector.select('name').get()
#item['description'] = selector.select('description').get()
return item
其中:
iterator 是数据迭代方式,目前一共有iternodes、xml、html三种方式
itertag 是迭代标签
parse_node(self, response, selector) 每次迭代时提取函数
假设有以下的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book>
<name>零基础学Python(全彩版)</name>
<price>73.4</price>
</book>
<book>
<name>Python编程 从入门到实践</name>
<price>59.7</price>
</book>
<book>
<name>深度学习</name>
<price>112.6</price>
</book>
<book>
<name>鸟哥的Linux私房菜</name>
<price>93.2</price>
</book>
<book>
<name>深度学习的数学</name>
<price>51.4</price>
</book>
<book>
<name>Python项目开发案例集锦</name>
<price>117.8</price>
</book>
<book>
<name>计算机网络:自顶向下方法(原书第7版)</name>
<price>70.3</price>
</book>
<book>
<name>数学之美(第二版)</name>
<price>38.7</price>
</book>
<book>
<name>计算机科学中的数学:信息与智能时代的必修课</name>
<price>127.7</price>
</book>
<book>
<name>图解机器学习</name>
<price>38.6</price>
</book>
</books>
可以如下配置:
iterator = 'iternodes' # you can change this; see the docs
itertag = 'book' # change it accordingly
def parse_node(self, response, selector):
item = {}
item['name'] = selector.xpath('./name/text()').get()
item['price'] = selector.xpath('./price/text()').get()
print(item)
#return item
执行后,输出结果:
{'name': '零基础学Python(全彩版)', 'price': '73.4'}
{'name': 'Python编程 从入门到实践', 'price': '59.7'}
{'name': '深度学习', 'price': '112.6'}
{'name': '鸟哥的Linux私房菜', 'price': '93.2'}
{'name': '深度学习的数学', 'price': '51.4'}
{'name': 'Python项目开发案例集锦', 'price': '117.8'}
{'name': '计算机网络:自顶向下方法(原书第7版)', 'price': '70.3'}
{'name': '数学之美(第二版)', 'price': '38.7'}
{'name': '计算机科学中的数学:信息与智能时代的必修课', 'price': '127.7'}
{'name': '图解机器学习', 'price': '38.6'}
其它爬虫基类
除了genspider命令自带的四个模板外,scrapy还提供了其它爬虫基类,有兴趣的可以深入了解下:
SitemapSpider 用于爬取网站地图的基类
InitSpider 带有初始化器的基类