目录:Python网络爬虫实战系列
- Python网络爬虫实战之一:网络爬虫理论基础
- Python网络爬虫实战之二:环境部署、基础语法、文件操作
- Python网络爬虫实战之三:基本工具库urllib和requests
- Python网络爬虫实战之四:BeautifulSoup
- Python网络爬虫实战之五:正则表达式
- Python网络爬虫实战之六:静态网页爬取案例实战
- Python网络爬虫实战之七:动态网页爬取案例实战 Selenium + PhantomJS
- Python网络爬虫实战之八:动态网页爬取案例实战 Selenium + Headless Chrome
- Python网络爬虫实战之九:Selenium进阶操作与爬取京东商品评论
- Python网络爬虫实战之十:利用API进行数据采集
- Python网络爬虫实战之十一:Scrapy爬虫框架入门介绍
- Python网络爬虫实战之十二:Scrapy爬虫三个实战小案例
- Python网络爬虫实战之十三:Scrapy爬取名侦探柯南漫画集
- Python网络爬虫实战之十四:Scrapy结合scrapy-splash爬取动态网页数据
正文:
一、Scrapy爬取动态网页数据的原理
之前我们学习的内容都是抓取静态页面,每次请求,它的网页全部信息将会一次呈现出来。 但是,像比如一些购物网站,他们的商品信息都是js加载出来的,并且会有ajax异步加载。像这样的情况,直接使用scrapy的Request请求是拿不到我们想要的信息的,比如京东商城的商品列表中的价格、店铺名称、评论数量。解决的方法就是使用scrapy-splash。
scrapy-splash加载js数据是基于Splash来实现的,Splash是一个Javascript渲染服务。它是一个实现了HTTP API的轻量级浏览器,Splash是用Python实现的,同时使用Twisted和QT,而我们使用scrapy-splash最终拿到的response相当于是在浏览器全部渲染完成以后,拿到的渲染之后的网页源代码。
二、爬取之前的环境部署
1、安装docker
在windows环境下,安装docker简便的方法是使用docker toolbox,由于Docker引擎的守护进程使用的是Linux的内核,所以我们不能够直接在windows中运行docker引擎。而是需要在你的机器上创建和获得一个Linux虚拟机,用这个虚拟机才可以在你的windows系统上运行Docker引擎,docker toolbox这个工具包里面集成了windows环境下运行docker必要的工具,当然也包括虚拟机了。
首先下载docker toolbox,
官方下载地址:https://www.docker.com/products/docker-desktop
执行安装程序,默认情况下,你的计算机会安装以下几个程序
- Windows版的Docker客户端
- Docker Toolbox管理工具和ISO镜像
- Oracle VM 虚拟机
- Git 工具
当然,如果你之前已经安装过了Oracle VM 虚拟机 或者 Git 工具 ,那么你在安装的时候可以取消勾选这两个内容,之后,你只需要狂点下一步即可。安装完毕以后,找到Docker Quickstart Terminal图标,双击运行,稍等它自己配置一小段时间,你会看到以下的界面
scrapy1.png请注意上面画红框的地方,这是默认分配给你的ip,下面会用到。至此,docker工具就已经安装好了。
2、安装Splash
双击运行Docker Quickstart Terminal,输入以下内容
docker pull scrapinghub/splash
这个命令是拉取Splash镜像,等待一算时间,就可以了。
下面就是启动Splash
docker run -p 8050:8050 scrapinghub/splash
这个命令就是在计算机的8050端口启动Splash渲染服务
你会看到以下的图示内容。
这个时候,打开你的浏览器,输入192.168.99.100:8050你会看到出现了这样的界面。
scrapy3.png你可以在上图红色框框的地方输入任意的网址,点击后面的Render me! 来查看渲染之后的样子。
3、安装scrapy-splash
pip install scrapy-splash
至此,我们的准备环节已经全部结束了。
4、如果以上操作遇到困难
以上操作如遇到困难,请参考 Docker Toolbox for Windows 之安装二三事解决
三、实战爬取京东商品列表中的商品信息
网页地址:https://list.jd.com/list.html?cat=652,654,831
1、创建项目
scrapy startproject jdcamera
创建项目后在spider目录下新建 camera.py 文件
项目结构截图
scrapy4.png
2、items.py代码
import scrapy
class JdcameraItem(scrapy.Item):
# 名称
name = scrapy.Field()
# 链接
link = scrapy.Field()
# 价格
price = scrapy.Field()
# 销售店铺
owner = scrapy.Field()
# 评论数
comment = scrapy.Field()
3、camera.py代码
import scrapy
from jdcamera.items import JdcameraItem
from scrapy.http import Request
import re
from scrapy_splash import SplashRequest
class CameraSpider(scrapy.Spider):
name = "jdcamera"
allowed_domains = ["list.jd.com"]
start_urls = (
'https://list.jd.com/list.html?cat=652,654,831',
# "https://list.jd.com/list.html?cat=652,654,831&page=1&sort=sort_totalsales15_desc&trans=1&JL=6_0_0#J_main"
)
def start_requests(self):
for url in self.start_urls:
yield SplashRequest(url=url, callback=self.parse,
args={'wait': 1}, endpoint='render.html')
def parse(self, response):
for sel in response.xpath('//*[@id="plist"]/ul/li/div[@class="gl-i-wrap j-sku-item"]'):
item = JdcameraItem()
# 链接
item["link"] = "http:" + str(sel.xpath('div[1]/a/@href').extract())[2:-2]
# 价格
item["price"] = sel.xpath('div[2]/strong[1]/i/text()').extract()
# 商品名称
temp = str(sel.xpath('div[3]/a/em/text()').extract())
pattern = re.compile("[\u4e00-\u9fa5]+.+\w") # 从第一个汉字起 匹配商品名称
good_name = re.search(pattern, temp)
item["name"] = good_name.group()
# 评论数
item["comment"] = sel.xpath('div[4]/strong/a/text()').extract()
# 销售店铺
item["owner"] = sel.xpath('div[5]/span/a/text()').extract()
# 提取完后返回item
yield item
# 通过循环自动爬取127页的数据
for i in range(2, 128):
# 通过上面总结的网址格式构造要爬取的网址
url = "https://list.jd.com/list.html?cat=652,654,831&page=" + str(i) + "&sort=sort_totalsales15_desc&trans=1&JL=6_0_0"
# 通过yield返回Request,并指定要爬取的网址和回调函数
# 实现自动爬取
# yield Request(url, callback=self.parse)
yield SplashRequest(url=url, callback=self.parse, args={'wait': 1}, endpoint='render.html')
4、pipelines.py代码
import codecs
import json
class JdcameraPipeline(object):
def __init__(self):
# 此时存储到的文件是mydata2.json,不与之前存储的文件mydata.json冲突
self.file = codecs.open('D:/DataguruPyhton/PythonSpider/images/京东数码相机.txt', "wb", encoding="utf-8")
def process_item(self, item, spider):
# 每一页中包含多个商品信息,所以可以通过循环,每一次处理一个商品
# 其中len(item["name"])为当前页中商品的总数,依次遍历
# 将当前页的第j个商品的名称赋值给变量name
name = item["name"]
price = item["price"]
owner = item["owner"]
comment = item["comment"]
link = item["link"]
# 将当前页下第j个商品的name、price、comnum、link等信息处理一下,重新组合成一个字典
goods = {"name": name, "price": price, "owner": owner, "comment": comment, "link": link}
# 将组合后的当前页中第j个商品的数据写入json文件
i = json.dumps(dict(goods), ensure_ascii=False)
line = i + '\n'
self.file.write(line)
# 返回item
return item
def close_spider(self, spider):
self.file.close()
5、settings.py代码
BOT_NAME = 'jdcamera'
SPIDER_MODULES = ['jdcamera.spiders']
NEWSPIDER_MODULE = 'jdcamera.spiders'
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
# Disable cookies (enabled by default)
COOKIES_ENABLED = False
# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}
# 渲染服务的url
SPLASH_URL = 'http://192.168.99.100:8050'
# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
ITEM_PIPELINES = {
'jdcamera.pipelines.JdcameraPipeline': 300, # 实现保存到txt文件
}
# 去重过滤器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
# 使用Splash的Http缓存
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
6、运行项目
scrapy crawl jdcamera
结果如图:
scrapy5.png
网友评论