scrapy爬虫--苏宁图书
实现业务逻辑如下:
1. 创建scrapy项目,并生成 爬虫
2. 在suning.py中实现Schedul 和 Spider业务逻辑
3. 修改start_urls为正确的初始请求地址
4. 构造parse(self,response)函数(底部封装自动发送请求,)获取响应
5. 根据响应,使用xpath提取大分类和中间分类的list
6. 根据上述得到的list再遍历,使用xpath提取我们需要的内容字段,存入刚构建的空dict中
7. 如果要进入到下一个商品列表页面,则 yield 一个Requset对象,指明要进入的url,callback,以及把item通过meta传到列表页响应中。
8. 构建callback对应的商品列表页面数据提取函数 parse_book_list(self,response),使用xpath提取我们需要的内容字段,使用yield response.yellow()构造请求,指明要进入的url(使用的是follow,所以可以是不完整的url),callback,以及把item通过meta传到详情页响应中。
9. 构建callback对应的商品详情页面数据提取函数 parse_book_detail(self,response),使用xpath提取我们需要的内容字段,字段提取完成后,就可以把item返回了,yield item。
10. 构建分类页中的后一部分图书列表数据请求,首先找到next_url,然后构造Request。
11. 上述最终yield 的item 通过在settings中设置spiderpiplelines,就会进入指定的spiderpiplelines中通过process_item()进行进一步数据处理,比如清洗和保存。
12. 另外在Downloader Middlewares中还可以设置open_spider(),close_spider(),做相应处理。
# 注意点,scrapy框架底层实现了多线程,所以item传递时,为避免数据覆盖错位情况,需要使用deepcopy()传递下去。
下面直接上代码:
# suning.py
# -*- coding: utf-8 -*-
import scrapy
import re
from copy import deepcopy class SuningSpider(scrapy.Spider):
name = 'suning'
allowed_domains = ['suning.com']
start_urls = ['https://book.suning.com/'] def parse(self, response):
#获取大分类的分组
div_list = response.xpath("//div[@class='menu-list']/div[@class='menu-item']")
# 和大分类呼应的中间分类组
div_sub_list = response.xpath("//div[@class='menu-list']/div[@class='menu-sub']")
for div in div_list[:1]:
item = {}
#大分类的名字--eg:文学艺术
item["b_cate"] = div.xpath(".//h3/a/text()").extract_first()
#当前大分类的所有的中间分类的位置
current_sub_div = div_sub_list[div_list.index(div)]
#获取中间分类的分组--eg: 小说,青春文学
p_list = current_sub_div.xpath(".//div[@class='submenu-left']/p[@class='submenu-item']")
for p in p_list:
#中间分类的名字
item["m_cate"] = p.xpath("./a/text()").extract_first()
#获取小分类的分组
li_list = p.xpath("./following-sibling::ul[1]/li")
for li in li_list:
#小分类的名字
item["s_cate"] = li.xpath("./a/text()").extract_first()
#小分类的URL地址
item["s_href"] = li.xpath("./a/@href").extract_first() #请求图书的列表页
yield scrapy.Request(
item["s_href"],
callback=self.parse_book_list,
meta={"item":deepcopy(item)}
) #发送请求,获取列表页第一页后一部分的数据
next_part_url_temp = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp=0&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010&paging=1&sub=0"
#获取url地址的ci
ci = item["s_href"].split("-")[1]
next_part_url = next_part_url_temp.format(ci)
yield scrapy.Request(
next_part_url,
callback=self.parse_book_list,
meta={"item":deepcopy(item)}
) def parse_book_list(self,response): #处理图书列表页内容
item = response.meta["item"]
#获取图书列表页的分组
# li_list = response.xpath("//div[@id='filter-results']/ul/li")
li_list =response.xpath("//li[contains(@class,'product book')]")
for li in li_list[:1]:
#书名
item["book_name"] = li.xpath(".//p[@class='sell-point']/a/text()").extract_first().strip()
#书的url地址,不完整
item["book_href"] = li.xpath(".//p[@class='sell-point']/a/@href").extract_first()
#书店名
item["book_store_name"] = li.xpath(".//p[contains(@class,'seller oh no-more')]/a/text()").extract_first()
#发送详情页的请求
yield response.follow(
item["book_href"],
callback = self.parse_book_detail,
meta = {"item":deepcopy(item)}
) #列表页翻页
#前半部分数据的url地址
next_url_1 = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp={}&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010"
#后半部分数据的url地址
next_url_2 = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp={}&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010&paging=1&sub=0"
ci = item["s_href"].split("-")[1]
#当前的页码数
current_page = re.findall('param.currentPage = "(.*?)";',response.body.decode())[0]
#总的页码数
total_page = re.findall('param.pageNumbers = "(.*?)";',response.body.decode())[0]
if int(current_page)<int(total_page):
next_page_num = int(current_page) + 1
next_url_1 = next_url_1.format(ci,next_page_num) #组装前半部分URL
yield scrapy.Request(
next_url_1,
callback=self.parse_book_list,
meta = {"item":item}
)
#构造后半部分数据的请求
next_url_2 = next_url_2.format(ci,next_page_num)
yield scrapy.Request(
next_url_2,
callback=self.parse_book_list,
meta = {"item":item}
) def parse_book_detail(self,response):#处理图书详情页内容
item = response.meta["item"]
price_temp_url = "https://pas.suning.com/nspcsale_0_000000000{}_000000000{}_{}_10_010_0100101_226503_1000000_9017_10106____{}_{}.html"
p1 = response.url.split("/")[-1].split(".")[0]
p3 = response.url.split("/")[-2]
p4 = re.findall('"catenIds":"(.*?)",',response.body.decode())
if len(p4)>0:
p4 = p4[0]
p5 = re.findall('"weight":"(.*?)",',response.body.decode())[0]
price_url = price_temp_url.format(p1,p1,p3,p4,p5)
yield scrapy.Request(
price_url,
callback=self.parse_book_pirce,
meta={"item":item}
) def parse_book_pirce(self,response): #提取图书的价格
item = response.meta["item"]
# item["book_price"] = re.findall('"netPrice":"(.*?)"',response.body.decode())[0]
# print(item)
yield item
关于setting.py & pipeline.py & middlewares.py的代码比较简单,这里就不传了。
scrapy爬虫--苏宁图书的更多相关文章
- Scrapy项目_苏宁图书信息
苏宁图书(https://book.suning.com/) 目标: 1.图书一级分类 2.图书二级分类 3.图书三级分类 4.图书名字 5.图书作者 6.图书价格 7.通过Scrapy获取以上数据 ...
- scrapy爬虫结果插入mysql数据库
1.通过工具创建数据库scrapy
- Python之Scrapy爬虫框架安装及简单使用
题记:早已听闻python爬虫框架的大名.近些天学习了下其中的Scrapy爬虫框架,将自己理解的跟大家分享.有表述不当之处,望大神们斧正. 一.初窥Scrapy Scrapy是一个为了爬取网站数据,提 ...
- Linux搭建Scrapy爬虫集成开发环境
安装Python 下载地址:http://www.python.org/, Python 有 Python 2 和 Python 3 两个版本, 语法有些区别,ubuntu上自带了python2.7. ...
- Scrapy 爬虫
Scrapy 爬虫 使用指南 完全教程 scrapy note command 全局命令: startproject :在 project_name 文件夹下创建一个名为 project_name ...
- [Python爬虫] scrapy爬虫系列 <一>.安装及入门介绍
前面介绍了很多Selenium基于自动测试的Python爬虫程序,主要利用它的xpath语句,通过分析网页DOM树结构进行爬取内容,同时可以结合Phantomjs模拟浏览器进行鼠标或键盘操作.但是,更 ...
- 同时运行多个scrapy爬虫的几种方法(自定义scrapy项目命令)
试想一下,前面做的实验和例子都只有一个spider.然而,现实的开发的爬虫肯定不止一个.既然这样,那么就会有如下几个问题:1.在同一个项目中怎么创建多个爬虫的呢?2.多个爬虫的时候是怎么将他们运行起来 ...
- 如何让你的scrapy爬虫不再被ban之二(利用第三方平台crawlera做scrapy爬虫防屏蔽)
我们在做scrapy爬虫的时候,爬虫经常被ban是常态.然而前面的文章如何让你的scrapy爬虫不再被ban,介绍了scrapy爬虫防屏蔽的各种策略组合.前面采用的是禁用cookies.动态设置use ...
- 如何让你的scrapy爬虫不再被ban
前面用scrapy编写爬虫抓取了自己博客的内容并保存成json格式的数据(scrapy爬虫成长日记之创建工程-抽取数据-保存为json格式的数据)和写入数据库(scrapy爬虫成长日记之将抓取内容写入 ...
- scrapy爬虫成长日记之将抓取内容写入mysql数据库
前面小试了一下scrapy抓取博客园的博客(您可在此查看scrapy爬虫成长日记之创建工程-抽取数据-保存为json格式的数据),但是前面抓取的数据时保存为json格式的文本文件中的.这很显然不满足我 ...
随机推荐
- 微信小程序记账本进度六
//app.jsApp({ onLaunch: function () { //调用API从本地缓存中获取数据 var logs = wx.getStorageSync('logs') || [] l ...
- 设计模式之模板模式 template
设计模式 模板模式如果有一个流程如下step1();step2();step3();step4();step5();其中step3() step5()是需要用户自己编写使用其他步骤是固定的那么可以写成 ...
- asp.net core2.0中网站发布的时候,怎么样才配置才可以使视图文件不被打包进去?
默认设置可真是坑~~ https://q.cnblogs.com/q/99680/
- Zookeeper系列2 原生API 以及核心特性watcher
原生API 增删改查询 public class ZkBaseTest { static final String CONNECT_ADDR = "192.168.0.120"; ...
- SQL学习(一.索引)
数据库索引 作用: 提高查询速度 确保数据的唯一性 可以加速表和表之间的连接,实现表和表之间的参照完整性 使用分组和排序子句进行数据检索时,可以减少分组和排序的时间 全文检索字段进行搜素优化 分类: ...
- tf-slim-mnist
谷歌开放TF-Slim:在TensorFlow中定义复杂模型的高层库 使用 TF-Slim 的 GitHbu 代码: README:https://github.com/tensorflow/mode ...
- git stash错误小记
git出错小记 想要push代码,我们经常这样做. 1.查看状态 git status 2.隐藏本地编辑的新内容 git stash 3.拉远程的代码 git pull 这一步操作有的时候会报错,没有 ...
- 20175316盛茂淞 2018-2019-2 《Java程序设计》第2周学习总结
20175316盛茂淞 2018-2019-2 <Java程序设计>第2周学习总结 教材学习内容总结 1.整数:可细分为为short整数(占2字节),int整数(占4字节),long整数( ...
- MYSQL性能查看(多指标)
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...
- 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)
传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...