项目需求
爬取网站http://books.toscrape.com
需要得到如下信息:
- 书名
- 价格
- 评价等级
- 产品编码
- 库存量
- 评价等级
页面分析
分析第一本书的页面,运行scrapy shell
命令,如下图所示
结果如下:
在scrapy shell
中调用view
函数,该函数用于在浏览器中显示 response
所包含的界面:
结果如下:
然后去提取书名等信息:
通过调用fetch
函数下载第一个书籍列表界面:
通过使用LinkExtractor
提取每个书籍页面的链接:
编码实现
首先创建一个Scrapy
项目,叫做toscrape_book
,在命令提示符窗口输入
scrapy startproject toscrapy_book
用PyCharm
打开,则该项目主要结构如下图:
在toscrape_book/spiders
中创建books.py
,在其中创建一个BookSpider
类,接下来,按以下五步完成BookSpider
:
- 继承
Spider
创建BookSpider
类 - 为
Spider
取名 - 指定起始爬取点
- 实现书籍列表页面的解析函数
- 实现书籍页面的解析函数
先定义封装书籍信息的Item
类,在items.py
中添加如下代码:
class BookItem(scrapy.Item):
name = scrapy.Field() #书名
price = scrapy.Field() #价格
review_rating = scrapy.Field() #评价等级1~5星
review_num = scrapy.Field() #评价数量
upc = scrapy.Field() #产品编码
stock = scrapy.Field() #库存量
在BookSpider
类中写入如下代码:
class BookSpider(scrapy.Spider):
name = 'books'
allowed_domains = ['books.toscrape.com']
start_urls = ['http://books.toscrape.com/']
#书籍列表页面的解析函数
def parse(self, response):
#提取书籍列表页面中每本书的链接
le = LinkExtractor(restrict_css='article.product_pod h3')
for link in le.extract_links(response):
yield scrapy.Request(link.url,callback=self.parse_book)
#提取“下一页”的链接
le = LinkExtractor(restrict_css='ul.pager li.next')
links = le.extract_links(response)
if links:
next_url = links[0].url
yield scrapy.Request(next_url,callback=self.parse)
#书籍页面的解析函数
def parse_book(self,response):
book = BookItem()
sel = response.css('div.product_main')
book['name'] = sel.xpath('./h1/text()').extract_first()
book['price'] = sel.css('p.price_color::text').extract_first()
book['review_rating'] = sel.css('p.star-rating::attr(class)').re_first('star-rating ([A-Za-z]+)')
sel = response.css('table.table.table-striped')
book['upc'] = sel.xpath('(.//tr)[1]/td/text()').extract_first()
book['stock'] = sel.xpath('(.//tr)[last()-1]/td/text()').re_first('\((\d+) available\)')
book['review_num'] = sel.xpath('(.//tr)[last()]/td/text()').extract_first()
yield book
在配置文件settings.py
中使用FEED_EXPORT_FIELDS
指定各列的顺序:
FEED_EXPORT_FIELDS=['upc','name','price','stock','review_rating','review_num']
结果中评价等级字段的值是One,Two,Three…这样的单词,阅读起来不方便,现在实现一个Item Pipeline,将评价等级字段映射到数字,接下来在pipelines.py
中实现BookPipeline
,代码如下:
class BookPipeline(object):
review_rating_map={
'One': 1,
'Two': 2,
'Three': 3,
'Four': 4,
'Five': 5,
}
def process_item(self,item,spider):
rating = item.get('review_rating')
if rating:
item['review_rating'] = self.review_rating_map[rating]
return item
在配置文件settings.py
中启用BookPipeline
:
ITEM_PIPELINES = {
'toscrape_book.pipelines.BookPipeline': 300,
}
在与settings.py
同一级目录下创建文件main.py
,写入如下语句:
from scrapy import cmdline
cmdline.execute(['scrapy','crawl','books','-o','books.csv'])
运行爬虫,在Terminal
中输入语句scrapy crawl books -o books.csv
,最终会生成一个books.csv
文件,则结果如下图所示: