Scrapy框架学习(五)—-Request、Response介绍及模拟GitHub登录
Scrapy
使用Request
和Request
对象爬取web
站点。
一般来说,Request
对象在spider
中被生成并且最终传递到下载器(Downloader
),下载器对其进行处理并返回一个Response
对象,Response
对象还会返回到生成request
的spider
中。
所有Request
和Response
的子类都会实现一些在基类中非必要的功能。它们会在Request subclasses
和 Response subclasses
两部分进行详细的说明。
Request对象
一个Request
对象代表一个HTTP请求,一般来讲,HTTP请求是由Spider
产生并被Downloader
处理进而生成一个Response
。
Request的构造方法:
class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback])
url(string)
:请求的urlcallback(callable)
:处理响应数据的回调方法,用来解析响应数据,如果没有指定,则spider的parse方法。如果在处理期间引发异常,则会调用errback。method(string)
:HTTP的请求方法。默认GET。meta(dict)
:Request.meta
属性的初始值。一旦此参数被设置,通过参数传递的字典将会被浅拷贝。body
:请求体。headers(dict)
:请求头。cookies(dict)
:cookieencoding(string)
:编码方式,默认utf-8。priority(int)
:优先级,调度程序使用优先级来定义用于处理请求的顺序。具有较高优先级值的请求将会提前执行。默认0。dont_filter(boolean)
:请求不应该被调度器过滤。False
表示过滤,True
表示不过滤。默认False
。errback(callable)
:如果在处理请求时引发异常,将会调用该函数。 这包括404 HTTP错误等失败的页面。
Request.meta
Request.meta
在不同的请求之间传递数据使用的
Request.meta
属性可以包含任意的数据,但是Scrapy
和它的内置扩展可以识别一些特殊的键。
- dont_redirect:不重定向
- dont_retry:不重试
- handle_httpstatus_list
- dont_merge_cookies:不合并cookie
- cookiejar:使用cookiejar
- redirect_urls:重定向连接
- bindaddress:绑定ip地址
- dont_obey_robotstxt:不遵循反爬虫协议
- download_timeout:下载超时
Request的子类FormRequest
FormRequest是Request的子类,一般用作表单数据提交。
FormRequest的构造:
class scrapy.http.FormRequest(url[,formdata,...])
FormRequest类除了有Request的功能,还提供一个form_response()
方法:
form_response(response[,formname=None,formnumber=0,formdata=None,formxpath=None,clickdata=None,dont_click=False,...])
response
:是指包含HTML表单的Response对象,该表单将用于预填充表单字段。formname
:如果给定,将使用设置为该值的name属性的表单。formnumber
:当响应包含多个表单时,要使用的表单的数量。 formnumber默认是0,表示使用第一个。formdata
:字段来覆盖表单数据。如果一个字段已经存在于响应<form>
元素中,那么它的值被在这个参数中传递的值覆盖。formxpath
:如果给定,将使用与XPath匹配的第一个表单。clickdata
:查找单击控件的属性。如果没有给出,表单数据将被提交模拟点击第一个可点击的元素。dont_click
:如果为True,表单数据将被提交而不需要单击任何元素。
Response对象
HTTP请求返回的响应对象,它通常被下载(由Downloader)下载并被传送给Spider进行处理。
class scrapy.http.Response(url[,status=200,headers,body,flags])
url:响应对象response的url
headers:响应对象的响应报头
status:响应的状态码,默认200。
body:响应体
meta:为response.meta属性的初始值。如果给定的,字典将浅复制。
flags:是一个列表包含的response.flags初始值的属性。如果给定,列表将被浅拷贝。
Response的子类
- TextResponse
class scrapy.http.TextResponse(url[,encoding[,...]])
TextResponse
对象增加了编码能力的基础响应类,是指将只用于二进制数据,如图像、声音或任何媒体文件。
TextResponse
对象除了标准的Response对象外,还支持以下属性和方法:
encoding
与此响应编码的字符串。 通过尝试以下机制来解决编码问题:
在构造函数编码参数中传递的编码
在Content-Type HTTP头中声明的编码。如果这种编码是无效的(即未知的),它将被忽略,并尝试下一个解析机制。
在响应正文中声明的编码。TextResponse类不提供任何特殊的功能。但是,HtmlResponse和XmlResponse类可以。
通过查看响应主体来推断编码。 这是更脆弱的方法,但也是最后一个尝试。
selector
:使用响应作为目标的选择器实例。body_as_unicode()
:以unicode形式返回响应的主体。xpath(query)
:xpath解析textresponse.selector.xpath('//p') 也可以简写为: textresponse.xpath('//p')
css(query)
:css解析,相当于BeautifulSoup4解析textresponse.selector.css('p') 也可以简写为: textresponse.css('p')
- HtmlResponse
HtmlResponse
类是TextResponse
的一个子类,它通过查看HTML meta http-equiv
属性来添加编码自动发现支持。
- XmlResponse
XmlResponse
类是TextResponse
的一个子类,它通过查看XML
声明行来添加编码自动发现支持。
FormRequest.from_response()模拟用户登录,以Github网站为例
代码如下:
from scrapy import Spider, Request, FormRequest
class GithubLoginSpider(Spider):
name = "github"
allow_domains = ['github.com']
# post登入的必须要的头字段
post_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36",
"Referer": "https://github.com/",
}
def start_requests(self):
"""
执行spider,开始请求
:return: 返回一个Request对象,请求登录的页面
"""
return [Request(url='https://github.com/login', meta={'cookiejar': 1}, callback=self.post_login)]
def post_login(self, response):
"""
登录的页面请求成功后,解析响应的页面,获取登录需要的<input>标签的信息
:param response: 登录接口返回的页面
:return:
"""
# 解析GitHub登入上传必要的字段
utf8 = response.xpath('//form// input[@name="utf8"]/@value').extract()[0]
authenticity_token = response.xpath("//form//input[@name='authenticity_token']/@value").extract()[0]
login = "xxxxxx"
password = "xxxxxx"
commit = response.xpath("//form//input[@name='commit']/@value").extract()[0]
print("utf8: " + utf8)
print("authenticity_token: " + authenticity_token)
print("commit: " + commit)
# 发送FormRequest表单请求
return FormRequest.from_response(response=response,
meta={'cookiejar': response.meta['cookiejar']},
headers=self.post_headers,
formdata={
"utf8": utf8,
"authenticity_token": authenticity_token,
"login": login,
"password": password,
"commit": commit
},
callback=self.after_login)
def after_login(self, response):
"""
form表单请求成功后,请求登入我的页面
:param response:
:return: 返回一个响应
"""
if response.status == 200:
return Request("https://github.com/zhang3550545",
meta={'cookiejar': response.meta['cookiejar']},
callback=self.parse_page)
def parse_page(self, response):
"""
将响应的我的页面数据,写入文件
:param response:
:return:
"""
if response.status == 200:
with open('my_account.html', 'wb')as f:
f.write(response.body)
在settings.py
页面把Cookie开关打开,且设置成True,如:
COOKIES_ENABLED = True
执行爬虫命令:
scrapy crawl github