持久化

步骤

pipeline/items
a. 先写pipeline类
class XXXPipeline(object):
def process_item(self, item, spider):
return item b. 写Item类
class XdbItem(scrapy.Item):
href = scrapy.Field()
title = scrapy.Field() c. 配置
ITEM_PIPELINES = {
'xdb.pipelines.XdbPipeline': 300,
} d. 爬虫,yield每执行一次,process_item就调用一次。 yield Item对象

编写pipeline

from scrapy.exceptions import DropItem

class FilePipeline(object):

	def __init__(self,path):
self.f = None
self.path = path @classmethod
def from_crawler(cls, crawler):
"""
初始化时候,用于创建pipeline对象
:param crawler:
:return:
"""
print('File.from_crawler')
path = crawler.settings.get('HREF_FILE_PATH')
return cls(path) def open_spider(self,spider):
"""
爬虫开始执行时,调用
:param spider:
:return:
"""
print('File.open_spider')
self.f = open(self.path,'a+') def process_item(self, item, spider):
# f = open('xx.log','a+')
# f.write(item['href']+'\n')
# f.close()
print('File',item['href'])
self.f.write(item['href']+'\n') # return item # 交给下一个pipeline的process_item方法
raise DropItem()# 后续的 pipeline的process_item方法不再执行 def close_spider(self,spider):
"""
爬虫关闭时,被调用
:param spider:
:return:
"""
print('File.close_spider')
self.f.close()

注意:pipeline是所有爬虫公用,如果想要给某个爬虫定制需要使用spider参数自己进行处理。 

去重规则

编写类

from scrapy.dupefilter import BaseDupeFilter
from scrapy.utils.request import request_fingerprint class XdbDupeFilter(BaseDupeFilter): def __init__(self):
self.visited_fd = set() @classmethod
def from_settings(cls, settings):
return cls() def request_seen(self, request):
fd = request_fingerprint(request=request)
if fd in self.visited_fd:
return True
self.visited_fd.add(fd) def open(self): # can return deferred
print('开始') def close(self, reason): # can return a deferred
print('结束') # def log(self, request, spider): # log that a request has been filtered
# print('日志')

配置  

# 修改默认的去重规则
# DUPEFILTER_CLASS = 'scrapy.dupefilter.RFPDupeFilter'
DUPEFILTER_CLASS = 'xdb.dupefilters.XdbDupeFilter'

爬虫使用 

class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['chouti.com']
start_urls = ['https://dig.chouti.com/'] def parse(self, response):
print(response.request.url)
# item_list = response.xpath('//div[@id="content-list"]/div[@class="item"]')
# for item in item_list:
# text = item.xpath('.//a/text()').extract_first()
# href = item.xpath('.//a/@href').extract_first() page_list = response.xpath('//div[@id="dig_lcpage"]//a/@href').extract()
for page in page_list:
from scrapy.http import Request
page = "https://dig.chouti.com" + page
# yield Request(url=page,callback=self.parse,dont_filter=False) # https://dig.chouti.com/all/hot/recent/2
yield Request(url=page,callback=self.parse,dont_filter=True) # https://dig.chouti.com/all/hot/recent/2 

注意:
- request_seen中编写正确逻辑
- dont_filter=False

深度

配置文件:
# 限制深度
DEPTH_LIMIT = 3

cookie

方式一:
- 携带
Request(
url='https://dig.chouti.com/login',
method='POST',
body="phone=8613121758648&password=woshiniba&oneMonth=1",# # body=urlencode({})"phone=8615131255555&password=12sdf32sdf&oneMonth=1"
cookies=self.cookie_dict,
headers={
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
callback=self.check_login
) - 解析:
cookie_dict
cookie_jar = CookieJar()
cookie_jar.extract_cookies(response, response.request) # 去对象中将cookie解析到字典
for k, v in cookie_jar._cookies.items():
for i, j in v.items():
for m, n in j.items():
cookie_dict[m] = n.value

start_url

内部原理

scrapy引擎来爬虫中取起始URL:
1. 调用start_requests并获取返回值
2. v = iter(返回值)
3.
req1 = 执行 v.__next__()
req2 = 执行 v.__next__()
req3 = 执行 v.__next__()
...
4. req全部放到调度器中  

编写 

class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['chouti.com']
start_urls = ['https://dig.chouti.com/']
cookie_dict = {} def start_requests(self):
# 方式一:
for url in self.start_urls:
yield Request(url=url)
# 方式二:
# req_list = []
# for url in self.start_urls:
# req_list.append(Request(url=url))
# return req_list 

定制:可以去redis获取 

深度和优先级

深度

- 最开始是0
- 每次yield时,会根据原来请求中的depth + 1
配置:DEPTH_LIMIT 深度控制

优先级

- 请求被下载的优先级 -= 深度 * 配置 DEPTH_PRIORITY
配置:DEPTH_PRIORITY

下载中间件

scrapy中设置代理

内置

在爬虫启动时,提前在os.envrion中设置代理即可。
class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['chouti.com']
start_urls = ['https://dig.chouti.com/']
cookie_dict = {} def start_requests(self):
import os
os.environ['HTTPS_PROXY'] = "http://root:woshiniba@192.168.11.11:9999/"
os.environ['HTTP_PROXY'] = '19.11.2.32',
for url in self.start_urls:
yield Request(url=url,callback=self.parse)

meta(每次发请求都要自己携带)

class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['chouti.com']
start_urls = ['https://dig.chouti.com/']
cookie_dict = {} def start_requests(self):
for url in self.start_urls:
yield Request(url=url,callback=self.parse,meta={'proxy':'"http://root:woshiniba@192.168.11.11:9999/"'})

自定义

import base64
import random
from six.moves.urllib.parse import unquote
try:
from urllib2 import _parse_proxy
except ImportError:
from urllib.request import _parse_proxy
from six.moves.urllib.parse import urlunparse
from scrapy.utils.python import to_bytes class XdbProxyMiddleware(object): def _basic_auth_header(self, username, password):
user_pass = to_bytes(
'%s:%s' % (unquote(username), unquote(password)),
encoding='latin-1')
return base64.b64encode(user_pass).strip() def process_request(self, request, spider):
PROXIES = [
"http://root:woshiniba@192.168.11.11:9999/",
"http://root:woshiniba@192.168.11.12:9999/",
"http://root:woshiniba@192.168.11.13:9999/",
"http://root:woshiniba@192.168.11.14:9999/",
"http://root:woshiniba@192.168.11.15:9999/",
"http://root:woshiniba@192.168.11.16:9999/",
]
url = random.choice(PROXIES) orig_type = ""
proxy_type, user, password, hostport = _parse_proxy(url)
proxy_url = urlunparse((proxy_type or orig_type, hostport, '', '', '', '')) if user:
creds = self._basic_auth_header(user, password)
else:
creds = None
request.meta['proxy'] = proxy_url
if creds:
request.headers['Proxy-Authorization'] = b'Basic ' + creds

scrapy框架 小知识的更多相关文章

  1. JS框架设计读书笔记之-小知识

    这一篇写一点小知识 JS中0.1+0.2为什么不等于0.3? 关于这个问题之前也很疑虑,老师也只是笼统的讲这是JS的语言问题,但是内部具体的情况却没有讲,看了书才发现原理如此简单. 简单来讲,计算机识 ...

  2. Python 爬取 北京市政府首都之窗信件列表-[Scrapy框架](2020年寒假小目标04)

    日期:2020.01.22 博客期:130 星期三 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作(本期博客) 2.爬取工作 3.数据处理 4.信息展 ...

  3. Scrapy框架简介及小项目应用

    今天来总结一下Scrapy框架的用法.scrapy的架构如下: Engine  :引擎,处理整个系统的数据流处理.触发事务,是整个框架的核心. Items :项目,它定义了爬取结果的数据结构,爬取的数 ...

  4. Scrapy框架爬虫

    一.sprapy爬虫框架 pip install pypiwin32 1) 创建爬虫框架 scrapy startproject Project # 创建爬虫项目 You can start your ...

  5. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  6. HTML+CSS中的一些小知识

    今天分享一些HTML.CSS的小知识,希望能够对大家有所帮助! 1.解决网页乱码的问题:最重要的是要保证各个环节的字符编码一致! (1)编辑器的编辑环境的字符集(默认字符集):Crtl+U 常见的编码 ...

  7. Scrapy框架使用—quotesbot 项目(学习记录一)

    一.Scrapy框架的安装及相关理论知识的学习可以参考:http://www.yiibai.com/scrapy/scrapy_environment.html 二.重点记录我学习使用scrapy框架 ...

  8. Python爬虫从入门到放弃(十一)之 Scrapy框架整体的一个了解

    这里是通过爬取伯乐在线的全部文章为例子,让自己先对scrapy进行一个整理的理解 该例子中的详细代码会放到我的github地址:https://github.com/pythonsite/spider ...

  9. 安装scrapy框架的常见问题及其解决方法

    下面小编讲一下自己在windows10安装及配置Scrapy中遇到的一些坑及其解决的方法,现在总结如下,希望对大家有所帮助. 常见问题一:pip版本需要升级 如果你的pip版本比较老,可能在安装的过程 ...

随机推荐

  1. 干净的 js测试页面

    <!DOCTYPE html><html lang="en" > <head> <meta charset="utf-8&quo ...

  2. HDOJ5883(欧拉路)

    The Best Path Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  3. ElasticSearch所使用的倒排索引的思想和使用场景

    背景: 在关系数据库系统里,索引是检索数据最有效率的方式,.但对于搜索引擎,它并不能满足其特殊要求: 1)海量数据:搜索引擎面对的是海量数据,像Google,百度这样大型的商业搜索引擎索引都是亿级甚至 ...

  4. [Java][Web]Response学习.缓存

    response.setHeader("expires", String.valueOf(System.currentTimeMillis() + 1000 * 3600)); S ...

  5. MapReduce启动的Map/Reduce子任务简要分析

      对于Hadoop来说,是通过在DataNode中启动Map/Reduce java进程的方式来实现分布式计算处理的,那么就从源码层简要分析一下hadoop中启动Map/Reduce任务的过程.   ...

  6. 学生党成功拿到阿里技术offer:面Java开发,却是C++考官,几个意思?

    摘要: 这是我为大家分享的如何拿到阿里技术offer系列文章中的第一篇,今天分享的文章的作者是一位在2015年阿里的校招中成功得到offer的美女学姐,从学姐的这篇文章中我们能学到很多在阿里面试的宝贵 ...

  7. 【BZOJ】1833: [ZJOI2010] count 数字计数(数位dp)

    题目 传送门:QWQ 分析 蒟蒻不会数位dp,又是现学的 用$ dp[i][j][k] $ 表示表示长度为i开头j的所有数字中k的个数 然后预处理出这个数组,再计算答案 代码 #include < ...

  8. 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...

  9. Java 编译???

    如果是在命令行下,编译就是 javac a.java 如果有错误,那么命令运行之后会显示错误 但是在eclipse下,我都是直接点击运行按钮的,如果有错误,在编程是就提示了,那么是怎么编译的呀 大的工 ...

  10. Ubuntu13.10:密码忘记了怎么办?

    重启ubuntu系统,开机时长按shift按键进入GRUB菜单,选择第二个高级模式. 新版的UBUNTU系统居然启用了GRUNB2.0的内核!虽然传说相当的牛X,但是用起来感觉就是非常看不清楚字体,要 ...