首先查看以下当当网的页面结构,可以看到的是图书的大小分类都在class="con flq_body"的div中。记得要看看页面源代码中是否有这些数据噢
然后可以看到所有小分类的链接都在class="inner dl"的dl标签中,所以使用link_extractor可以直接提取,再到详情页面获取大小分类。
然后将下一页的链接也提取出来,这样就可以获取到所有的数据咯
具体分析已经做完就可以开始敲代码,首先开始写一个crawlspider文件。可以自己写import,如果嫌麻烦可以直接使用cmd创建
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider
class SpiderSpider(CrawlSpider):
name = 'dd_book'
allowed_domains = ['dangdang.com']
# redis_key = 'dangdang'
start_urls = ['http://book.dangdang.com/']
rules = (
# 直接提取小分类的页面的链接并请求页面
Rule(LinkExtractor(restrict_xpaths='//dl[@class="inner_dl"]/dd/a'), callback='parse_data',follow=True),
# 提取下一页的链接并请求 因为scrapy的请求是放在调度器中
Rule(LinkExtractor(restrict_xpaths='//ul[@name="Fy"]/li/a'), callback='parse_data')
)
def parse_data(self, response):
print(response)
以下为打印的response结果:
同时记住不要忘记提取他的分类噢
可以看到已经请求到这些图书的链接。然后再开始获取这些页面的图书信息,可以看到这些图书都在class="bigimg"的ul标签下的li标签里,只需要提取到ul标签下的所有的li标签,遍历之后再提取就好了
提取图书信息的代码如下:
def parse_data(self, response):
item = {}
# 获取分类信息
item['big_sort'] = response.xpath('//div[@class="crumbs_fb_left"]/div[1]/a/text()').extract_first()
item['small_sort'] = response.xpath('//div[@class="crumbs_fb_left"]/div[2]/a/text()').extract_first()
# 因为当当有些图书页面结构不一样,所以的话会查询不到,需要加一个判断
if item['big_sort']:
# 获取该页面下所有的包含图书信息的li标签
lis = response.xpath('//ul[@class="bigimg"]/li')
# 遍历提取需要的信息
for li in lis:
item['book_name'] = li.xpath('./a/@title').extract_first()
item['price_now'] = li.xpath('./p[@class="price"]/span[@class="search_now_price"]/text()').extract_first()
item['price_pre'] = li.xpath('./p[@class="price"]/span[@class="search_pre_price"]/text()').extract_first()
item['book_shop'] = li.xpath('./p[@class="search_shangjia"]/a/text()').extract_first()
# print(item)
yield item
运行结果如下,可以看到所有需要的信息都被提取到了,他的价格竟然可以直接获取,哈哈,也是很容易就获取到了呢,就是他有的图书页面的结构是不一样的,所以需要加一个判断,不一样的结构页面我就不爬咯
然后再settings文件中添加以下配置
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True # 为false Redis关闭了 Redis数据也会被清空
REDIS_URL = "redis://127.0.0.1:6379"
修改spider文件,让他继承RedisCrawlSpider,然后不需要start_urls,这个需要我们使用redis客户端手动压入,对了别忘记开启redis服务端噢,现在就实现了分布式爬虫,关闭爬虫之后,下次再开始就不会继续爬取上次已经爬过的内容
from scrapy_redis.spiders import RedisCrawlSpider
from copy import deepcopy
class SpiderSpider(RedisCrawlSpider):
name = 'dd_book'
allowed_domains = ['dangdang.com']
redis_key = 'dangdang'
# start_urls = ['http://book.dangdang.com/']
到现在就可以使用pipeline直接保存爬取到的信息咯,再配置项中开启pipeline,我选择保存在MongoDB,因为MongoDB比较适合保存字典类型的文件,pipeline文件如下,MongoDB使用的时候也不能忘记开启服务端哟
from pymongo import MongoClient
class DangdangPipeline(object):
def __init__(self):
self.mongo_cli = MongoClient(host='localhost', port=27017)
self.db = self.mongo_cli['dang_dang_book']
def process_item(self, item, spider):
self.db.dang_dang_book.insert_one(item)
print(item, '已保存')
return item
最终保存结果如下,大概不到3分钟获取了1万多条数据,settings中还设置了delay为3秒,速度还是挺快的: