1 创建一个srcapy项目:
(项目名为:jingdong),会生成一系列文件夹,命令如下(cmd下运行):
scrapy startproject jingdong
2 创建爬虫文件
在刚刚生成的jingdong文件夹下面找到spiders文件夹,在spider文件下创建一个爬虫文件(名字叫jd)– 用来解析网页的,命令如下(cmd下运行):
"list.jd.com"
scarpy genspider jd # 创建一个jd.py的爬虫文件,爬虫名为jd ,以及指定爬虫允许爬取的范围:只能在jd.com下.
3 编写items.py文件
创建爬虫目标(明确需要提取的数据),如下:
import scrapy
class JingdongItem(scrapy.Item):
# define the fields for your item here like:
# 所有商品的名称、链接、价格、销售店铺、评论数的信
# 商品名称
= scrapy.Field()
name # 商品的简介
= scrapy.Field()
abstract # 商品的链接
= scrapy.Field()
link # 商品的价格
= scrapy.Field()
price # 店铺名
= scrapy.Field()
shop_name # 评论数
= scrapy.Field() commet
4 设置setting文件,开启管道
= {
ITEM_PIPELINES 'jingdong.pipelines.JingdongPipeline': 300,
}
5 编写spiders/jd.py 文件 (爬虫文件)
编写爬虫文件(我们创建的jd.py,,在spiders这个文件夹下面),此文件用来处理请求和响应,以及提取数据
# -*- coding: utf-8 -*-
import scrapy
from jingdong.items import JingdongItem
class JdSpider(scrapy.Spider):
# 爬虫名
= "jd"
name # 允许爬虫作用的范围
= ["list.jd.com"]
allowed_domains # 页面提取url 也可以拼接url:https://list.jd.com/list.html?cat=652,654,831&page=0
# 爬虫起始的url
= ['https://list.jd.com/list.html?cat=652,654,831']
start_urls = 1 # 设置爬取的起始页数
offset def parse(self, response):
= response.xpath('//div[@id="plist"]//li[@class ="gl-item"]')
info_list for each in info_list:
# 构建item对象,用来保存数据
= JingdongItem()
item ####################################################
########## 一下为提取页面信息######################
# 提取商品的名称,
if len( each.xpath('./div/div[@class="p-name"]/a/em/text()') ) == 0 :
'name']=""
item[else:
'name'] = each.xpath('./div/div[@class="p-name"]/a/em/text()').extract()[0]
item[
# 商品简介
if len(each.xpath('./div/div[@class="p-name"]/a/i[@class="promo-words"]/text()'))==0:
'abstract']=""
item[else:
'abstract'] = each.xpath('./div/div[@class="p-name"]/a/i[@class="promo-words"]/text()').extract()[0]
item[
# 商品链接
if len(each.xpath('./div/div[@class="p-name"]/a/@href'))==0:
'link'] = ""
item[else:
'link'] = each.xpath('./div/div[@class="p-name"]/a/@href').extract()[0]
item[
# 商品价格
if len(each.xpath('./div/div[@class="p-price"]/strong[1]/i/text()'))==0:
'price'] = ""
item[else:
'price'] = each.xpath('./div/div[@class="p-price"]/strong[1]//i/text()').extract()[0]
item[
# 商品店铺名称
if len(each.xpath('./div/div[@class="p-shop"]/span/a/text()'))==0:
'shop_name']=""
item[else:
'shop_name'] = each.xpath('./div/div[@class="p-shop"]/span/a/text()').extract()[0]
item[
# 商品评论数
if len(each.xpath('./div/div[@class="p-commit p-commit-n"]/strong/a/text()'))==0:
'commet']=""
item[else:
'commet'] = each.xpath('./div/div[@class="p-commit p-commit-n"]/strong/a/text()').extract()[0]
item[# 通过yield 返回数据,返回数据后还能回来继续执行下面的代码
yield item
# 直接从response获取需要爬取的链接,并发送给请求处理,直到链接处理完成
if len(response.xpath('//div[@class="p-wrap"]//a[@class="pn-next"]'))!= 0 and self.offset<1000:
# self.offset手动控制爬取的页面数 ,当然这里没有1000个页面,直到所有为止
self.offset = self.offset+1
= response.xpath('//div[@class="p-wrap"]//a[@class="pn-next"]/@href').extract_first()
next_url = "https://list.jd.com/"+next_url# 找到下一页的url链接
url yield scrapy.Request(url=url,callback= self.parse)
6 编写pipelines.py(管道文件)
编写管道文件,处理spider返回的item数据,我把它存为json文件: 如下
import json
class JingdongPipeline(object):
def __init__(self):
self.f = open("jingdong_xiangji.json","w")
def process_item(self, item, spider):
= json.dumps(dict(item),ensure_ascii=False) + ",\n"
content self.f.write(content)
return item # 一定要返回item ,相当于告诉引擎,我做事做完了,请给我下一个item
# 第一个方法:只执行一次
def close_spider(self,spider):
self.f.close()
7 编写middlewares.py(下载中间件)
由于京东这个网站,网页是动态加载的,于是结合selenium进行下载,(如果是静态页面,无需写这个文件,以及后面的第8步)
from selenium import webdriver
#检查页面是否加载完毕
import time
from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options #设置Google的无头浏览器
class JingdongSpiderMiddleware(object):
# 开始运行的选项
def __init__(self):
= Options()
chrome_options = {"profile.managed_default_content_settings.images":2}
prefs # 设置Chrome浏览器不加载图片的方法
"prefs",prefs)
chrome_options.add_experimental_option(#设置Google的无头浏览器
'--headless')
chrome_options.add_argument(self.browser = webdriver.Chrome(chrome_options=chrome_options)
self.browser.maximize_window() # 最大化浏览器
self.browser.implicitly_wait(10)#隐式等待10s
# 最后结束的时候运行的选项
def __del__(self):
self.browser.close()
self.browser.quit()
def process_request(self,request,spider):
try:
self.browser.get(request.url)
self.browser.implicitly_wait(6)
self.browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
3)
time.sleep(self.browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
3)
time.sleep(return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,encoding='utf-8',request=request,status=200)
except TimeoutException as e:
print("超时")
self.browser.execute_script('window.stop()')
return HtmlResponse(url=request.url,status=500,request = request)
8 设置下载中间件
= {
DOWNLOADER_MIDDLEWARES 'jingdong.middlewares.JingdongSpiderMiddleware': 543,
}
9 最后的settings.py(设置文件)
由于爬虫有时候网站不让你爬 。有一个robots协议,我们不管这个,需要在setting.py设置,把ROBOTSTXT_OBEY = False即可
最后我的setting.py 如下:
= 'jingdong'
BOT_NAME
= ['jingdong.spiders']
SPIDER_MODULES = 'jingdong.spiders'
NEWSPIDER_MODULE ########################### 以上全自动生成
#以下为 手动改写
= False
ROBOTSTXT_OBEY = {
DOWNLOADER_MIDDLEWARES 'jingdong.middlewares.JingdongSpiderMiddleware': 543,
}= {
ITEM_PIPELINES 'jingdong.pipelines.JingdongPipeline'
300,
:
}
## 解释: 'jingdong.pipelines.JingdongPipeline' ## 注意这里的字典 键要对应前面的类,
##### jingdong 为爬虫项目名,
##### pipelines为爬虫下面的pipelines.py文件的文件名,
##### JingdongPipeline为pipelines.py中的类名
10 最后执行爬虫文件:
cmd下执行:
scrapy crawl jd
# 注意:jd为 spiders/jd.py文件中name的值 即(name = "jd")
# 也可以执行 scrapy crawl jd -o jd_xiangji.csv
#### 即存为 json 又有保存了csv文件 ,生成的文件都在当前目录下(我们可以在爬虫的项目的文件下创建一个data文件夹,在这个文件夹下执行爬虫文件,就可以把代码和数据分开了。
######################
# 在cmd下运行的命令 只要在爬虫项目文件下运行都可以执行,
11 结果展示
一共 7192 条信息 = 120* 60 (最后一页没有60个商品)
可以看出速度很快(大概20分钟左右)就抓取玩了