Scrapy实战篇(八)之Scrapy对接selenium爬取京东商城商品数据
本篇目标:我们以爬取京东商城商品数据为例,展示Scrapy框架对接selenium爬取京东商城商品数据。
背景:
京东商城页面为js动态加载页面,直接使用request请求,无法得到我们想要的商品数据,故需要借助于selenium模拟人的行为发起请求,输出源代码,然后解析源代码,得到我们想要的数据。
第一步:设置我们需要提取的字段,也就是在Scrapy框架中设置Item.py文件。
class ProductItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
dp = Field()
title = Field()
price = Field()
comment=Field()
url=Field()
type=Field()
这里我们需提取上面几个字段,依次为店铺名称,商品名称,商品价格,评论数,商品url,类型(区分是什么类型的商品) 第二步:
设置我们需要从哪个页面开始爬起,也就是开发scrapy框架中的spider文件,代码如下
class JingdongSpider(scrapy.Spider):
name = 'jingdong'
allowed_domains = ['www.jingdong.com']
base_url = 'https://search.jd.com/Search?keyword=' def start_requests(self):
for keyword in self.settings.get('KEYWORDS'):
for page in range(1,self.settings.get('MAX_PAGE') + 1):
url = self.base_url + quote(keyword)
#dont_filter = True 不去重
yield Request(url = url ,callback = self.parse,meta = {'page':page},dont_filter=True)
我们设置初始url为京东商城搜索商品的页面链接,其中搜索的商品用KEYWORDS表示,在settings文件中以列表的形式设置,因为搜索出来的页数可能很多,所有我们需要爬取的页数页用MAX_PAGE变量
在settings文件中设置。
KEYWORDS=['iPad']
MAX_PAGE=2
如果此时运行项目,链接会直接发送给下载器进行下载,无法得到我们想要的数据,所以我们在下载器中间件中对该请求进行处理。 第三步:
在下载器中间件中对接selenium,直接输出源代码并返回,不在下载器中下载页面。
class SeleniumMiddleware(object):
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the downloader middleware does not modify the
# passed objects. def __init__(self,timeout=None):
self.logger=getLogger(__name__)
self.timeout = timeout
self.browser = webdriver.Chrome()
self.browser.set_window_size(1400,700)
self.browser.set_page_load_timeout(self.timeout)
self.wait = WebDriverWait(self.browser,self.timeout) def __del__(self):
self.browser.close() @classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
return cls(timeout=crawler.settings.get('SELENIUM_TIMEOUT')) def process_request(self, request, spider):
'''
在下载器中间件中对接使用selenium,输出源代码之后,构造htmlresponse对象,直接返回
给spider解析页面,提取数据
并且也不在执行下载器下载页面动作
htmlresponse对象的文档:
:param request:
:param spider:
:return:
''' print('Chorme is Starting')
page = request.meta.get('page', 1)
self.wait = WebDriverWait(self.browser, self.timeout)
try:
self.browser.get(request.url)
if page > 1:
input = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > input')))
input.clear()
input.send_keys(page)
time.sleep(5) # 将网页中输入跳转页的输入框赋值给input变量 EC.presence_of_element_located,判断输入框已经被加载出来
input = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > input')))
# 将网页中调准页面的确定按钮赋值给submit变量,EC.element_to_be_clickable 判断此按钮是可点击的
submit = self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > a')))
input.clear()
input.send_keys(page)
submit.click() # 点击按钮
time.sleep(5) # 判断当前页码出现在了输入的页面中,EC.text_to_be_present_in_element 判断元素在指定字符串中出现
self.wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.curr'),str(page)))
# 等待 #J_goodsList 加载出来,为页面数据,加载出来之后,在返回网页源代码
self.wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.curr'),str(page)))
return HtmlResponse(url=request.url, body=self.browser.page_source, request=request, encoding='utf-8',status=200)
except TimeoutException:
return HtmlResponse(url=request.url, status=500, request=request)
__init__和类函数都执行一些初始化操作,无需多说,我们主要看process_request()方法
首先我们这是浏览器的等待时长,然后我们见输入页码的输入框赋值给input变量,在将翻页的点击按钮框赋值给submit变量,然后在数据框中输入页码,等待页面加载,直接返回
htmlresponse给spider解析,这里我们没有经过下载器下载,直接构造response的子类htmlresponse返回。(当下载器中间件返回response对象时,更低优先级的process_request将不在执行,转而
执行其他的process_response()方法,本例中没有其他的process_response(),所以直接将结果返回给spider解析。) 第四步:
开发第二步中Request对象中的回调函数,解析页面数据,提取我们想要的数据。这里我们采用BeautifulSoup进行解析,代码如下:
def parse(self, response):
soup = BeautifulSoup(response.text, 'lxml')
lis = soup.find_all(name='li', class_="gl-item")
for li in lis:
proc_dict = {}
dp = li.find(name='span', class_="J_im_icon")
if dp:
proc_dict['dp'] = dp.get_text().strip()
else:
continue
id = li.attrs['data-sku']
title = li.find(name='div', class_="p-name p-name-type-2")
proc_dict['title'] = title.get_text().strip()
price = li.find(name='strong', class_="J_" + id)
proc_dict['price'] = price.get_text()
comment = li.find(name='a', id="J_comment_" + id)
proc_dict['comment'] = comment.get_text() + '条评论'
url = 'https://item.jd.com/' + id + '.html'
proc_dict['url'] = url
proc_dict['type'] = 'JINGDONG'
yield proc_dict
第五步:
提取完页面数据之后,数据会发送到item pipeline处进行数据处理,清洗,入库等操作,所以我们此时当然需要定义项目管道了,在此我们将数据存储在mongodb数据库中。
class MongoPipeline(object): def __init__(self,mongo_url,mongo_db,collection):
self.mongo_url = mongo_url
self.mongo_db = mongo_db
self.collection = collection @classmethod
def from_crawler(cls,crawler):
return cls(
mongo_url=crawler.settings.get('MONGO_URL'),
mongo_db = crawler.settings.get('MONGO_DB'),
collection = crawler.settings.get('COLLECTION')
) def open_spider(self,spider):
self.client = pymongo.MongoClient(self.mongo_url)
self.db = self.client[self.mongo_db] def process_item(self,item, spider):
# name = item.__class__.collection
name = self.collection
self.db[name].insert(dict(item))
return item def close_spider(self,spider):
self.client.close()
我们使用类方法from_crawler从settings文件中获取mongodb数据库的配置信息,在__init__中进行初始化,在process_item中将数据存储到mongodb中。 第六步
1、配置settings文件,将项目中使用到的配置项在settings文件中配置,本项目中使用到了KEYWORDS,MAX_PAGE,SELENIUM_TIMEOUT(页面加载超时时间),MONGOURL,MONGODB,COLLECTION;
2、修改配置项,激活下载器中间件和item pipeline。
DOWNLOADER_MIDDLEWARES = {
'scrapyseleniumtest.middlewares.SeleniumMiddleware': 543,
} ITEM_PIPELINES = {
'scrapyseleniumtest.pipelines.MongoPipeline': 300,
}
至此,项目中所有需要开发的代码和配置项开发完成,运行项目之后,在mongodb中查看数据,应该已经执行成功。
本项目完整代码:
https://gitee.com/liangxinbin/Scrpay/tree/master/scrapyseleniumtest
Scrapy实战篇(八)之Scrapy对接selenium爬取京东商城商品数据的更多相关文章
- Scrapy实战篇(七)之Scrapy配合Selenium爬取京东商城信息(下)
之前我们使用了selenium加Firefox作为下载中间件来实现爬取京东的商品信息.但是在大规模的爬取的时候,Firefox消耗资源比较多,因此我们希望换一种资源消耗更小的方法来爬取相关的信息. 下 ...
- 爬虫(十七):Scrapy框架(四) 对接selenium爬取京东商品数据
1. Scrapy对接Selenium Scrapy抓取页面的方式和requests库类似,都是直接模拟HTTP请求,而Scrapy也不能抓取JavaScript动态谊染的页面.在前面的博客中抓取Ja ...
- 利用selenium爬取京东商品信息存放到mongodb
利用selenium爬取京东商城的商品信息思路: 1.首先进入京东的搜索页面,分析搜索页面信息可以得到路由结构 2.根据页面信息可以看到京东在搜索页面使用了懒加载,所以为了解决这个问题,使用递归.等待 ...
- selenium模块使用详解、打码平台使用、xpath使用、使用selenium爬取京东商品信息、scrapy框架介绍与安装
今日内容概要 selenium的使用 打码平台使用 xpath使用 爬取京东商品信息 scrapy 介绍和安装 内容详细 1.selenium模块的使用 # 之前咱们学requests,可以发送htt ...
- 爬虫系列(十三) 用selenium爬取京东商品
这篇文章,我们将通过 selenium 模拟用户使用浏览器的行为,爬取京东商品信息,还是先放上最终的效果图: 1.网页分析 (1)初步分析 原本博主打算写一个能够爬取所有商品信息的爬虫,可是在分析过程 ...
- 利用Selenium爬取淘宝商品信息
一. Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样.由于这个性质,Selenium也是一 ...
- Scrapy实战篇(四)爬取京东商城文胸信息
创建scrapy项目 scrapy startproject jingdong 填充 item.py文件 在这里定义想要存储的字段信息 import scrapy class JingdongItem ...
- Scrapy实战篇(五)爬取京东商城文胸信息
创建scrapy项目 scrapy startproject jingdong 填充 item.py文件 在这里定义想要存储的字段信息 import scrapy class JingdongItem ...
- 使用Selenium爬取网站表格类数据
本文转载自一下网站:Python爬虫(5):Selenium 爬取东方财富网股票财务报表 https://www.makcyun.top/web_scraping_withpython5.html 需 ...
随机推荐
- hdu3746 Cyclic Nacklace KMP
CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, ...
- 使用fastjson解析数据后导致顺序改变问题
在开发过程中遇到一个问题,服务器经过排序返回后的字符串数据使用fastjson解析后,数据顺序发生变化,引起业务异常. 解决办法: 1.解析时增加参数不调整顺序 JSONObject responde ...
- XML之命名空间的作用(xmlns)
http://www.w3school.com.cn/xml/xml_namespaces.asp http://blog.csdn.net/zhch152/article/details/81913 ...
- string的方法find
官方解释:find(sub[, start[, end]]) Return the lowest index in the string where substring sub is found wi ...
- 【shell编程】之基础知识-文件包含
和其他语言一样,Shell 也可以包含外部脚本.这样可以很方便的封装一些公用的代码作为一个独立的文件. Shell 文件包含的语法格式如下: . filename # 注意点号(.)和文件名中间有一空 ...
- 找工作String类(重点,背诵)(本质是一个类)
一个顶层设计者眼中只有2个东西接口,类(属性,方法) 无论String 类 , HashMap实现类 , Map接口 String str = "Hello" ; // 定义 ...
- Hi3516CV300 sample -> region
- async await 的 实质 本质
async await 的 实质 就是 用 “状态机” 来 取代 函数层层调用 . async await 的 本质 是 语法糖, 和 提高性能 什么的 没什么关系 . 为了避免理解歧义, 我把 ...
- 论 大并发 下的 乐观锁定 Redis锁定 和 新时代事务
在 <企业应用架构模式> 中 提到了 乐观锁定, 用 时间戳 来 判定 交易 是否有效, 避免 传统事务 的 表锁定 造成 的 瓶颈 . 在 现在的 大并发 的 大环境下, 传统事务 及其 ...
- mongodb之 oplog 日志详解
1:oplog简介 oplog是local库下的一个固定集合,Secondary就是通过查看Primary 的oplog这个集合来进行复制的.每个节点都有oplog,记录这从主节点复制过来的信息,这样 ...