爬虫知识2/22

爬虫知识
爬虫分类:
-通用爬虫:一整张页面源码数据
-聚焦爬虫:一张页面中的局部数据
-增量式爬虫:检测网站数据更新的情况,爬取最新网站的数据
-分布式爬虫:踢高爬取效率的终极武器


如何区别数据是否为动态加载:在捕捉的地址网络network中没搜到所见到的数据
抓动态加载数据的方法:(一)通过抓包工具刷新页面,来审查元素解析地址(network)
1.步骤①刷新页面来全局抓包,点开network,点住Name里面的项目按ctrl+F(全局搜索)
② 输入搜索内容
③ 找到数据的response,打开json格式化数据输出
2,缺点:若动态加载数据是经过加密的密文数据,密文不一定能搜索出来
②通过selenium模拟浏览器抓取
Ajax请求:输入搜索项目,地址url不变(network中的XHR为专有ajax请求)
如何爬取图片:①基于requests
②基于urllib(使用urllib爬图片无法进行UA伪装)
返回数据类型:.content返回二进制,.text返回字符串,.json返回字典或列表对象
————————————————————————————
页面中Element和network的区别:
① E包含显示的页面源码数据为当前页面所有的数据加载完毕后对应的完整页面源码数据
② N显示的页面源码数据仅仅为某一个单独的请求对应的响应数据
③ 结论:数据解析页面时,若当前页面无动态加载的数据,可直接使用Element,否则只能使用network对页面数据解析
数据解析的作用:
——用来实现聚焦爬虫
数据解析的通用原理
——指定标签的定位
——取出标签中存储的数据
Bs4解析原理:(1)实例化BeautifulSoup的对象,并加载页面数据源码到该对象中
BeautifulSoup对象实例化有两种方式:
①BeautifulSoup(fp,’lxml’): ,fp表示本地的文件,用来将本地存储的html文档中的数据进行解析
②BeautifulSoup(page_text,’lxml’)将互联网上请求到的页面源码数据进行解析

		  (2)调用Beautiful对象中相关方法或者属性进行标签定位和文本数据的提取
				(1如何进行标签定位:

①soup.tagname只可以定位到第一次出现的tagName标签,如soup.p
②soup.find(),soup.find(‘tagName’,attrName =‘value’):属性定位
③soup.findALL(),只不过findAll返回的是列表,find返回的是参数,findALL返回的是所有参数
④soup.select(‘选择器’):类选择器/id选择器/层级选择器(soup.select(’.tang>ul>li’),或.tang li,空格表多个层级,>表示一个层级)
(2取数据:-.text返回的是该标签下所有的文本内容
-.string返回的是该标签直系的文本内容
(3取属性:[‘attrName’],如a_tag[‘href’]

Xpath解析原理(xpath返回的是列表):1.实例化一个etree的对象,且将待解析的页面源码加载到数据对象中
实例化etree对象:①ettree.parse(‘filename’)将本地的html文档加载到该对象中②etree.HTML(page_text)网站获取的页面数据加载到该对象
2,调用etree对象的xpath方法结合着不同的xpath表达式实现标签的定位和数据提取
(1标签定位:①如/表示一个层级,//表示多个层级
from lxml import etree
tree = etree.parse(‘text.html’)
tree.xpath(’/html/head/meta’)
tree.xpath(’/html//meta’)
tree.xpath(’//meta’)
②属性定位:tagName.[@attrName=”value”]
class为song的div下面所有的p tree.xpath(‘//div [@class=”song”]/p’)

  1. ③索引定位:定位class为song的div下面第二个p,tag.[index] ,索引从1开始
    tree.xpath(‘//div [@class=”song”]/p[2]’)
    ④ 模糊匹配(略)

(2数据提取:①索引定位去文本:tree.xpath(‘//div [@class=”song”]/p[1]/text()’)
/text()为直系文本内容
//text()为所有的文本内容
②取属性 -/@hattrName
Tree.xpath(‘//div[@class=”feng”]/@href’)
编码格式:utf-8不行用gbk
什么时候使用Xpath还是BS4表达式?
bs4在实现标签定位的时候返回的直接就是定位到标签对应的字符串数据,可以解析出携带html标签的局部数据如 asdasffsd
|为xpath中的可以表示同时生效的管道符作用
————————————————————————————
反爬机制:1.图片懒加载(踢高浏览速度),requests无可视化范围,因此我们解析的是img伪属性的属性值(图品地址)2.robots 3.UA伪装 4.动态加载数据的捕获5.cookies机制
Cookies处理:1,手动处理:将抓包工具中的cookies粘贴在headers中,弊端:cookies过了有效市场就失效了
2.自动处理:基于session对象实现自动处理,requests.session()返回seession对象
为什么在爬虫中需要代理服务器?如果我们的爬虫在短时间内对服务器发起了高频的请求,服务器就会检测到异常的行为请求,就会将该请求的IP禁掉(若IP被禁,我们就可以使用代理服务器进行请求转发,破解ip被禁的反爬机制)
代理服务器不同的匿名度:透明,匿名,高匿代理
代理的类型:https:只能转发https协议的请求
http:转发http的请求
代理服务器:
-快代理
-西饲代理
-goubanjia
-代理精灵(推荐)
在xpath表达式中不可以出现tbody标签(从2开始为 [1:])
验证码的识别:
-基于线上的打码平平台识别验证码
-打码平台:
-超级鹰(专门识别12306)
-云打码
-打码兔
模拟登录:
-流程:点击登录(post请求),处理请求参数(用户名,密码,验证码,其他的防伪参数)
动态变化的请求参数获取:
-方式1:在前台登录页面的element中获取(在element中搜索)
-方式2:若前台页面页面无,基于抓包工具全局搜索
基于百度AI实现的爬虫功能:
-图像识别
-使用流程:1,点控制台登录。2,选想要实现的功能。3,实现功能下创建一个app。4,选择对应的python SDK文档进行代码实现
-语音合成
-自然语言处理
___________________________________________________________________________-
实现异步爬虫:
-基于线程池
-from multiprocessing.dummy import Pool
-map(callback,alist)
-可以实现callback对alist中的每一个元素进行指定形式的异步操作
-基于单线程+多任务的异步爬虫(asynio对应的四个概念)
-特殊的函数
-若一个函数被asynico修饰后变成特殊函数,
-特殊之处:该函数调用后内部函数不会立即执行,调用该函数后会返回一个协程对象
-协程对象:通过特殊函数的调用返回一个协程对象
-协程特殊函数一组指定的操作
-协程一组特殊的操作
-任务对象
-任务对象就是一个高级的协程对象(任务对象就是对协程对象的进一步封装)
-任务
一组指定的操作
-高级之处:可以给任务对象绑定回调,回调函数不是特殊函数
-task.add_done_callback(task_callback)
-回调函数的调用时机:任务被执行结束后,才可以调用回调函数
-回调函数的参数只可以有一个:表示该回调函数的调用这
-使用回调函数的参数调用result()返回的就是任务对象表示的特殊函数return的结果
-如何创建一个任务对象:
-task=asyncio.ensure_future(协程对象)
-事件循环对象
-对象作用:一,可以将多个任务对象注册到事件循环对象中
二,若开启了事件循环后,起内部注册/装载的任务对象表示的指定操作就会被基于异步的被执行
-创建方式:
-loop=asyncio.get_event_loop()
-注册且启动方式
-loop.run_until_complete(task)
Aiohttp:支持异步的网络请求模块
-1,写出大致架构
async def get_requests(url):
#实例化好请求对象
with aiohttp.ClientSession() as sess:
#调用gate发起强求,返回一个响应对象
#get/post(url,headers,params/data,proxy=“http://ip:port”)
with sess.get(url=url) as response:
#获取了字符串形式的响应数据
page_text=response.text()
return page_text
-2,补充细节,sess.get前加await
response.text前加await
在每一个with前加async
(在阻塞操作前加await)
补完整代码
async def get_requests(url):
#实例化好请求对象
with aiohttp.ClientSession() as sess:
#调用gate发起强求,返回一个响应对象
#get/post(url,headers,params/data,proxy=“http://ip:port”)
with await sess.get(url=url) as response:
#text()获取了字符串形式的响应数据
#read()获取byte类型的响应数据
page_text=await response.text()
return page_text
__________________________
selenium:基于浏览器自动化的模块(自动化:通过代码指定一些的动作,作用到浏览器中)
-1,便捷的捕获到任意形式动态加载的数据(可见即可得)
-2,实现模拟登录
如何捕获动态加载的数据
-以药监总局为例
selenium缺点
-效率低,网速慢就废了
动作链:
-一系列连续的动作(滑动动作)
若通过find定位进行在iframe下面的标签,则会定位失败
-解决方案:使用switch_to
-bro.switch_to.frame(‘iframeResult’)
div_tag=bro.find_element_by_xpath(’//*[@id=“draggable”]’)
print(div_tag)
有的网站会检测会检测请求是否为selenium发起
-规避检测的方法:使用浏览器接管
-1,打开谷歌驱动程序的目录找到,添加到环境变量中
-2,打开cmd输入

  • chrome.exe --remote-debugging-port=9222 --user-data-dir=“C:\selenium\AutomationProfile”(空文件夹的目录)
    -3,执行如下代码,可以使用下属代码接管步骤2打开的真实的浏览器
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    chrome_options=Options()
    chrome_options.add_experimental_option(“debuggerAddress”,“127.0.0.1:9222”)
    #本机的谷歌驱动程序路径
    chrome_driver="(chromedriver的存放路径)"
    driver=webdriver.Chrome(executable_path=chrome_driver,chrome_options=chrome_options)
    print(driver.title)
    无头浏览器(无可视化界面的浏览器):速度比可视化界面更快
    -谷歌
    -phantomJs(已经停止更新)

JS解密+混淆破解(火狐浏览器)
-爬取网站https://www.aqistudy.cn/html/city_detail.html(数据不解释,但还可以爬)
-1,修改查询条件,点击查询按钮,捕获点击按钮后发起请求对应的数据包(点击查询发起的是ajax请求,该请求就会将指定查询条件加载对应的数据)
-2,从XHR中找出Ajax的url,请求方式post还是get和请求参数data(若为d且一堆数据,则响应数据为动态数据且为密文加密)
-3.将捕捉到的密文数据解密
爬虫知识2/22_第1张图片火狐浏览器
-4从getdata函数实现中找寻ajax请求对应的代码,点击click行右边的箭头(在该函数的实现中没找到ajax代码,但是发现了另外两个函数的调用)
-ajax代码的实现一定存在这两个函数内部
-type==HOUR :查询事件以小时为单位
-5 再进一步分析发现这两个方法都调用了 getServerData() 这个方法,并传递了 method、param 等参数,然后还有一个回调函数很明显是对返回数据进行处理的,这说明 Ajax 请求就是由这个 getServerData()方法发起
爬虫知识2/22_第2张图片
爬虫知识2/22_第3张图片
-6,分析getserverdata,找寻ajax代码(全局搜索从network的ctrl+F找),再点response,找到为加密的内容
爬虫知识2/22_第4张图片
-7,如何对etserverdata加密的内容实现解密?
-js混淆:对核心的js代码进行加密
-js反混淆:对js加密的代码进行解密
-暴力破解:
这里提供一个:http://www.bm8.com.cn/jsConfusion/。我们可以将getServerData存在的这行数据粘贴到反混淆的网站中。
爬虫知识2/22_第5张图片
-data:加密的响应数据
-param:动态变化且加密的请求参数
-decodeData(data)将加密的数据进行解密
-decodeData(method,object)返回动态变化的请求参数
-发现method是固定形式字符串,object就是param是一个字典,里面存储了三组键值对city表示查询城市名称,startTime和endTime为查询起止时间,type表示为HOUR:params为查询参数(method=’GETCITYWEATHER‘or’GETDETAIL’
params={city,type,startTime,endTime})
-8,js逆向
-现在只需要调用两个js函数decodeData/decodeData返回结果即可
-再python如何调用js函数
-方式1:手动把js函数改写成python函数
-方式2:使用固定模块实现自动你想(逆向)
-借助PyExecJS 库来实现模拟JavaScript代码执行获取动态加密的请求参数,然后再将加密的响应数据带入decodeData进行解密即可!
-pip install PyExecJS
-在本机安装好nodejs的环境
1, 将反混淆网站中的代码粘贴到jsCode.js文件中
2,在该js文件中添加一个自定义函数getPostParamCode,该函数是为了获取且返回post请求的动态加密参数
function getPostParamCode(method, city, type, startTime, endTime){
var param = {};
param.city = city;
param.type = type;
param.startTime = startTime;
param.endTime = endTime;
return getParam(method, param);
}

  • 3.在py源文件中可以基于PyExecJS模拟执行步骤2中定义好的自定义函数,获取动态加密参数params:
  • 下面为代码------
  • #基于该模块执行getParam返回动态变化的请求参数
    import execjs
    #实例化node对象
    node = execjs.get()

Params

method = ‘GETCITYWEATHER’
city = ‘北京’
type = ‘HOUR’
start_time = ‘2018-01-25 00:00:00’
end_time = ‘2018-01-25 23:00:00’

Compile javascript

#先创建一个文件jsCode.js,存放需要存放解密的js函数数据,compile进行编译
file = ‘jsCode.js’
ctx = node.compile(open(file,encoding=‘utf-8’).read())

Get params,调用jsCode中指定的getPostParamCode函数调用,01234为传参,传回params为动态变化的加密请求参数,用eval执行函数

js = ‘getPostParamCode("{0}", “{1}”, “{2}”, “{3}”, “{4}”)’.format(method, city, type, start_time, end_time)
params = ctx.eval(js)
print(params)

4.接着我们用 requests 库来模拟 POST 请求,获取加密的响应参数 
#发起post请求
url = ‘https://www.aqistudy.cn/apinew/aqistudyapi.php’
data={
‘d’:params
}
response_text = requests.post(url, data=data).text
print(response_text)
-5,用decodeData() 方法即可实现解密,返回解密后的原文数据
js = ‘decodeData("{0}")’.format(response_text)
decrypted_data = ctx.eval(js)
print(decrypted_data)
-我们可以把JS混淆归结为三类,分别是 eval类型,hash类型,压缩类型。而压缩类型,是目前前端性能优化的常用工具,以uglify为代表。
eval对应的解混淆工具, 随便百度都可以搜索到,如jspacker
JSA对应的解混淆工具unjsa
javascript-obfuscator对应的解混淆工具crack.js
————————————————————————————————————
初学者:requests爬取网页+bs4解析网页爬取页面源码的数据,用Selenium获取动态网页,用csv存储网页
老手:scrapy框架(使用与异步爬虫的框架)
(一scrapy基本使用:
-1,scrapy startproject ProName创建项目
-spiders:爬虫文件夹
-必须存放一个爬虫源文件
-setting.py:工程的配置文件
-cd ProName
-2,创建爬虫源文件
-crapy genspider spiderName www.xxx.com
-编写对应的代码
-3,执行工程
-scrapy crawl spiderName
-执行工程后,默认输出工程所有日志
-指定类型日志的输出
-setting.py加上:
- LOG_LEVEL=‘ERROR’(只输出错误的日志)
- UA也可伪装
-4,补充说明
-#name为爬虫文件名称,当前源文件的唯一标识
-#url为起始的url列表,只可以存url,该列表存的url都会被get请求发送,若域名允许为百度,则不能打开sougou的url
- #allow为允许的域名
- #parse方法调用取决于请求的次数,parse方法为请求后的数据解析操作
-#reponse表示的就是服务器返回的响应对象
-#setting.py中
-1,禁止robot
-2,指定日志伪装:LOG_LEVEL=‘ERROR’
-3,UA伪装
(二scrapy数据解析
发现:
(1)对于Selector类型的对象,并不能使用extract_first()方法,而使用get()可以。get() 、getall() 是新版本的方法,extract() 、extract_first()是旧版本的方法。前者更好用,取不到就返回None,后者取不到就raise一个错误。
(2) get() == extract_first()
返回的是一个list,里面包含了多个string,如果只有一个string,则返回[‘我很孤独’]这样的形式
getall() == extract()
返回的是string,list里面第一个string
(3)
-使用:response.xpath(’xpath表达式‘)
-scrapy封装的xpath和etree中的xpath区别:
-scrapy中的xpath直接将定位到的标签中存储的值或属性值取出,返回selector对象,需要用get/extract取出字符串数据
(三持久化存储
-基于终端指令的持久化存储
- scrapy crawl 爬虫名称 -o xxx.json
scrapy crawl 爬虫名称 -o xxx.xml
scrapy crawl 爬虫名称 -o xxx.csv
-要求:该种方式只可以将parse方法的返回值存储到本地指定后缀的文本文件中
def parse(self, response):
#数据解析名称和内容
li_list=response.xpath(’//*[@id=“list”]/ul/li’)
all_data=[]
for li in li_list:
title = li.xpath(’./div[2]/a/text()’)[0].get()
content=li.xpath(’./div[1]/text()’)[0].get()
dic={
‘title’:title,
‘content’:content
}
all_data.append(dic)
return all_data
-基于管道的持久化存储(重点)
-1,在爬虫文件中进行数据解析
-2,在items.py中定义相关属性
-步骤1中解析出了几个字段的数据,在此就定义几个属性
class WangziproItem(scrapy.Item):
title=scrapy.Field()
content=scrapy.Field()
-3,在爬虫文件中将解析到的数据存储封装到item类型的对象中
item=WangziproItem()
#不可以通过.形式调用属性
item[‘title’]=title
item[‘content’]=content
-4,将item类型对象提交给管道
yield item
-5,在管道文件(pipelines.py)中,接受爬虫文件提交过来的item类型对象,进行任意形式的持久化存储操作
class WangziproPipeline:
#该方法用来接收item对象,一次只能接受一次item,说明会被调用多次
#参数item:就是接收到的item对象
def process_item(self, item, spider):
print(item)#item就是一个字典
return item

	-6,在配置文件中开启管道机制
		setting中
		ITEM_PIPELINES = {
		#300表示管道的优先级,越小优先级越高
		'wangzipro.pipelines.WangziproPipeline': 300,
		}
	-7 补充管道内部内容

class WangziproPipeline:
fp=None
#重写父类的两个方法
def open_spider(self,spider):
print(‘我是open_spider(),我只会在爬虫开始的时候执行一次!’)
self.fp=open(‘duanzi.txt’,‘w’,encoding=‘utf-8’)
def close_spider(self,spider):
print(‘我是close_spider(),我只会在爬虫结束的时候执行一次!’)
self.fp.close()
#该方法用来接收item对象,一次只能接受一次item,说明会被调用多次
#参数item:就是接收到的item对象
def process_item(self, item, spider):
#print(item)#item就是一个字典
#将item存储到文本文件
self.fp.write(item[‘title’]+’:’+item[‘content’]+’\n’)
return item
-基于管道实现数据的备份
-将爬取到的数据分别存储到不同的载体
-实现:将数据一份存储到mysql,一份存储到redis
-问题:管道文件中的一个管道类表示怎么样的一组操作呢?
-一个管道类对应一种形式的持久化存储操作,若将数据存到不同的载体就需要多个管道类
-已经定义好三个管道类,将数据写入三个导体中存储:
-item会不会依次提交给三个管道类
-不会,爬虫文件中的item只会被提交给优先级最高的管道类
-优先级高的管道类需要在process_item中实现return item,就item传递给下一个即将被执行管道类
-scrapy的手动请求发送实现的全站数据爬取
-yield scrapy.Request(url=new_url,callback=self.parse):get请求
-callback指定解析函数,用于解析数据
-yield scrapy.FormRequest(url,callback,formdata): post请求
-formdata:字典,请求参数
-为什么start_urls列表中的url会自动进行get请求的发送?
-因为列表中的url其实是被start_request这个父类方法发起的请求发送(遍历列表)
def start_requests(self):
for u in self.start_urls:
yield scrapy.Reqeusts(url=u,callback=self.parse)
-如何将start_urls中的url默认进行post请求的发送?
-重写start_request方法即可
def start_requests(self):
for u in self.start_urls:
yield scrapy.FormReqeusts(url=u,callback=self.parse)
-scrapy一般用于发送get请求
——————————————————————————
一般动态加载的数据用request去爬,不用scrapy,scrapy用来爬静态的数据
——————————scrapy五大部件作用
-spider:数据解析,url获取
-twisted在下载器中体现异步下载
-互联网返回给下载器的是response
-调度器分为:过滤器和队列
-item封装好由spider给引擎,引擎给管道
-引擎:接受数据流,触发事物
-管道:持久性储存
请求传参的深度爬取:
-深度爬取:爬取的数据没有在同一张页面中(首页数据+详情页数据)
-在scrapy中无请求传参无法实现持久化存储数据
-实现方式:
-scrapy.Request(url,callback,meta)
-meta是一个字典,可以将meta传递给callback
-callback取出meta:
-item=response.meta[‘item’]
————————中间件作用:批量拦截请求响应
-(1)爬虫中间件(不经过调度器)
-(2)下载中间件(推荐)
-(1拦截请求:
-【1篡改请求url
-【2伪装请求头信息
-UA
-Cookie
-【3设置请求代理(重点)
-(2拦截响应:
-篡改响应数据
-需求:需要爬取网易新闻中的新闻数据(标题和内容)
-1,通过网页新闻的首页解析出五大板块对应的详情页url(无动态加载)
-2,每一块板块对应的新闻标题都是动态加载出来的(动态加载)
-3,通过解析出每一条新闻详情页对应的页面源码,解析出新闻内容(动态数据通过中间件selenium获取)
-(3代理操作必须使用中间件才可以实现
#拦截异常的请求,参数:requests拦截到的发生异常的请求,
#作用:想要将异常的请求修正,对其进行重新发送
def process_exception(self, request, exception, spider):
#若ip被封,请求就会变得一个异常的请求
#设置代理
request.meta[‘proxy’]=‘http://ip:port’
return request#将异常的请求修正后重新发送
——————————大文件下载(图片):大文件数据是在管道中请求到的(img.Pro)
-下属管道类是scrapy封装好的我们直接用
-from scrapy.pipelines.images import ImagesPipeline #scapy提供了下载功能
-重写管道类三个方法
#get_media为根据图片地址item【src】发起请求
① def get_media_requests(self,item,info):
yield scrapy.Request(item[‘src’],meta={‘item’:item})
#指定存储图片的地址,只要返回图片名称就可以
②def file_path(self,request,response=None,info=None):
item=request.meta[‘item’]
filePath=item[‘name’]
return filePath#只需要返回图片名称1
#将item传给下一个即将被执行的管道类
③ def item_completed(self,results,item,info):
return item
-在配置文件中添加:
-IMAGES_STORE=‘dirName’
——————————setting.py中的常用配置
-增加并发
-默认scrapy开启线程为32个,可适当增加。在setting的concurrent——requests
-降低日志级别
-运行scrapy会有日志的输出,可设置减少日志输出LOG_LEVEL=‘ERROR’
-禁止cookie
-若不需要cookie,scrapy一般不用cookie,减少使用cookie则降低cpu使用率,cookie_enabled=false
-禁止重试
-中间件会修正重新发送请求,请求重试降低爬取速度。RETRY_ENABLED=False
-减少下载超时
-如果对一个非常慢的链接进行爬取,减少下载超时可让能卡住的链接快速被放弃,从而提升效率。DOWNLOAD_TIMEOUT=10,超时时间为10s
————————
CrawlSpider(全站数据爬取)
-其实是spider的一个子类,spider是爬虫文件中爬虫类的父类
-作用:被作用于专业实现全站数据爬取
-将一个页面下所有页码对应的数据进行爬取
-使用流程:
-1,创建一个机遇crawlspider的一个爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com
-2,构建链接提取器和规则解析器
-链接提取器:
-作用:根据指定规则进行指定链接的提取
-提取的规则:allow=‘正则表达式’
-规则解析器:
-作用:获取链接提取器提取到的链接,根据指定规则对请求到的页面源码数据进行数据解析
-fllow:true,将链接提取器继续作用到到所提取的页面链接
-链接提取器和规则提取器也是一对一的关系
-想取得当前网站的所有链接,link=LinkExtaractor(allow=r’’)-----link内为空
——————————
-分布式
-(效率高,但环境难搭建)什么是分布式爬虫?(1)
机遇多台电脑组件一个分布式机群,然后让机群中的每一台电脑执行同一组程序,然他们对同一个网站的数据进行分部爬取
-为什么要使用分布式爬虫?(2)
提升爬取数据的效率
-如何实现分布式爬虫?(3)
基于scrapy+redis的形式实现分布式·
-scrapy结合这scrapy-redis组建实现的分布式
-原生的scapy框架是无法实现分布式的?(4)
-调度器无法被分布式机群共享
-管道无法共享
-scrapy-redis组件的作用(5)
-提供可以被共享的调度器和管道
-环境安装(6)
-redis
-pip install scrapy-redis
-编码流程(7)
-创建一个工程①scrapy startproject fbsPro
cd fbsPro
scrapy genspider -t crawl fbs www.xxx.com
-创建一个爬虫文件:基于crawlSpider的爬虫文件②
-修改当前的爬虫文件,
- 导包:
-fbs.py
from scrapyg_redis.spiders importc RedisCrawlSpider,ReddisSpider
-将当前爬虫类的父类修改成RedisCrawlSpider
-fbs,py
class FbsSpider(RedisCrawlSpider)
-将start_url替换成redis_key=‘xxx’,xxx表示可被共享调度器中队列的名称
#redis_key表示的是可悲共享调度器中队列的名称
redis_key=‘fbsQueue’
-fbs.py
from fbsPro.items import FbsproItem
rules=(
Rule(LinkExtractor(allow=r’type=4&page=\d+’),callback=‘parse_item’,folloiw=True,

def parse_item(self,response):
tr_list=…
for tr in tr_trlist:
title=…
status=…
item=FbsproItem()
item=[‘title’]=title
item[‘status’]=status
item[‘num’]=num
yield item
-items.py
calss FbsproItem()
title=scrapy.Field()
status=scrapy.Field()
-setting.py
#开启可被共享的管道
ITEM_PIPELINES={
‘scrapy_redis.pipelines.RedisPipeline’:400

#指定使用可被共享的调度器(过滤器)
#增加一个去重容器类的配置,作用使用Redis的set合集来存储请求的指纹数据,从而实现请求去重的持久化
DUPEFILTER_CLASS=“scrapy_redis.dupefilter.RFPDupeFilter”
#使用scrapy-redis组件自己的调度器
SCHEDULER=“scrapy_redis.scheduler.Scheduler”
#配置调度器是否要持久化,也就是当爬虫结束了,要不要清空redis中请求队列和去重指纹的set。如果是TRUE,则表示持久化
SCHEDULER_PERSIST=True
-③对setting进行设置:
-指定管道
-指定调度器
-指定redis的服务
REDIS_HOST=‘redis服务的ip地址’ //本机ip地址
REDIS_PORT=6379
-④redis的配置文件进行配置:redis.windows.conf
#关掉默认绑定
#bind 127.0.0.1
#关闭保护模式,开了后只能读
protected-mode no
-⑤携带配置文件启动redis服务
-在当前目录打开Powershell窗口
-redis-server
-./redis-server redis.windows.conf
-⑥启动redis的客户端
-在当前目录打开Powershell窗口
-redis-cli
-⑦执行当前的工:(进入到等待状态)
-setting.py
CONCURRENT_REQUESTS=2
-进入到爬虫文件对应的目录中(进入到spiders文件当前
-scrapy runspider fbs,py
-⑧向调度器windows PowerShell r扔入一个起始的url:(仍入url就开始爬取)
-队列在哪里呢?
答:队列在redis中
-lpush fbsQueue www.xxx.com
#爬完后输入key *显示存的数据,其中fbs:requests为查询对象
#看存储的items,0到-1
lrange fbs:items 0 -1
#flushall为清空所有数据
#llen fbs:items为看items爬取有多少条
-⑨限制条件:各电脑之间为局域网内网,每一个分布式雇佣一个路由器
————————————————————————__————————————_----
增量式爬虫:
-概念:检测网站数据更新的情况
-核心:去重!!!
-实战中去重的方式:记录表
-记录表中记录什么?记录爬取过的相关信息
-爬取过的相关信息:每一部电影详情页的url,作为唯一标识,称为数据指纹
-去重的方式:
-python中的set集合(不可以)
-set集合无法持久化存储
-redis中的set可以持久化存储
-将爬取到网页url存储到redis的set数据结构中(sadd name xxx,返回1表示不存在,返回0表示爬过)
-开始
scrapy startproject zlsPro
cd zlsPro
scrapy startproject genspider -t crawl zls www.xxx.com
setting.py改三个:UA/log_level/君子协议
-指定起始url
-基于crawlspider获取其他页码链接
-基于rule将其他页码链接进行请求
-从每一个页码对应的页面源码中解析出每一个电影详情页的url
-核心:检测电影详情页的url有没有请求过,将没爬过的电影详情页的url存储到redis的set数据结构
-对详情页的url发起请求,解析电影的名称和简介,封装到item提交到管道
-在管道里把名字和简介存到数据库里持久化存储
——————————————————
爬虫高级课程(爬虫的js加密处理+js算法改写分析)
-涉及到的相关内容
线性散列Md5算法
对称加密DES/AES算法
非对称加密算法RSA
base64伪加密
https证书秘匙加密
-可以处理的爬虫问题
模拟登录中密码加密和其他请求参数加密处理
动态加载且加密数据的捕获和破解
重点:找到js算法加密和解密相关流程的编码关于处理套路/技巧,大幅度提升处理相关问题的效率
-常见的加密算法分类
-线性散列Md5算法
定义:可以产生128位的散列值,且MD5加密后产生得事一个固定长度(32位或16位)的数据
思路:暴力破解,通过用很多数据跟已有的数据对比寻找规律,理论上数据量够庞大MD5是可以破解的,但需要注意MD5是需要考虑破解的成本。
方法:①使用一段无意义的且随机的私匙进行MD5加密生成一个加密串,暂且称为串1
②将要加密的数据跟串1拼接,再进行MD5加密,生成串2
③将串2再进行MD5加密,生成的串3就是我们加密后的数据
附加:我们注册账号时的密码都是用MD5加密
-对称加密DES/AES算法
定义:DES为数据加密标准,是一种使用密匙加密的算法,加密方式是对称加密,其加密运算/解密运算需要使用的是同样的密匙(一组字符串)即可
注意:
现在用AES 这个标准代替原先的DES
AES和DES的区别:
加密后密文长度不同:
DES加密后密文长度是8的整数倍
AES加密后密文长度是16的整数倍
应用场景不同:
企业级开发用DES足够安全
如果要求高使用AES
DES和AES切换只需要修改CrytoJS.AES<=>CryptoJS.DES
使用DES/AES进行数据交互是要求双方都拥有相同的私匙
破解方法:
暴力破解
DES如果使用56位的密匙,可能的密匙数量是2的56次方个。只要计算足够强大是可以暴力破解
DES算法的入口参数有三个:
key/data/mode/padding:
key为7个字节共56位,是DES算法的工作密匙;
Data为8个字节64位,是要被加密或被解密的数据
Mode位DES的工作方式,有解密或加密
padding为填充模式,如果加密后密文长度如果达不到指定整数倍(8个字节,16个字节),填充相应字符
padding的赋值固定为CryptoJS.pad.Pkcs7即可
-非对称加密算法RSA
RSA加密:
定义:非对称加密算法(两个密匙),再公开密匙加密和电子商业中广泛使用
详解:(RSA需要两个密匙)
公开密匙publickey
私有密匙privatekey
注意:
使用都是公开密匙加密,私有密匙解密。私有钥匙自己保留
算法复杂,使得加密解密速度没有对称加密解密的快
私有钥匙是通过共有钥匙计算生成。
公开钥匙生成方式:
公私匙可以在线生成:
http://web.chacuo.net/netrsakeypair
-base64伪加密
base64是一种用64个字符来表示任意二进制数据的方法。base64是一种编码方式而不是加密算法。只是看上去像是加密而已。
base64使用A-Z,a-z,0-9,+,/这64个字符实现对数据进行加密

你可能感兴趣的:(爬虫笔记,python)