使用 Scrapy + Selenium 爬取动态渲染的页面
点击上方蓝字关注我们!
背景
在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值。但是通过观察我们会发现,通过浏览器进行url请求发送则会加载出对应的动态加载出的数据。那么如果我们想要在scrapy也获取动态加载出的数据,则必须使用selenium创建浏览器对象,然后通过该浏览器对象进行请求发送,获取动态加载的数据值. 本文分享scrapy的介绍和如何配合selenium实现动态网页的爬取。
Scrapy
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。其最初是为了 页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。
Scrapy 安装并运行
安装 通过pip install Scrapy 安装即可, Ubuntu安装需要安装依赖sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zliblg-dev libffi-dev libssl-dev;
创建项目: scrapy startproject project_name;
创建爬虫: 进入项目根目录 scrapy genspider spider_name sprder_domian;
目录介绍;
project_folder -- 项目文件夹名称
|
|──project_name -- 该项目的python模块,一般和项目文件夹名称相同
| |
| |──spider -- 放置spider代码的包,以后所有的爬虫,都存放在这个里面
| |
| |──items.py -- 用来存放爬虫怕写来的数据的模型
| |
| |──middlewares.py -- 用来存放各种中间件的文件
| |
| |──pipelines.py -- 用来对items里面提取的数据做进一步处理,如保存到本地磁盘等
| |
| |──settings.py -- 本爬虫的一些配置信息(如请求头、多久发送一次请求、ip代理池等)
|
|──scrapy.cfg -- 项目的配置文件
01
Scrapy执行流程
Scrapy中的数据流由执行引擎控制,其过程如下:
- (从第二步)重复直到调度器中没有更多的请求(Requests)。
02
Scrapy架构图
03
中间件架构
Selenium
Selenium有很多东西,但从本质上讲,它是一个 Web 浏览器自动化工具集,它使用可用的最佳技术远程控制浏览器实例并模拟用户与浏览器的交互。它允许用户模拟最终用户执行的常见活动;在字段中输入文本,选择下拉值和复选框,并单击文档中的链接。它还提供了许多其他控件,例如鼠标移动、任意 JavaScript 执行等等。
01
selenium 安装
安装 pip install selenium
02
驱动安装
使用selenium驱动chrome浏览器需要下载chromedriver,而且chromedriver版本需要与chrome的版本对应,版本错误的话则会运行报错。
03
chrome
下载chromedriver可以通过淘宝镜像地址:
http://npm.taobao.org/mirrors/chromedriver/
最新的镜像与Chrome同名,尽量选择版本相近的避免兼容问题,镜像下notes.txt可查看当前驱动支持的版本。
04
其他浏览器驱动
Opera:http://npm.taobao.org/mirrors/operadriver/
IE: http://selenium-release.storage.googleapis.com/index.html
使用requests爬取动态渲染的页面
import requestsheader = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ''AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36','Accept-Encoding': 'gzip','Connection': 'keep-alive','Host': 'www.aqistudy.cn',
}url = "https://192.168.1.1/aqistudy/monthdata.php?city=北京"
res = requests.get(url, headers=header)
if res.status_code == 200:print("请求成功")with open("aqistudy.txt", encoding="utf8", mode='w+') as f:f.write(res.text)
else:print("请求失败")
<table width="100%" class="table table-condensed table-bordered table-striped table-hover table-responsive" style="margin-bottom:5px"><tr height=38px><th style="background:#d9edf7">月份</th><th style="background:#d9edf7">AQI</th><th style="background:#d9edf7" class="hidden-xs">范围</th><th style="background:#d9edf7" width="80px" >质量等级</th><th style="background:#d9edf7">PM2.5</th><th style="background:#d9edf7">PM10</th><th style="background:#d9edf7" class="hidden-xs">SO2</th><th style="background:#d9edf7" class="hidden-xs">CO</th><th style="background:#d9edf7" class="hidden-xs">NO2</th><th style="background:#d9edf7" class="hidden-xs">O3</th></tr></table>
var muwSVVIti = 'GETMONTHDATA';endebug(false, function () {document.write('检测到非法调试, 请关闭调试终端后刷新本页面重试!');document.write("<br/>");document.write("Welcome for People, Not Welcome for Machine!");diwAafiP = true;});txsdefwsw();document.onkeydown = function() {if ((e.ctrlKey) && (e.keyCode == 83)) {alert("检测到非法调试,CTRL + S被管理员禁用");return false;}}document.onkeydown = function() {var e = window.event || arguments[0];if (e.keyCode == 123) {alert("检测到非法调试,F12被管理员禁用");return false;}}document.oncontextmenu = function() {alert('检测到非法调试,右键被管理员禁用');return false;}
}
可以看到 返回的页面源码中 只有一个天气表格的框架, 没有我们需要的天气信息. 而且出现了被检测的信息. 出现这种情况 是因为:
● 目标网页是动态渲染的页面, 所以我们只能看到天气表格的框架,看不到具体的信息
● 目标网页检测到selenium 禁止调试
Scrapy + Selenium
- 运行一个Scrapy的项目
import scrapyclass ApistudyMainSpider(scrapy.Spider):name = 'apistudy_main'allowed_domains = ['192.168.1.1']def start_requests(self):start_url = r'https://192.168.1.1/aqistudy/monthdata.php?city=北京'yield scrapy.Request(url=start_url, callback=self.parse, dont_filter=True)def parse(self, response):yield {'text': response.text}
class AqistudyPipeline(object):# def process_item(self, item, spider):# return itemdef open_spider(self, spider):self.file = open('my.html', 'w', encoding='utf-8')def close_spider(self, spider):self.file.close()def process_item(self, item, spider):self.file.write(str(item['text']))
class RandomHeaderMiddleWare:def __init__(self):self.user_agents = USER_AGENTSdef process_request(self, request, spider):request.headers['User-Agent'] = random.choice(self.user_agents)# 如果IP被限制, 可以在此下载中间件添加代理option = webdriver.ChromeOptions()option.add_argument('--headless') # 无界面运行option.add_argument('--disable-gpu') # 禁止gpu加速option.add_argument("no-sandbox") # 取消沙盒模式option.add_argument("disable-blink-features=AutomationControlled") # 禁用启用Blink运行时的功能option.add_experimental_option('excludeSwitches', ['enable-automation']) # 开发者模式driver = webdriver.Chrome(options=option)# 移除 `window.navigator.webdriver`. scrapy 默认为Truedriver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""})driver.get(request.url)driver.implicitly_wait(5)content = driver.page_sourcedriver.quit()return HtmlResponse(request.url, encoding="utf-8", body=content, request=request)def process_response(self, request, response, spider):return responsedef process_exception(self, request, exception, spider):return None
SPIDER_MIDDLEWARES = {'aqistudy.middlewares.AqistudySpiderMiddleware': 543,
}DOWNLOADER_MIDDLEWARES = {'aqistudy.middlewares.AqistudyDownloaderMiddleware': 543,'aqistudy.middlewares.RandomHeaderMiddleWare': 545, # 添加下载中间件
}ROBOTSTXT_OBEY = False
<table width="100%" class="table table-condensed table-bordered table-striped table-hover table-responsive"style="margin-bottom:5px"><tbody><tr height="38px"><th style="background:#d9edf7">月份</th><th style="background:#d9edf7">AQI</th><th style="background:#d9edf7" class="hidden-xs">范围</th><th style="background:#d9edf7" width="80px">质量等级</th><th style="background:#d9edf7">PM2.5</th><th style="background:#d9edf7">PM10</th><th style="background:#d9edf7" class="hidden-xs">SO2</th><th style="background:#d9edf7" class="hidden-xs">CO</th><th style="background:#d9edf7" class="hidden-xs">NO2</th><th style="background:#d9edf7" class="hidden-xs">O3</th></tr><tr><td align="center"><a href="daydata.php?city=北京&amp;month=2013-12">2013-12</a></td><td align="center">100</td><td align="center" class="hidden-xs">23~291</td><td align="center"><spanstyle="display:block;width:60px;text-align:center;background-color:#efdc31;color:black;">轻度污染</span></td><td align="center">73</td><td align="center">97</td><td align="center" class="hidden-xs">37</td><td align="center" class="hidden-xs">1.73</td><td align="center" class="hidden-xs">56</td><td align="center" class="hidden-xs">38</td></tr><tr>...></tbody></table>
总结
在撰写爬虫程序时, 遇到动态渲染的页面我们可以使用Scrapy+Selenium对页面规避反爬策略和爬取页面信息. 虽然webdriver影响到了Scrapy 的运行速度, 我们还可以使用scrapy-redis让我们的爬虫变成分布式以提高效率。
哈喽,喜欢这篇文章的话烦请点个赞哦!万分感谢(^▽^)PS:有问题可以联系我们哦v ceshiren001
复制“下方链接”,提升测试核心竞争力!
更多技术文章分享和免费资料领取
使用 Scrapy + Selenium 爬取动态渲染的页面相关推荐
- 使用scrapy +selenium爬取动态渲染的页面
背景 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现 ...
- python爬虫动态加载页面_Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
- Scrapy+Selenium爬取动态网页:no ‘moz:firefoxOptions.binary‘ capability provided
报错信息:selenium.common.exceptions.SessionNotCreatedException: Message: Expected browser binary locatio ...
- scrapy+selenium爬取五个外国新闻网站关于“中国“的新闻,并分析
1.题目 爬取一下5家的加拿大新闻网站包含"China" / "Chinese"的数据,时间范围为2020年1月日至今,分析每家媒体文章的词云图.情感趋势图等. ...
- scrapy+selenium爬取B站生活区热门视频信息!
在爬取动态网页时,一般尽量先找相应网页的API接口.但当接口不好找(或者接口的URL中含有加密参数)时,这时候就需要selenium来帮忙了.但由于selenium爬取速度比较慢,此时结合scrapy ...
- Python之网络爬虫(selenium爬取动态网页、爬虫案例分析、哈希算法与RSA加密)
文章目录 一.selenium爬取动态网页 二.爬虫案例分析 三.哈希hash算法与RSA加密 一.selenium爬取动态网页 1.动态网页认知 爬虫其实就是在模仿浏览器的行为 应对要多次数据的交互 ...
- 【爬虫】Selenium爬取动态网页的base64图片
文章简介 Selenium爬取动态网页的base64图片,并解决页面完整加载缓慢,base64字符串的获取和格式转码,一些页面不存在,部分照片无法加载等问题.后附源码. 目录 1,需求 2,环境和使用 ...
- Python爬虫基础(三) —— 爬取动态渲染页面
文章目录 使用Selenium库 例子引入 声明游览器对象 访问页面 查找节点 单个节点 多个节点 节点交互 动作链 模拟执行javascript 获取节点信息 获取属性 获取文本值 获取id,位置, ...
- python3+scrapy+selenium爬取英雄联盟英雄资料
继前一篇文章用nodejs+puppeteer+chromium爬取了这个英雄资料后,在本篇同样爬这个页面,思路都差不多,只是用不同语言来实现,可作为参考,个人觉得爬虫还是nodejs比较好用,可能是 ...
最新文章
- Office Web Apps证书的申请步骤讲解
- 4.11 日期/时间的程序
- k8s强制删除一直处于terminating状态的pod
- LeetCode每日一题:回文数(No.9)
- a推b等价于非a或b_分级基金谢幕倒计时 警惕分级B高溢价风险
- BZOJ 3053 The Closest M Points
- reboot 重启系统命令
- SourceInsight3.5---a valid serial number was not entered问题解决
- 大众点评 爬虫 python_大众点评爬虫教程 - 八爪鱼采集器
- 【工具】SMART原则的分析举例注意事项
- 零基础学UI设计好学不?
- Silverlight C# 游戏开发:草动系统(一)简单的草动
- Java小白必学——冒泡排序
- Excel表格快速复制公式到最后一行,无需拖拽!
- nginx: worker process is shutting down
- 黄建宏-redis单机服务器
- R及Rstudio下载安装教程
- 520浪漫表白,爱要大胆说出来,无法拒绝的浪漫表白网页
- Redis 实现搜索关键词自动补全
- 元好问《摸鱼儿-雁邱词》赏析
热门文章
- 串行通信比并行通信的速度更高
- 塑胶模具报价计算原理方法与程序
- 会员管理系统实战开发教程(三)-充值记录功能
- Android 屏幕适配神器ScreenMatch
- 洛谷3387 模板 缩点
- c语言gl函数,R语言:gl()函数
- 【ManggoDB】安装配置(伪分布式集群搭建)Replia Set
- Python将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
- Win10 功能大全
- jenkins启动一直显示 Jenkins正在启动,请稍后...