Scrapy框架进阶之start_requests重写
start_rquests重写
- scrapy中start_url是通过start_requests来进行处理的,
- 其实现代码如下
def start_requests(self):
cls = self.__class__
if method_is_overridden(cls, Spider, 'make_requests_from_url'):
warnings.warn(
"Spider.make_requests_from_url method is deprecated; it "
"won't be called in future Scrapy releases. Please "
"override Spider.start_requests method instead (see %s.%s)." % (
cls.__module__, cls.__name__
),
)
for url in self.start_urls:
yield self.make_requests_from_url(url)
else:
for url in self.start_urls:
yield Request(url, dont_filter=True)
- 有些时候
- 需要重写starte_rquests方法发起首次请求
import scrapy
class N17kSpider(scrapy.Spider):
name = "n_17k"
start_urls = ["https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919"]
def start_requests(self):
'''
请求登陆的账号和密码
'''
login_url = 'https://passport.17k.com/ck/user/login'
# 使用request进行请求
# yield scrapy.Request(url=login_url, body='loginName=17346570232&password=xlg17346570232', callback=self.do_login, method='POST')
# 使用Request子类FormRequest进行请求 自动为post请求
yield scrapy.FormRequest(
url=login_url,
formdata={'loginName': '.....', 'password': '....'},
callback=self.do_start
)
def do_start(self, response):
'''
登陆成功后调用parse进行处理
cookie中间件会帮我们自动处理携带cookie
'''
for url in self.start_urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response, **kwargs):
with open("data.json", "w") as f:
f.write(response.text)
特别注意
-
关于 scrapy 中 COOKIES_ENABLED 设置
源码中 : 默认是注释掉的,但是可以有三种状态
【1】源码的 注释状态
# Disable cookies (enabled by default)
# COOKIES_ENABLED = False
- 这个状态下, 其实可以理解成 cookie 是开启的状态, 但是他的获取值 是通过源码的方法,scrapy直接获取网页的上层的cookie ,然后带到下一层去的。
【2】源码的 解开注释状态
# Disable cookies (enabled by default)
COOKIES_ENABLED = False
-
这个状态下的 cookie 是通过 headers 添加上去的(包裹在中间件头部里面)
-
scrapy 关闭 CookiesMiddleware 中间件,response 设置的 cookie 失效
-
使用 cookies 设置的 cookie 失效。
-
使用 headers 设置的 cookie 保留。
-
就是 setting源码中的
# Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #}
-
-
要是只是个别需要增加头部的,可以直接传参进去。 setting 写入时传全局的;
-
从这个里面去添加 cookie, token 等 一系列东西 。 或者 在请求的时候自己带上 ,源码里面 ,有 可以带的参数。
- headers 这个参数, 只是当前项目需要,可以在这里传
class Request(object_ref):
def __init__(self, url, callback=None, method='GET', headers=None, body=None,
cookies=None, meta=None, encoding='utf-8', priority=0,
dont_filter=False, errback=None, flags=None, cb_kwargs=None):
【3】源码的 解开注释状态并设置为True
# Disable cookies (enabled by default)
COOKIES_ENABLED = True
-
这种方法就是覆盖源码中的方法, 后面使用的是自己的cookie
- scrapy 启动 CookiesMiddleware 中间件,为请求自动添加服务器响应的 cookie
- 如果我们在 Request 中,使用 cookies 参数添加 cookie 时,
- 我们添加的 cookie 会额外加入到请求头中,如果响应有重名设置,则覆盖。(即,cookies 参数的cookie优先,但是 response 里的 cookie 也一个不少)
- 如果我们使用 headers 参数添加 cookie,
- headers添加的 cookie 会失效,被响应 cookie 完全覆盖。(即,headers里设置的 cookie 无效)
-
需要在请求的时候 带上 cookies= cookie
-
cookie 自己设置到 setting 或者 spider 里面都可以。
def start_requests(self): cookie = {} str_cookie = '你的cookie信息' str_cookie_items_list = str_cookie.split(';') for str_cookie_items in str_cookie_items_list: str_cookie_kw = str_cookie_items.split('=') cookie[str_cookie_kw[0].strip()] = str_cookie_kw[1].strip() yield scrapy.Request( url=self.start_urls[0], method='get', callback=self.parse, cookies=cookie ) def parse(self, response, **kwargs): print(response.text)
-
这个设置是 全局的设置 。 以后的请求都使用这个cookie 。
-
需要先声明他: cookie = '.......'
-
然后在请求的里面写上
yield scrapy.Request( href, callback=self.get_parse, cookies=cookie, meta={ 'name': name } )
-
【4】三种状态的使用场景
【4.1】每个请求需要自己的 cookie、 token:状态二
【4.2】全局可以使用一个cookie 的且只需要这个字段:状态三
【4.3】在全部的cookie基础上进行部分更改,用cookies参数调整 cookie 设置:状态三