Python爬蟲Scrapy(七)_Request_Response

本章將介紹Request與Response,更多內(nèi)容請參考:Python學(xué)習(xí)指南

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

其中惕味,比較常用的參數(shù):

url:就是需要請求,并進行下一步處理的url
callback:指定該請求返回的response彭谁,由哪個函數(shù)來處理瓷患。
method: 請求一般不需要指定铃肯,默認為GET方法己沛,可設(shè)置為"GET"、"POST"商乎、"PUT"等央拖,且保證字符串大寫。
headers: 請求時鹉戚,包含的頭文件鲜戒。一般不需要,內(nèi)容一般如下:

  • 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:比較常用崩瓤,在不同的請求之間傳遞數(shù)據(jù)使用的。字典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:表明該請求不由調(diào)度器過濾却桶。這是當(dāng)你想使用多次執(zhí)行相同的其你去,就忽略重復(fù)的過濾器。默認為False
errback:指定錯誤處理函數(shù)

Request.meta

Request.meata在不同請求之間傳遞數(shù)據(jù)使用的颖系。
Request.meta屬性可以包含任意的數(shù)據(jù)嗅剖,但是Scrapy和它的內(nèi)置擴展可以識別一些特殊的鍵。

  • dont_rediect:不重定向
  • dont_retry:不重試
  • handle_httpstatus_list
  • dont_merge_cookies:不合并cookie
  • cookiejar:使用cookiejar
  • rediect_urls:重定向連接
  • bindaddress:綁定ip地址
  • dont_obey_robotstxt:不遵循反爬蟲協(xié)議
  • download_timeout:下載超時

Request的子類FormRequest

FormRequest是Request的子類嘁扼,一般用作表單數(shù)據(jù)提交信粮。

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的構(gòu)造:

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:是指包含HTML表單的Response對象趁啸,該表單將用于預(yù)填充表單字段强缘。
  • formname:如果給定,將使用form表單的name屬性為該值的name屬性的表單不傅。
  • formid:如果給定旅掂,將使用form表單的id屬性為該值的name屬性的表單
  • formnumber:當(dāng)響應(yīng)包含多個表單時,要使用的表單的數(shù)量访娶。 formnumber默認是0商虐,表示使用第一個。
  • formdata:字段來覆蓋表單數(shù)據(jù)崖疤。如果一個字段已經(jīng)存在于響應(yīng)<form>元素中秘车,那么它的值被在這個參數(shù)中傳遞的值覆蓋。
  • formxpath:如果給定劫哼,將使用與XPath匹配的第一個表單叮趴。
  • clickdata:查找單擊控件的屬性。如果沒有給出沦偎,表單數(shù)據(jù)將被提交模擬點擊第一個可點擊的元素疫向。
  • dont_click:如果為True,表單數(shù)據(jù)將被提交而不需要單擊任何元素豪嚎。

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")

大部分參數(shù)和上面的差不多:

status :響應(yīng)的狀態(tài)碼
body :響應(yīng)體
url :響應(yīng)url
headers:響應(yīng)對象的響應(yīng)報頭
meta:為response.meta屬性的初始值搔驼。如果給定的,字典將淺復(fù)制侈询。

Response的子類

Response的繼承關(guān)系

Response
    TextResponse
        HtmlResponse
        XmlResponse

TextResponse

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

TextResponse對象增加了編碼能力的基礎(chǔ)響應(yīng)類舌涨,是指將只用于二進制數(shù)據(jù),如圖像扔字、生硬或任何媒體文件囊嘉。
TextResponse對象除了標準的Response對象外,還支持以下屬性和方法:

  • encoding:
    與此響應(yīng)編碼的字符串革为。 通過嘗試以下機制來解決編碼問題:

    • 在構(gòu)造函數(shù)編碼參數(shù)中傳遞的編碼
    • 在Content-Type HTTP頭中聲明的編碼扭粱。如果這種編碼是無效的(即未知的),它將被忽略震檩,并嘗試下一個解析機制琢蛤。
    • 在響應(yīng)正文中聲明的編碼蜓堕。TextResponse類不提供任何特殊的功能。但是博其,HtmlResponse和XmlResponse類可以套才。
    • 通過查看響應(yīng)主體來推斷編碼。 這是更脆弱的方法慕淡,但也是最后一個嘗試背伴。
  • selector : 使用響應(yīng)作為目標的選擇器實例。

  • ``body_as_unicode()` : 以unicode形式返回響應(yīng)的主體峰髓。

  • xpath(query) : xpath解析

textresponse.selector.css('p')

#也可以簡寫為:

textresponse.css('p')
  • css(query) : :css解析傻寂,相當(dāng)于BeautifulSoup4解析
textresponse.selector.css('p')

#也可以簡寫為:

textresponse.css('p')

HtmlResponse

HtmlResponse類是TextResponse的一個子類,它通過查看HTML meta http-equiv屬性來添加編碼自動發(fā)現(xiàn)支持儿普。

XmlResponse

XmlResponse類是TextResponse的一個子類崎逃,它通過查看XML聲明行來添加編碼自動發(fā)現(xiàn)支持。

Response的

發(fā)送POST請求

  • 可以使用yield scrapy.FormRequest(url, formdata, callback)的方法發(fā)送POST請求眉孩。
  • 如果希望程序執(zhí)行一開始就發(fā)送POST請求个绍,可以重寫Spider類的start_requests(self)方法,并且不再調(diào)用start_urls里的url浪汪。
class mySpider(scrapy.Spider):
    #start_utls = ['http://www.example d']
    def start_requests(self):
        url = "http://www.renren.com/PLogin.do"

    #FormRequest是Scrapy發(fā)送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()方法模擬用戶登陸

通常網(wǎng)站通過實現(xiàn)對某些表單字段(如數(shù)據(jù)或者登陸界面中的認證令牌等)的預(yù)填充巴柿。
使用Scrapy抓取網(wǎng)頁時,如果想要預(yù)填充或重寫像用戶名死遭、用戶密碼這些表單字段時广恢,可以使用FormRequest.from_response()方法實現(xiàn)。
在Request中不存在formadata參數(shù)呀潭,所以無法使用提交表單的方式

下面是使用這種方法的爬蟲例子:

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):
        """
            執(zhí)行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):
        """
            登陸的頁面請求成功后,解析響應(yīng)的頁面钠署,獲取登陸需要的<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]

        #發(fā)送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:返回一個響應(yīng)
        """
        print(response.body)
        if response.status == 200:
            with open("my_github.html", "wb") as f:
                f.write(response.body)

禁用遵循robot協(xié)議,打開Cookie

ROBOTSTXT_OBEY = False
COOKIE_ENABLED = True

啟動爬蟲

scrapy crawl github

參考:

  1. Scrapy框架學(xué)習(xí)(五)—-Request、Response介紹及模擬GitHub登錄
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谐鼎,一起剝皮案震驚了整個濱河市舰蟆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狸棍,老刑警劉巖身害,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異草戈,居然都是意外死亡塌鸯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門唐片,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丙猬,“玉大人丢习,你說我怎么就攤上這事』吹浚” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵揽思,是天一觀的道長袜腥。 經(jīng)常有香客問我,道長钉汗,這世上最難降的妖魔是什么羹令? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮损痰,結(jié)果婚禮上福侈,老公的妹妹穿的比我還像新娘。我一直安慰自己卢未,他們只是感情好肪凛,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辽社,像睡著了一般伟墙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滴铅,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天戳葵,我揣著相機與錄音,去河邊找鬼汉匙。 笑死拱烁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的噩翠。 我是一名探鬼主播戏自,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绎秒!你這毒婦竟也來了浦妄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤见芹,失蹤者是張志新(化名)和其女友劉穎剂娄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玄呛,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡阅懦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了徘铝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耳胎。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡惯吕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怕午,到底是詐尸還是另有隱情废登,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布郁惜,位于F島的核電站堡距,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兆蕉。R本人自食惡果不足惜羽戒,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虎韵。 院中可真熱鬧易稠,春花似錦、人聲如沸包蓝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽测萎。三九已至衬吆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绳泉,已是汗流浹背逊抡。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留零酪,地道東北人冒嫡。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像四苇,于是被迫代替她去往敵國和親孝凌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容