scrapy框架使用:分布式、增量式
scrapy框架的使用
前记:爬虫框架部分整理完成,后续慢慢完善,
声明:
1)仅作为个人学习,如有冒犯,告知速删!
2)不想误导,如有错误,不吝指教!
创建工程:
scrapy startproject name
cd proName
scrapy genspider spiderName urlName(限制爬虫的爬取范围)
执行:scrapy crawl spiderName
start_urls = []=====>列表中的元素会被scrapy自动进行发送--几个url,请求
setting必备设置:
robotstxt_obey = False
USER_AGENT = ' '
LOG_LEVEL = 'ERROR'
LOG_FILE = 'log.txt'----一般不用
scrapy框架中:
xpath返回的列表中的列表元素是selector对象,我们需要解析获取的字符串的数据
必须经过一个extract() 操作才可以将该对象汇总存储的字符串的数据获取
.extract()----列表
.extract_first()-----字符串
---问题:xpath返回的列表中的列表元素有多个(selector对象),想要将每个列表元素对应的selector中的字符串取出--------使用 extract()
scrapy数据解析
xpath语法
通过返回的response数据可以直接直接进行Xpath解析。
scrapy持久化存储
基于终端指令:
只可以将parse方法的返回值存储到电脑磁盘中
scrapy crwal first -o file.csv-------->将当前返回值存储到file文件中csv\json
基于管道:>pipelines.py
编码流程
数据解析(在爬虫类中)
在item的类中定义相关的属性(爬虫类)
将解析的数据存储封装到item类型的对象中;
将item对象提交给管道 yield
在管道类中process_item方法负责接收item对象,然后对item进行任意形式的格式持久化存储
在settings中设置MySQL的配置信息
- # 如下所示
# mysql 配置
MYSQL_DB_NAME = 'scrapy_db'
MYSQL_HOST = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_PASSWORD = '123456'
- # 如下所示
细节补充:
管道文件中的一个管道类表示将数据存储到某一个形式的平台中。
如果管道文件中定义多个管道类,爬虫类提交的item的操作会给到优先级最高的管道类,只有优先级最高的管道类才可以接受到item,剩下的管道类是需要从优先级最高的管道中接受item;
process_item 方法的实现中的return item的操作表示item传递给下一个即将被执行的管道类
手动请求发送:
yield scrapy.Request(url,callback)-----发送的get请求
对yield总结:
1). 向管道提交item的时候:yield item
2). 手动请求发送:yeld scrapy.Request(url,callback)
手动发送post请求:
yield scrapy.FormRequest(url,formdata,callback):formdata是一个字典表示请求参数
scrapy五大核心组件:
- 略(网上都有)
scrapy的请求传参:
- - 作用:实现深度爬取
- 使用场景:使用scrapy爬取的数据没有存在同一张页面的数据
- 传递item:使用meta的技巧----yield scrapy.Request(url,callback,meta)
- 接受item:response.meta
提升scrapy爬取数据的效率(配置文件中):
- 增加并发:
CONCURRENT_REQUESTS = 100
- 降低日志级别:
LOG_LEVEL='ERROR'
- 禁止cookies:
COOKIES_ENABLE = True
-禁止重试:
retry_ebable = False
- 减少下载超时:
DOWNLOAD_TIMEOUT = 3----请求超过3,丢弃,
scrapy的中间件(middlewares):
--概念:下载中间件
--->处于引擎和下载器
--封装了两个类:
NameDownloaderMiddleware;NameSpiderMiddleware
--一次请求经过两次中间件:
---必须经过引擎:
首先由调度器(scheduler)到下载器(downloader)之间可以进行request的修改与设置;
再由下载器(downloader)到主爬虫(spider)之间可以进行response的修改与设置;
-- 批量拦截所有的请求响应
-- 拦截请求
-- 篡改请求的头信息(UA伪装)
-- 篡改请求对应的ip(代理)
-- 拦截响应:
-- 篡改响应数据,篡改响应对象
下载器中间件中的核心方法(NameDownloaderMiddleware):
位置:处于scrapy的Request和Response之间的处理模块;
process_request---拦截正常请求,并修改与设置
进行ua伪装:resquest.headers["User-Agent"] = "xxx "
随机更换UA
- 1 #middlewares中间件重写,记得开启该中间件
- 2 from scrapy import signals
- 3 import random
- 4 from xbhog.settings import USER_AGENTS_LIST
- 5
- 6 class UserAgentMiddleware(object):
- 7
- 8 def process_request(self,request,spider):
- 9 #设置随机请求头
- 10 ua = random.choice(USER_AGENTS_LIST)
- 11 #设置初始URL中的UA
- 12 request.headers['User-Agent'] = ua
- 1 #middlewares中间件重写,记得开启该中间件
- 1 #settings设置
- 2 USER_AGENTS_LIST = [
- 3 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
- 4 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
- 5 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
- 6 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
- 7 "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
- 8 "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
- 9 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
- 10 "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5"
- 11 ]
- 1 #settings设置
有一个fake-useragent,自行百度下用法;
见仁见智
进行代理设置:resquest.meta["proxy"] = proxy
代理池中随机选择代理ip
代理ip的webapi发送请求获取一个代理ip
添加代理:基本认证与摘要认证
source:一文读懂HTTP Basic身份认证https://juejin.im/entry/5ac175baf265da239e4e3999
- 1 #settings设置 PROXY_LIST = {"ip_port":"ip:port","user_pass":"user:pass"}
- 1 #付费代理
- 2 import base64
- 3
- 4 # 代理隧道验证信息 这个是在那个网站上申请的
- 5 proxyServer = 'http://proxy.abuyun.com:9010' # 收费的代理ip服务器地址,这里是abuyun
- 6 proxyUser = 用户名
- 7 proxyPass = 密码
- 8 #Basic后面有一个空格
- 9 proxyAuth = "Basic " + base64.b64encode(proxyUser + ":" + proxyPass)
- 10
- 11 class ProxyMiddleware(object):
- 12 def process_request(self, request, spider):
- 13 # 设置代理
- 14 request.meta["proxy"] = proxyServer
- 15 # 设置认证
- 16 request.headers["Proxy-Authorization"] = proxyAuth
- 1 #付费代理
返回三种方式:
返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法
返回Response对象:不再请求,把response返回给引擎j交给spider解析
返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法。
scrapy与selenium中间件的使用:
可以选择性的使用selenium,因为selenium比较慢,我们尽可能的避免使用它,在下载器中间件里面的process_request函数,可以理解所有的请求都要经过该函数,所以我们在修改请求时,可以判断所过的url里面有没有我们需要用selenium的url,一般可以使用url里面的关键字进行判断;
- 1 #判断关键字是否在url中
- 2 if "xxxxx" in resquest.url:
- 3 driver = webdriver.Chorme()
- 4 driver.get(url)
- 5 time.sleep(3)
- 6
- 7 data = driver.page_source
- 8
- 9 driver.close()
- 10 #创建相应对象
- 11 res = HtmlResponse(url=url,body=data,encoding='utf-8',request=request)
- 1 #判断关键字是否在url中
- 1 from scrapy.http import HtmlResponse
- 2 import time
- 3
- 4
- 5 #设置selenium的中间件
- 6 class SelemiumSpiderMiddleware(object):
- 7
- 8 def process_request(self, request, spider):
- 9 spider.driver.get(request.url)
- 10 time.sleep(1)
- 11 #获得渲染后的网页源代码
- 12 page_text = spider.driver.page_source
- 13 spider.driver.close()
- 14 #创建响应对象
- 15 return HtmlResponse(url=request.url, body=page_text, request=request, encoding='utf-8')
- 1 from scrapy.http import HtmlResponse
process_response--拦截所有的响应
在downloader执行Request下载后,会得到对应的response,在发送到spider之前,可以使用process_response来对数据进行处理。
process_exception--拦截发生异常的请求对象
当downloader或者process_request()方法抛出异常是,该方法会被调用;
spider中间件:(NameSpiderMiddleware):
spider Middleware是接入到scrapy的Spider处理机制的钩子框架;
在Downloader生成Response之后,Response会被发送到Spider之前,首先经过SpiderMiddleware处理,当spider处理生成item和Request之后,还会经过SpiderMiddleware处理。
暂时没有用到,只大体学习记录;
--四大核心方法(百度自行了解):
-process_spider_input
-process_spider_output
-process_spider_exception
-process_start_requests
CrawlSpider:
- - 基于scrapy进行全站数据爬取的一种新的手段
CrawlSpider就是spider的一个子类
链接提取器(LinkExtractor):
规则解析器(Rule):
使用流程
新建一个工程
cd 工程中
新建一个爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com
样例:
- 1 #demo
- 2 # -*- coding: utf-8 -*-
- 3 import scrapy
- 4 from scrapy.linkextractors import LinkExtractor
- 5 from scrapy.spiders import CrawlSpider, Rule
- 6
- 7
- 8 class CrawlproSpider(CrawlSpider):
- 9 name = 'Crawlpro'
- 10 allowed_domains = ['www.xxx.com']
- 11 start_urls = ['http://www.xxx.com/']
- 12
- 13 rules = (
- 14 Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
- 15 )
- 16
- 17 def parse_item(self, response):
- 18 item = {}
- 19 #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
- 20 #item['name'] = response.xpath('//div[@id="name"]').get()
- 21 #item['description'] = response.xpath('//div[@id="description"]').get()
- 22 return item
- 23
- 1 #demo
分布式:
-- 目的:
- 让多台爬虫机器同时运行爬虫任务并协同爬取,协同爬取的前提是共享爬取队列;
- 统一爬取队列,多个调度器、多个下载器----结果是爬取效率翻倍。
-- 维护爬虫队列:
- 性能考虑:基于内存存储的redis
列表有lpush、lpop、rpush、rpop方法,实现先进先出爬取队列,也可以实现先进后出栈式爬取队列
集合元素无需并且不重复
可实现带优先级的调度队列
-- URL地址去重:
使用md5生成的数据指纹来筛选数据,将转换的md5值与之前的传入redis中的数据进行比对;
使用哈希算法生成数据指纹筛选数据,将转换的md5值与之前的传入redis中的数据进行比对;
布隆过滤器
-- 文本内容去重:
编辑距离算法
simhash算法
-- 防止中断:
为什么要防止中断:
在scrapy中,爬虫运行时的Request队列放在内存中,在爬虫运行中中断后,这个空间就被释放,此队列就被销毁,所以一旦爬虫被中断,爬虫再次运行就相当于全新的爬取过程。
解决方法:
将队列中的Request保存起来,再次爬取直接读取保存的数据即可
实现命令:
- scrapy crawl spider -s JOB_DIP=crawls/spider(路径使用JOB_DIP标识)
增量式:
概念:用于检测网站数据更新的情况。
应用的网站类型:
增量式深度爬取
增量式非深度爬取
核心机制:去重;redis-set去重方式(可做持久化存储),python中的set是基于缓存中的
增量式流程:
- 与基本的爬虫Scrapy流程相似,只是再spider中加了数据指纹的认证
再pipelines中增加了redis的存储过程
- 与基本的爬虫Scrapy流程相似,只是再spider中加了数据指纹的认证
rules配置规则
数据库的连接
item数据类型创建完成
pipelines
数据库的调用:spider.方法
redis的存储
框架中的item传输问题(parse传到其他函数中):
传输:
- 1 yield scrapy.Resquest(url,callback=self.parse_detail,meta={'item':item})
下个函数接收:
- 1 item = response.meta['item']
- 2 item[""] = ...
- 3 yield item
- 1 item = response.meta['item']
scrapy中的post请求:
首先创建好scrapy
文件,注释掉allowed_domains以及start_urls
;重写初始化请求(start_requests)
,最后yield
返回给解析函数。
- 1 class xxx(scrapy.Spider):
- 2 name = 'xxxx'
- 3 #allowed_domains = ['']
- 4 #start_url = ['']
- 5
- 6 def start_requests(self):
- 7 headers = {}
- 8 base_url = ''
- 9 formdata = {}
- 10 yield scrapy.FormRequest(url=base_url,headers=headers,formdata=formdata,callback=self.parse)
- 11 #如果使用FormRequest报错,备选方案
- 12 scrapy.Request(url=base_url,headers=headers,body=json.dumps(formdata),method= 'POST',callback=self.parse)
- 13
- 14
- 15 def parse(self,response):
- 16 pass
扩展:
反爬机制整理:
robots
UA伪装
验证码
代理
cookie
动态变化的请求参数
JS加密
JS混淆
图片懒加载
动态数据的获取
selenium:规避检测
图片懒加载:
网站优化手段
应用到标签的伪属性,数据捕获的时候一定基于伪属性进行
- 是一种反爬机制,图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。
- 在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original…)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。
- 是一种反爬机制,图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。
imagePileline:专门用于二进制数据下载和持久化存储的管道类(图片下载)
scrapy中技巧:
当调用item中的类时,没有显示且标红
解决方法:找到项目根文件--右击--找到Mark Directory as----Source-root后点击,生成源文件
- 1 #翻页设置
- 2 url = response.xpath('//span[@class="next"]/a/@href').extract_first()
- 3 if url !=None:
- 4 ''''
- 5 在提取数据后,parse()方法查找到下一页的链接,使用urljoin()方法构建完整的绝对URL(因为链接可以是相对的),
- 6 并产生一个新的请求到下一个页面,将自己作为回调函数来处理下一页的数据提取,并保持遍历所有页面的抓取。
- 7 '''
- 8 url = response.urljoin(url)
- 9 yield scrapy.Request(
- 10 url=url,callback=self.parse
- 11 )
- 1 #翻页设置
selenium-绕过网站监测:
source
:https://www.cnblogs.com/presleyren/p/12936553.html
使用 Google 的Chrome Devtools-Protocol(Chrome 开发工具协议)简称CDP。
通过这个命令,我们可以给定一段 JavaScript 代码,让 Chrome 刚刚打开每一个页面,还没有运行网站自带的 JavaScript
代码时,就先执行我们给定的这段代码。
那么如何在 Selenium
中调用 CDP
的命令呢?实际上非常简单,我们使用driver.execute_cdp_cmd
。根据 Selenium 的官方文档[2],传入需要调用的 CDP 命令和参数即可;
只需要执行一次,之后只要你不关闭这个driver开启的窗口,无论你打开多少个网址,他都会自动提前在网站自带的所有 js 之前执行这个语句,隐藏window.navigator.webdriver
。
完美隐藏window.navigator.webdriver
。并且,关键语句:
- 1 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
- 2 "source": """
- 3 Object.defineProperty(navigator, 'webdriver', {
- 4 get: () => undefined
- 5 })
- 6 """
- 7 })
虽然使用以上代码就可以达到目的了,不过为了实现更好的隐藏效果,大家也可以继续加入两个实验选项:
- 1 from selenium import webdriver
- 2 options = webdriver.ChromeOptions()
- 3 options.add_experimental_option("excludeSwitches", ["enable-automation"])
- 4 options.add_experimental_option('useAutomationExtension', False)
- 5 driver = webdriver.Chrome(options=options, executable_path='./chromedriver')
- 6 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
- 7 "source": """
- 8 Object.defineProperty(navigator, 'webdriver', {
- 9 get: () => undefined
- 10 })
- 11 """
- 12 })
- 13 driver.get('http://exercise.kingname.info')
这是close()的说明:
Closes the current window. 关闭当前窗口。
这是quit()的说明:
Quits the driver and closes every associated window. 退出驱动并关闭所有关联的窗口。
gb2312与gb2312 urlencode区别
- 1 import urllib
- 2 country = u'中国'
- 3 country.encode('gb2312')
- 4 #-------'\xd6\xd0\xb9\xfa'
- 5 urllib.quote(country.encode('gb2312'))
- 6 #--------'%D6%D0%B9%FA'
scrapy框架使用:分布式、增量式的更多相关文章
- 爬虫 crawlSpider 分布式 增量式 提高效率
crawlSpider 作用:为了方便提取页面整个链接url,不必使用创参寻找url,通过拉链提取器,将start_urls的全部符合规则的URL地址全部取出 使用:创建文件scrapy startp ...
- python爬虫---CrawlSpider实现的全站数据的爬取,分布式,增量式,所有的反爬机制
CrawlSpider实现的全站数据的爬取 新建一个工程 cd 工程 创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com 连接提取器Link ...
- scrapy框架之分布式操作
分布式概念 分布式爬虫: 1.概念:多台机器上可以执行同一个爬虫程序,实现网站数据的分布爬取. 2.原生的scrapy是不可以实现分布式爬虫? a)调度器无法共享 b)管道无法共享 3.scrapy- ...
- 6 scrapy框架之分布式操作
分布式爬虫 一.redis简单回顾 1.启动redis: mac/linux: redis-server redis.conf windows: redis-server.exe redis-wi ...
- 爬虫开发14.scrapy框架之分布式操作
分布式爬虫 一.redis简单回顾 1.启动redis: mac/linux: redis-server redis.conf windows: redis-server.exe redis-wi ...
- 基于scrapy框架的分布式爬虫
分布式 概念:可以使用多台电脑组件一个分布式机群,让其执行同一组程序,对同一组网络资源进行联合爬取. 原生的scrapy是无法实现分布式 调度器无法被共享 管道无法被共享 基于 scrapy+redi ...
- 爬虫---scrapy分布式和增量式
分布式 概念: 需要搭建一个分布式的机群, 然后在每一台电脑中执行同一组程序, 让其对某一网站的数据进行联合分布爬取. 原生的scrapy框架不能实现分布式的原因 调度器不能被共享, 管道也不能被共享 ...
- 爬虫07 /scrapy图片爬取、中间件、selenium在scrapy中的应用、CrawlSpider、分布式、增量式
爬虫07 /scrapy图片爬取.中间件.selenium在scrapy中的应用.CrawlSpider.分布式.增量式 目录 爬虫07 /scrapy图片爬取.中间件.selenium在scrapy ...
- Scrapy 框架 增量式
增量式: 用来检测网站中数据的更新情况 from scrapy.linkextractors import LinkExtractor from scrapy.spiders import Crawl ...
- 基于Scrapy框架的增量式爬虫
概述 概念:监测 核心技术:去重 基于 redis 的一个去重 适合使用增量式的网站: 基于深度爬取的 对爬取过的页面url进行一个记录(记录表) 基于非深度爬取的 记录表:爬取过的数据对应的数据指纹 ...
随机推荐
- C语言基础之理论概述
C语言介绍 C语言是一种高级程序设计语言,由贝尔实验室的Dennis Ritchie在1972年开发.C语言是结构化编程语言,支持变量.数据类型.运算符.表达式.流程控制语句和函数等基本程序设计元素. ...
- java项目实践-webapp-mytomcat-day16
目录 1. http协议 2. 自定义的web框架 3. 具体实现 4. 启动 1. http协议 CS架构 建立连接"三次握手" 断开连接 "四次挥手" 三次 ...
- VUEX 使用学习四 : action
转载请注明出处: action 用于处理异步任务:action,可以操作任意的异步操作,类似于mutations,但是是替代mutations来进行异步操作的.首先mutations中必须是同步方法, ...
- ORA-00947:Not enough values (没有足够的值)
1.问题 2.解决方式 大概率是关系表实际列数大于你所填的元素个数,请检查是否有疏漏的列即可. 我这里是以为代理键直接忽略不写即可,没有标明具体插入列,但是还是得标明才行 --创建图书目录表TITLE ...
- crypto常用工具
古典密码 维吉尼亚密码(Vigenere): https://github.com/atomcated/Vigenere(加密解密程序,包含自动猜测密钥功能) https://www.guballa. ...
- [转帖](1.3)sql server for linux 配置mssql-conf(即SSCM)
https://blog.51cto.com/ultrasql/2152021 目录 [配置mssql-conf] 启用SQL Server代理 修改SQL Server排序规则 配置客户反馈 修改默 ...
- [转帖]SIMD+SSE+AVX
http://home.ustc.edu.cn/~shaojiemike/posts/simd/ SIMD SIMD全称Single Instruction Multiple Data,单指令多数 ...
- 【转帖】JAVA GC日志分析
https://zhuanlan.zhihu.com/p/613592552 目录 1. GC分类 针对HotSpot VM的实现,它里面的GC按照回收区域又分为两大种类型:一种是部分收集(Par ...
- [转帖]Linux:CPU频率调节模式以及降频方法简介
概述 cpufreq的核心功能,是通过调整CPU的电压和频率,来兼顾系统的性能和功耗.在不需要高性能时,降低电压和频率,以降低功耗:在需要高性能时,提高电压和频率,以提高性能. cpufreq 是一个 ...
- bcc工具的简要学习
摘要 继续补充假期落下的内容. 其实有很多知识需要学习, 自己掌握的还是偏少一些. bcc的全貌 # 注意 bcc 需要较高的内核. 3.10 系列的内核基本不可用. argdist drsnoop ...