关于scrapy流程的总结分析

自己总结的一些分析,可能比较散乱,凑合看下,有遗漏的请指教

以爬虫为起点:
1.爬虫提取start_url(列表或元组)的地址,
组装成request对象,给爬虫中间件,然后发送给引擎
由引擎传递给调度器
2.调度器从请求队列中提取request发送给引擎,
request通过引擎传递下载器中间件,再给下载器
3.下载器通过发送request,获得响应,响应再通过下载器中间件处理以后,
发送给引擎,引擎再给爬虫中间件,最后到爬虫这里
4.爬虫给提取数据,再发item或者重新生成请求,都发给引擎,item由引擎给管道,request由爬虫中间件处理后给引擎再给调度器如此循环
5管道这边收到item之后进行存储

Scrapy 使用了Twisted[‘twɪstɪd]异步网络框架,可以加快我们的下载速度。

scrapy项目实现流程
* 创建一个scrapy项目:scrapy startproject mySpider
* 生成一个爬虫:scrapy genspider baidu “baidu.com”
* 提取数据:完善spider,使用xpath等方法
* 保存数据:pipeline中保存数据

1.
命令:scrapy startproject +<项目名字>
示例:scrapy startproject myspider

2.
命令:scrapy genspider +<爬虫名字> + <允许爬取的域名>
示例:scrapy genspider baidu “baidu.com”

3.完善爬虫
注意:
1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
2. extract() 返回一个包含有字符串的列表
3. extract_first() 返回列表中的第一个字符串,列表为空没有返回None
4. spider中的parse方法必须有
5. 需要抓取的url地址必须属于allowed_domains,但是start_urls中的url地址没有这个限制
6. 启动爬虫的时候注意启动的位置,是在项目路径下启动
7. 解析以后yield能够传递的对象只能是 BaseItem,Request,dict,None

4.进行存储

pipeline在settings中能够开启多个,为什么需要开启多个?
* 不同的pipeline可以处理不同爬虫的数据
* 不同的pipeline能够进行不同的数据处理的操作,比如一个进行数据清洗,一个进行数据的保存

* 有多个pipeline的时候,process_item的方法必须return item,否则后一个pipeline取到的数据为None值
* pipeline中process_item的方法必须有,否则item没有办法接受和处理
* process_item方法接受item和spider,其中spider表示当前传递item过来的spider
* open_spider(spider) :能够在爬虫开启的时候执行一次
* close_spider(spider) :能够在爬虫关闭的时候执行一次

5.日志的设置
我们可以在setting中设置日志的等级
自行添加: LOG_LEVEL=”WARNING”

6.别忘记定义字段,设置item的类别,同时在settings里去启用自己写的管道类和一些中间件,同时配置setting的其他内容
下载超时问题
‘DOWNLOAD_TIMEOUT’: 25, # 下载超时,既可以是爬虫全局统一控制,也可以在具体请求中填入到Request.meta中,Request.meta[‘download_timeout’]

关于scrapy shell
* response.url:当前响应的url地址
* response.request.url:当前响应对应的请求的url地址
* response.headers:响应头
* response.body:响应体,也就是html代码,默认是byte类型
* response.requests.headers:当前响应的请求头

这里写图片描述
这里写图片描述

加代理的方式两种,重写start_request() yield Requrest(url,callback=self.parse,headers=headers,meta={“proxy”:”http://xxxxxxx“})
还一种写middlewares.py 定义一个类,在settings的中间件中开启,重写process_request()在Request.mata中进行设置
如果是带账号认证的,要在请求头中设置

base64_userpasswd = base64.b64encode(PROXIES_COUNT['user_passwd'])
request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd

创建crawlspdier爬虫的命令创建crawlspider命令
scrapy genspider -t crawl baidu baidu.com
模型例子

class BaiduSpdier(CrawlSpider):
    name= "baidu"
    allowed_domain=["baidu.com"]
    start_urls =["http://www.baidu.com"]

    rules=(
        Rule(LinkExtractor(allow=r"baidu/"),callback="parse_item",follow=True),
)

LinkExtractor:连接提取器,可以通过正则或者是xpath来进行url地址的匹配
follow 表示经过连接提取器提取的url地址对应的响应是否还会继续被rules中的规则提取
callback表示经过连接提取器提取的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数处理

这里写图片描述
这里写图片描述

关于下载件 Downloader Middlewares
一般重写process_request(self,request,spider)
这个方法去实现添加代理或者更换请求头user-agent
1.不做返回或者返回None继续请求,将请求给下载器
2.返回request,把request给调度器
3.返回response,把响应给引擎

只适合scrapy.spider
在scrapy.spider中模拟登陆 ,Resquest请求带cookies,或者用Post请求地址

在起始start_url中如果想带cookies,需要重写start_request方法,cookies不能直接直接放在headers中,要构造cookie字典

def start_requests(self):
    cookie_str = "cookie_str"
    cookie_dict = {i.split("=")[0]:i.split("=")[1] for i in cookie_str.split("; ")}
    yield scrapy.Request(
    self.start_urls[0],
    callback=self.parse,
    cookies=cookie_dict)
# headers={"Cookie":cookie_str}
三级页面想一次性爬完再进行存储的话
def funcA(self,response):
    item=Myitem()
    # 处理列表数据
    yield Request(url,callback=funcB,meta={"item":item})
def funcb(self, response):
    # 处理新闻详情页的数据
    item=response.meta["item"]
    yield Request(url,callback=funcC,meta={"item":item})
def funcCself,response):
    item = response.meta['item']
    #处理新闻解说页的数据
    return item

不用cookie,模拟登陆,发post请求
思路,
1.找到Post请求地址,
2.点击登陆的时候进行抓包,定位url地址
3.找到请求体的规律,其中包含的参数,在前一次的响应中
验证登陆,使用回调函数去解析,查找是否能匹配登陆后的内容

yield scrapy.FormRequest(
"https://github.com/session",
formdata={
"authenticity_token":authenticity_token,
"utf8":utf8,
"commit":commit,
"login":"noobpythoner",
"password":"***"
},
callback=self.parse_login

还有一种方法,能自动寻找action对应的url地址,不用去找url

def parse(self, response):
yield scrapy.FormRequest.from_response(
response,#自动的从中寻找action对应的url地址
formdata={
"login":"noobpythoner",
"password":"***"
},
callback = self.parse_login
)

关于代理ip的检测,
在中间件中重写 process_response(self,request,response)

class ProxyMiddleware(object):
def process_response(self, request, response, spider):
if response.status != 200 and response.status != 302:
return request

scrapy_redis的原理分析
在原先的基础上增加了redis这个组件,原先的请求队列是放在scheduler中,现在有了redis,将scheduler的请求队列放入redis中,同时利用hsahlib的sha1()去生成指纹,指纹是由url加请求体组成的
原先通过管道存入本地或者数据库的item,现在存入redis,就是说redis现在包含了三个,请求队列,指纹,item。
如何进行去重判断?
对请求进行去重,然后item就变成唯一性,所以数据唯一,实现了基于url地址的增量爬取

* request之前没有见过
* request的dont_filter为True,即不过滤
* start_urls中的url地址会入队,因为他们默认是不过滤

关于分布式爬虫,爬虫继承RedisSpider这个类,start_url 更换成 redis_key, redis_key一般设为 “myspider:start_url”,这个主要是充当redis里面的键,让程序运行时,往redis库里传url启动爬取网址就可以了
因为是分布式爬取,所以不可能指定多个start_url去爬取一样的网址,所以更换了redis_key。
启动分两步 第一步让爬虫就绪 scrapy crawl myspider(爬虫名)
第二步 在redis设置键值 lpush myspider:start_url + 爬取的网址 存入队列
爬虫开始

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值