Scrapy之表单提交

有时候,我们需要登录网站才能获取到特定的信息。我们以登录github login为例,下面是github登录的部分 html代码。

 <form action="/session" accept-charset="UTF-8" method="post">
   <input name="utf8" type="hidden" value="✓" />
   <input type="hidden" name="authenticity_token" value="vr2Ebi0MMmJvjeZEQDEToGr96pQ2CK6TraSsU96M86B9PUI9D+59pAtOG99pv7UouYfN19Ptxwo+PaaVxYnWMQ==" /> 
   <div class="auth-form-header p-0"> 
    <h1>Sign in to GitHub</h1> 
   </div> 
   <div id="js-flash-container"> 
   </div> 
   <div class="auth-form-body mt-3"> 
    <label for="login_field"> Username or email address </label> 
    <input type="text" name="login" id="login_field" class="form-control input-block" tabindex="1" autocapitalize="off" autocorrect="off" autofocus="autofocus" /> 
    <label for="password"> Password <a class="label-link" href="/password_reset">Forgot password?</a> </label> 
    <input type="password" name="password" id="password" class="form-control form-control input-block" tabindex="2" /> 
    <input type="submit" name="commit" value="Sign in" tabindex="3" class="btn btn-primary btn-block" data-disable-with="Signing in…" /> 
   </div> 
  </form>

<form>action表示表单提交的地址;
<form>accept-charset表示服务器接受的字符串集;
<form>method表示提交数据的方式;
<form>下的<input>标签决定了表单提交的内容;
<input>name属性决定了数据提交的名称,该名称对应的值根据type的不同,取值方式也不同,有些从value属性取值,如hidden;有些需要用户输入,如textpassword等,具体可查阅HTML的文档,本文不再赘述。

下面是提交数据的过程与结果:

请求地址
提交的数据

正如所看到的,表单数据是input的键值对锁组成。

返回包

在返回包中,服务器会返回用户对应的Cookie信息,由于需要跳转302,返回包还提供了需要跳转的地址location.

从以上看,登录的本质,就是向目标服务器发送含有表单数据的请求,一般是通过POST来请求的。
scrapy提供了一个Request的子类FormRequest来构造和提交表达数据。FormRequest的构造参数在Request的基础上添加了formdata,该参数支持字典或元组的可迭代对象,当需要发起表单请求的时候,在构造时添加formdata即可。

我们通过FormRequest来实现登录github,通过www.github.com是否包含Signed in as来判断是否登录成功。

# scrapy shell https://github.com/login

>>> input_selector = response.css('input')
>>> fd = dict()
>>> for selector in input_selector:
...     name = selector.css('input::attr(name)').extract_first()
...     value = selector.css('input::attr(value)').extract_first()
...     if value is None:
...             value = ''
...     fd[name] = value
...
>>> fd['login'] = '******@gmail.com'
>>> fd['password'] = '******'
>>> request = scrapy.FormRequest('https://github.com/session', formdata=fd)
>>> fetch(request)
2018-06-03 15:27:50 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://github.com/> from <POST https://github.com/session>
2018-06-03 15:27:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://github.com/> (referer: None)
>>> 'Signed in as' in response.text
True

除了使用FormRequest之外,scrapy还提供了另一种方式来更为简单的提交表单,就是使用FormRequest的类方法from_response(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...]),使用时,第一个参数只需要提供Response对象,然后在formdata中提供账号和密码,其余的其他隐藏参数,该方法会帮我们处理好。

下面再使用FormRequest.from_response()来登录github;

# scrapy shell https://github.com/login

>>> fd = dict()
>>> fd['login'] = '******@gmail.com'
>>> fd['password'] = '******'
>>> request = scrapy.FormRequest.from_response(response, formdata=fd)
>>> fetch(request)
2018-06-03 15:35:40 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://github.com/> from <POST https://github.com/session>
2018-06-03 15:35:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://github.com/> (referer: None)
>>> 'Signed in as' in response.text
True

再来看看再实际的项目中如何实现登录的逻辑:

# profiles.py
# -*- coding: utf-8 -*-
import scrapy

class ProfilesSpider(scrapy.Spider):
    name = 'profiles'
    allowed_domains = ['github.com']
    start_urls = ['http://github.com/']
    login = 'https://github.com/login'

    def parse(self, response):                      #开始正式爬虫后会默认调用的处理函数
        pass

    def after_login(self, response):
        yield from suoer().start_requests()         #调用spider的start_request()方法,以从start_urls开始爬取链接

    def start_requests(self):
        yield scrapy.Request(self.login_url, callback=self.parse_login)

    def parse_login(self, response):
        fd = dict()
        post_headers = {
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded",
            "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/",
        }
        fd['login'] = '*******@gmail.com'
        fd['password'] = '******'

        yield scrapy.FormRequest.from_response(response, formdata=fd, callback=self.after_login,headers = post_headers)

总结

本篇简单讲解了如何通过FormRequest来提交表单数据,至于带验证码的登录后面有时间研究一下。下一篇会研究如何动态页面的数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容