本篇目标:我们以爬取京东商城商品数据为例,展示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爬取京东商城商品数据的更多相关文章

  1. Scrapy实战篇(七)之Scrapy配合Selenium爬取京东商城信息(下)

    之前我们使用了selenium加Firefox作为下载中间件来实现爬取京东的商品信息.但是在大规模的爬取的时候,Firefox消耗资源比较多,因此我们希望换一种资源消耗更小的方法来爬取相关的信息. 下 ...

  2. 爬虫(十七):Scrapy框架(四) 对接selenium爬取京东商品数据

    1. Scrapy对接Selenium Scrapy抓取页面的方式和requests库类似,都是直接模拟HTTP请求,而Scrapy也不能抓取JavaScript动态谊染的页面.在前面的博客中抓取Ja ...

  3. 利用selenium爬取京东商品信息存放到mongodb

    利用selenium爬取京东商城的商品信息思路: 1.首先进入京东的搜索页面,分析搜索页面信息可以得到路由结构 2.根据页面信息可以看到京东在搜索页面使用了懒加载,所以为了解决这个问题,使用递归.等待 ...

  4. selenium模块使用详解、打码平台使用、xpath使用、使用selenium爬取京东商品信息、scrapy框架介绍与安装

    今日内容概要 selenium的使用 打码平台使用 xpath使用 爬取京东商品信息 scrapy 介绍和安装 内容详细 1.selenium模块的使用 # 之前咱们学requests,可以发送htt ...

  5. 爬虫系列(十三) 用selenium爬取京东商品

    这篇文章,我们将通过 selenium 模拟用户使用浏览器的行为,爬取京东商品信息,还是先放上最终的效果图: 1.网页分析 (1)初步分析 原本博主打算写一个能够爬取所有商品信息的爬虫,可是在分析过程 ...

  6. 利用Selenium爬取淘宝商品信息

    一.  Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样.由于这个性质,Selenium也是一 ...

  7. Scrapy实战篇(四)爬取京东商城文胸信息

    创建scrapy项目 scrapy startproject jingdong 填充 item.py文件 在这里定义想要存储的字段信息 import scrapy class JingdongItem ...

  8. Scrapy实战篇(五)爬取京东商城文胸信息

    创建scrapy项目 scrapy startproject jingdong 填充 item.py文件 在这里定义想要存储的字段信息 import scrapy class JingdongItem ...

  9. 使用Selenium爬取网站表格类数据

    本文转载自一下网站:Python爬虫(5):Selenium 爬取东方财富网股票财务报表 https://www.makcyun.top/web_scraping_withpython5.html 需 ...

随机推荐

  1. hdu4847 Wow! Such Doge! KMP

    Chen, Adrian (November 7, 2013). “Doge Is An Ac- tually Good Internet Meme. Wow.”. Gawker. Retrieved ...

  2. .closest 样例收集

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. Easyui datagrid 去掉表头的checkbox复选框

    $(".datagrid-header-check").html(""); 在onLoadSuccess中加入此行代码即可实现datagrid去除表头的chec ...

  4. 对《禁忌搜索(Tabu Search)算法及python实现》的修改

    这个算法是在听北大人工智能mooc的时候,老师讲的一种局部搜索算法,可是举得例子不太明白.搜索网页后,发现<禁忌搜索(Tabu Search)算法及python实现>(https://bl ...

  5. mysql新建用户在本地无法登录

    新建了一个mysql用户,但是无法在本地登录,即使已经授权任一ip都可以登录,甚至特地写清楚localhost登录,还是不行,情况如下 [root@localhost zabbix-release-3 ...

  6. 如何安装psutil以及提示缺少python.h头文件

    下载psutil 下载地址https://pypi.python.org/packages/57/93/47a2e3befaf194ccc3d05ffbcba2cdcdd22a231100ef7e4c ...

  7. sofa graphql 2 rest api webhook 试用

    sofa 的webhook实际上就是将graphql 的subscription 进行了扩展,当接受到sub 请求的时候 再做一次http 的转发处理,方便rest api 的访问 环境准备 环境还是 ...

  8. replicatedhq-ship 基于Kustomize 项目的快速kubernetes 应用部署工具

    replicatedhq-ship 是对Kustomize 项目的扩展,我们可以用它来快速的进行三方应用的管理部署, 可以和helm,kubernetes 清单文件,knative 集成,我们可以方便 ...

  9. 使用kubebapps 管理helm 仓库已经应用使用Monocular专门提供helm 仓库查找

    Monocular 从1.0 开始专注于helm 的UI展示,对于部署以及维护已经去掉了,官方也提供了相关的说明以及 推荐了几个可选的部署工具,从使用以及架构上来说kubeapps 就是Monocul ...

  10. C语言 二维数组(指针)动态分配和释放(转)

    C 二维数组(指针)动态分配和释放 先明确下概念: 所谓32位处理器就是一次只能处理32位,也就是4个字节的数据,而64位处理器一次就能处理64位,即8个字节的数据.如果我们将总长128位的指令分别按 ...