一、scrapy_redis案例之爬取 当当网
整体思路:先实现普通的scrapy爬虫,然后在改写成scrapy_redis
普通的scrapy爬虫:
(一)需求:获取图书分类中所有图书的书名和封面,如下图:
也就是说先得到小分类中的链接,点击(请求)进入之后,再获取每本书的书名和封面(链接)
(二)页面分析:
1、右键查看网页源代码,发现数据就在源代码中,不是js。
(三)爬虫文件的实现:
1、新建爬虫项目:(在桌面,新建一个dangd的爬虫文件夹)
2、点击进入爬虫文件夹,打开爬虫文件:
3、将逻辑代码写入该文件:
逻辑:大分类 二级分类 三级分类 图书的名字和图片的src
# -*- coding: utf-8 -*-
import scrapy
class DangdangSpider(scrapy.Spider):
name = 'dangdang'
allowed_domains = ['dangdang.com']
start_urls = ['http://book.dangdang.com/'] #将['http://dangdang.com/']修改
def parse(self, response):
div_list = response.xpath('//div[@class="con flq_body"]/div')
for div in div_list:
item = {}
# 获取大分类
item['b_cate'] = div.xpath('./dl/dt//text()').extract()
item['b_cate'] = [i.strip() for i in item['b_cate'] if len(i.strip())>0]
dl_list = div.xpath('.//dl[@class="inner_dl"]')
for dl in dl_list:
# 获取中分类
item['m_cate'] = dl.xpath('./dt//text()').extract()
item['m_cate'] = [i.strip() for i in item['m_cate'] if len(i.strip()) > 0]
# 获取小分类
a_list = dl.xpath('./dd/a')
for a in a_list:
item['s_cate'] = a.xpath('./text()').extract_first()
item['s_href'] = a.xpath('./@href').extract_first()
print(item)
注意:
大分类
整个大分类都在 div con flq_body 它下面的 div/dl/dt
(1)在大分类中有一个span标签,
但是源码中没有,
如果写成:
item[‘b_cate’] = div.xpath(’./dl/dt/span/text()’).extract(),反而是空。所以就不要span。
(2) 有的大分类在dt标签下面还有一个a标签,所以用双斜杠//, /dt//text().extract()
补充:单斜杠/和双斜杠//的区别:
二级分类
div level one --> dl class=“inner_dl” dt/text()
(1)有的大分类在dt标签下面还有一个a标签 /dt//text().extract()
三级分类
dl class=“inner_dl” --> dd/a/text()
(1)右键检查,定位到的src,以获取封面图片;与右键网页源代码中的src,不一致的问题。(后面有详细说明)
4、settings文件的准备:
LOG_LEVEL = 'WARNING'
ROBOTSTXT_OBEY = False
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
5、在cmd中进入到爬虫文件夹后,运行爬虫文件:scrapy crawl 爬虫文件名
结果:
由此就得到了小分类中的链接,接下来就是要请求这些链接,并获取每本书的书名和封面(链接)
6、请求和解析
# -*- coding: utf-8 -*-
import scrapy
from copy import deepcopy
class DangdangSpider(scrapy.Spider):
name = 'dangdang'
allowed_domains = ['dangdang.com']
start_urls = ['http://book.dangdang.com/'] #将['http://dangdang.com/']修改
def parse(self, response):
div_list = response.xpath('//div[@class="con flq_body"]/div')
for div in div_list:
item = {}
# 获取大分类
item['b_cate'] = div.xpath('./dl/dt//text()').extract()
item['b_cate'] = [i.strip() for i in item['b_cate'] if len(i.strip())>0]
dl_list = div.xpath('.//dl[@class="inner_dl"]')
for dl in dl_list:
# 获取中分类
item['m_cate'] = dl.xpath('./dt//text()').extract()
item['m_cate'] = [i.strip() for i in item['m_cate'] if len(i.strip()) > 0]
# 获取小分类
a_list = dl.xpath('./dd/a')
for a in a_list:
item['s_cate'] = a.xpath('./text()').extract_first()
item['s_href'] = a.xpath('./@href').extract_first()
if item['s_href'] is not None:
yield scrapy.Request(
url=item['s_href'],
callback=self.parse_book_list,
meta={'item':deepcopy(item)}
)
#print(item) #这里的打印item,结果不包含书名和封面
def parse_book_list(self,response):
item = response.meta.get('item')
li_list = response.xpath('//ul[@class="list_aa "]/li')
for li in li_list:
# 图片的url
item['book_img'] = li.xpath('./a[@class="img"]/img/@data-original').extract_first()
# 数据的名字
item['book_name'] = li.xpath('./p[@class="name"]//text()').extract_first()
print(item) #这里的打印item,结果包含书名和封面
注意:在获取封面的时候,本身应该是定位到src属性值:
item['book_img'] = li.xpath('./a[@class="img"]/img/@src').extract_first()
但,得到的所有结果都是: images/model/guan/url_none.png,因为在网页源代码中,src都是一样的,
同时,我们发现data-original属性值,就是封面,所以就改为获取该属性。
结果:
如果需要保存,则相应在管道文件中编写。
补充:赋值号、复制和深复制
赋值号:
复制:
深复制:(下图和上图对比,并看不出来复制和深复制的不一样)
那么如何看出两者的不同?如下: