大数据 爬虫Python AI SqlPython爬虫作业程序员

Python爬虫Scrapy(七)_Request_Respon

2017-12-30  本文已影响222人  小七奇奇

本章将介绍Request与Response,更多内容请参考:Python学习指南

Request

Request源码:

# 部分代码
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):

        self._encoding = encoding  # this one has to be set first
        self.method = str(method).upper()
        self._set_url(url)
        self._set_body(body)
        assert isinstance(priority, int), "Request priority not an integer: %r" % priority
        self.priority = priority

        assert callback or not errback, "Cannot use errback without a callback"
        self.callback = callback
        self.errback = errback

        self.cookies = cookies or {}
        self.headers = Headers(headers or {}, encoding=encoding)
        self.dont_filter = dont_filter

        self._meta = dict(meta) if meta else None

    @property
    def meta(self):
        if self._meta is None:
            self._meta = {}
        return self._meta

其中,比较常用的参数:

url:就是需要请求,并进行下一步处理的url
callback:指定该请求返回的response,由哪个函数来处理。
method: 请求一般不需要指定,默认为GET方法,可设置为"GET"、"POST"、"PUT"等,且保证字符串大写。
headers: 请求时,包含的头文件。一般不需要,内容一般如下:

  • Host:media.readthedocs.org
  • User-Agent:Mozilla/5.0 (Window NT 6.2; WOW64; rv:33.0) Cecko/20100101 Firefox/33.0
  • Accept:text/css, /;q=0.1
  • Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
  • Accept-Encoding:gzip,deflate
  • Referrer:http://scrapy-chs.readthedocs.org/zh_CN/0.24
  • Cookie:_ga=GA2.1612165614.14532342342
  • Connection:keep-alive
  • If-Modified-Since:Mon, 25 Aug 2015 21:59:35 GMT
  • Cache-Contro:max-age=0

meta:比较常用,在不同的请求之间传递数据使用的。字典dict型
"""
request_with_cookies = Request(
url="http://www.example.com",
cookies={'currency': 'USD', 'country': 'UY'},
meta={'dont_merge_cookies': True}
)
"""
encoding:使用默认的'utf-8'就行。
dont_filter:表明该请求不由调度器过滤。这是当你想使用多次执行相同的其你去,就忽略重复的过滤器。默认为False
errback:指定错误处理函数

Request.meta

Request.meata在不同请求之间传递数据使用的。
Request.meta属性可以包含任意的数据,但是Scrapy和它的内置扩展可以识别一些特殊的键。

Request的子类FormRequest

FormRequest是Request的子类,一般用作表单数据提交。

class FormRequest(Request):

    def __init__(self, *args, **kwargs):
        formdata = kwargs.pop('formdata', None)
        if formdata and kwargs.get('method') is None:
            kwargs['method'] = 'POST'

        super(FormRequest, self).__init__(*args, **kwargs)

FormRequest的构造:

class scrapy.http.FormRequest(url, [formdata,...])

FormRequest类除了有Request的功能,还提供了form_response的功能

def from_response(cls, response, formname=None, formid=None, formnumber=0, formdata=None,clickdata=None, dont_click=False, formxpath=None, formcss=None, **kwargs)

Response

# 部分代码
class Response(object_ref):
    def __init__(self, url, status=200, headers=None, body='', flags=None, request=None):
        self.headers = Headers(headers or {})
        self.status = int(status)
        self._set_body(body)
        self._set_url(url)
        self.request = request
        self.flags = [] if flags is None else list(flags)

    @property
    def meta(self):
        try:
            return self.request.meta
        except AttributeError:
            raise AttributeError("Response.meta not available, this response " \
                "is not tied to any request")

大部分参数和上面的差不多:

status :响应的状态码
body :响应体
url :响应url
headers:响应对象的响应报头
meta:为response.meta属性的初始值。如果给定的,字典将浅复制。

Response的子类

Response的继承关系

Response
    TextResponse
        HtmlResponse
        XmlResponse

TextResponse

class scrapy.http.TextResponse(url[,encoding[,...]])

TextResponse对象增加了编码能力的基础响应类,是指将只用于二进制数据,如图像、生硬或任何媒体文件。
TextResponse对象除了标准的Response对象外,还支持以下属性和方法:

textresponse.selector.css('p')

#也可以简写为:

textresponse.css('p')
textresponse.selector.css('p')

#也可以简写为:

textresponse.css('p')

HtmlResponse

HtmlResponse类是TextResponse的一个子类,它通过查看HTML meta http-equiv属性来添加编码自动发现支持。

XmlResponse

XmlResponse类是TextResponse的一个子类,它通过查看XML声明行来添加编码自动发现支持。

Response的

发送POST请求

class mySpider(scrapy.Spider):
    #start_utls = ['http://www.example d']
    def start_requests(self):
        url = "http://www.renren.com/PLogin.do"

    #FormRequest是Scrapy发送POST请求的方法
    yield scrapy.FormRequest(
            url = url,
            formdata = {"email" : "xxxx@qq.com", "password":"xxxxxx"}
            callback = self.parse_page
        )
    def parse_page(self, response):
    #do something

模拟登陆

使用FormRequest.form_response()方法模拟用户登陆

通常网站通过实现对某些表单字段(如数据或者登陆界面中的认证令牌等)的预填充。
使用Scrapy抓取网页时,如果想要预填充或重写像用户名、用户密码这些表单字段时,可以使用FormRequest.from_response()方法实现。
在Request中不存在formadata参数,所以无法使用提交表单的方式

下面是使用这种方法的爬虫例子:

import scrapy

class LoginSpider(scrapy.Spider):
    name = 'example.com'
    start_urls = ['http://www.example.com/users/login.php']

    def parse(self, response):
        return scrapy.FormRequest.from_response(
            response,
            formdata={'username': 'john', 'password': 'secret'},
            callback=self.after_login
        )

    def after_login(self, response):
        # check login succeed before going on
        if "authentication failed" in response.body:
            self.log("Login failed", level=log.ERROR)
            return

        # continue scraping with authenticated session...

Github爬虫案例参考:

#-*- coding:utf-8 -*-
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/63.0.3239.84 Safari/537.36",
        "Referer" : "https://github.com",
        "Origin" : 'https://github.com',
        "Host":'github.com'
    }

    def start_requests(self):
        """
            执行spider请求
            :return 返回一个Request对象,请求登陆的页面
        """
        return [Request(url="https://github.com/login", meta={"cookiejar":1}, callback = self.post_login, headers = self.post_headers)]

    def post_login(self, response):
        """
            登陆的页面请求成功后,解析响应的页面,获取登陆需要的<input>标签信息
            :param response :登陆接口返回的页面
        """

        #github登陆上传必要的字段
        utf8 = response.xpath('//form//input[@name="utf8"]/@value').extract()[0]
        authenticity_token = response.xpath('//form//input[@name="authenticity_token"]/@value').extract()[0]
        login = "xxxx@qq.com"
        password = "xxxxxx"
        commit = response.xpath('//form//input[@name="commit"]/@value').extract()[0]

        #发送FormRequest表单请求
        return FormRequest.from_response(response=response, meta={"cookiejar":response.meta['cookiejar']},
            formdata = {
                "utf8" : utf8,
                "authenticity_token" :authenticity_token,
                "login" : login,
                "password" : password,
                "commit" : commit
            },
            callback = self.after_login,
            headers = self.post_headers
            )

    def after_login(self, response):
        """
            form表单请求成功后,请求登陆我的页面
            :param response
            :return:返回一个响应
        """
        print(response.body)
        if response.status == 200:
            with open("my_github.html", "wb") as f:
                f.write(response.body)

禁用遵循robot协议,打开Cookie

ROBOTSTXT_OBEY = False
COOKIE_ENABLED = True

启动爬虫

scrapy crawl github

参考:

  1. Scrapy框架学习(五)—-Request、Response介绍及模拟GitHub登录
上一篇 下一篇

猜你喜欢

热点阅读