运维学python之爬虫高级篇(六)scrapy模拟登陆

上一篇介绍了如何爬取豆瓣TOP250的相关内容,今天我们来模拟登陆GitHub。

1 环境配置

语言:Python 3.6.1
IDE: Pycharm
浏览器:firefox
抓包工具:fiddler
爬虫框架:Scrapy 1.5.0
操作系统:Windows 10 家庭中文版

2 爬取前分析

分析登陆提交信息
分析登陆信息我使用的是fiddler,fiddler的使用方法就不作介绍了,大家可以自行搜索,首先我们打开github的登陆页面,输入用户名密码,提交查看fiddler获取的信息,我这里第一次故意输入错误的密码,结果入下:
登陆页面(https://github.com/login ) :

输入用户名和错误密码获取的fiddler结果:

这里我们用火狐开发者工具也可以看到form提交时会加入authenticity_token参数一起,如下图:

3 开始爬虫

3.1 创建项目

进入你要存储项目的文件夹中执行下面命令:

scrpy startproject githubspider

可以根据提示继续创建spider,也可以自己手动创建,使用下面命令:

cd githubspider
scrapy genspider example example.com

如下图:

项目内容如下:

3.2 开始前准备

在scrapy.cfg同级目录下创建pycharm调试脚本run.py,内容如下:

# -*- coding: utf-8 -*-
from scrapy import cmdline

cmdline.execute(‘scrapy crawl github‘.split())

修改settings中的ROBOTSTXT_OBEY = True参数为False,因为默认为True,就是要遵守robots.txt 的规则, robots.txt 是遵循 Robot协议 的一个文件,它保存在网站的服务器中,它的作用是,告诉搜索引擎爬虫,本网站哪些目录下的网页不希望你进行爬取收录。在Scrapy启动后,会在第一时间访问网站的 robots.txt 文件,然后决定该网站的爬取范围。查看robots.txt可以直接网址后接robots.txt即可如百度:https://www.baidu.com/robots.txt

如果我们没有修改这个参数,则结果如下:

3.3 获取authenticity_token

首先要打开登陆页面,获取authenticity_token,代码如下:

import scrapy
from scrapy.http import Request

class GithubSpider(scrapy.Spider):
    name = ‘github‘
    allowed_domains = [‘github.com‘]

    def start_requests(self):
        urls = [‘https://github.com/login‘]
        for url in urls:
            # 重写start_requests方法,通过meta传入特殊key cookiejar,爬取url作为参数传给回调函数
            yield Request(url, meta={‘cookiejar‘: 1}, callback=self.github_login)

    def github_login(self, response):
        # 首先获取authenticity_token,这里可以借助scrapy shell ”url“来获取页面
        # 然后从源码中获取到authenticity_token的值
        authenticity_token = response.xpath("//input[@name=‘authenticity_token‘]/@value").extract_first()
        # 利用scrapy内置logger打印info信息
        self.logger.info(‘authenticity_token=‘ + authenticity_token)
        pass

结果如下:

可以看到我们已经获取了authenticity_token的值,这一步重点要说明meta、cookiejar和logger。
meta:字典格式的元数据,可以传递给下一个函数meta官网解释
cookiejar:是meta的一个特殊的key,通过cookiejar参数可以支持多个会话对某网站进行爬取,可以对cookie做标记,1,2,3,4......这样scrapy就维持了多个会话;
logger:scrapy为每个spider实例内置的日志记录器具体信息参考官网logging

3.4 FormRequest

Scrapy提供了FormRequest类,是Request类的扩展,专门用来进行Form表单提交。我们主要使用FormRequest.from_response()方法来模拟简单登陆,通过FormRequest.from_response提交后,交给回调函数处理。代码如下:

     def github_login(self, response):
        # 首先获取authenticity_token,这里可以借助scrapy shell ”url“来获取页面
        # 然后从源码中获取到authenticity_token的值
        authenticity_token = response.xpath("//input[@name=‘authenticity_token‘]/@value").extract_first()
        self.logger.info(‘authenticity_token=‘ + authenticity_token)
        # url可以从fiddler抓取中获取,dont_click作用是如果是True,表单数据将被提交,而不需要单击任何元素。
        return FormRequest.from_response(response,
                                         url=‘https://github.com/session‘,
                                         meta={‘cookiejar‘: response.meta[‘cookiejar‘]},
                                         headers=self.headers,
                                         formdata={‘utf8‘: ‘?‘,
                                                   ‘authenticity_token‘: authenticity_token,
                                                   ‘login‘: ‘[email protected]‘,
                                                   ‘password‘: ‘xxxxxx‘},
                                         callback=self.github_after,
                                         dont_click=True,
                                         )

回调函数的代码如下:

    def github_after(self, response):
        # 获取登录页面主页中的字符串‘Browse activity‘
        list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()
        # 如果含有字符串,则打印日志说明登录成功
        if ‘Browse activity‘ in list:
            self.logger.info(‘我已经登录成功了,这是我获取的关键字:Browse activity‘)

主页如下:

完整的github.py代码如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request, FormRequest

class GithubSpider(scrapy.Spider):
    name = ‘github‘
    allowed_domains = [‘github.com‘]
    # 头信息直接从fiddler中复制出来的
    headers = {
        ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0‘,
        ‘Accept‘: ‘text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8‘,
        ‘Accept-Language‘: ‘zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2‘,
        ‘Accept-Encoding‘: ‘gzip, deflate, br‘,
        ‘Referer‘: ‘https://github.com/‘,
        ‘Content-Type‘: ‘application/x-www-form-urlencoded‘,
    }

    def start_requests(self):
        urls = [‘https://github.com/login‘]
        for url in urls:
            # 重写start_requests方法,通过meta传入cookiejar特殊key,爬取url作为参数传给回调函数
            yield Request(url, meta={‘cookiejar‘: 1}, callback=self.github_login)

    def github_login(self, response):
        # 首先获取authenticity_token,这里可以借助scrapy shell ”url“来获取页面
        # 然后从源码中获取到authenticity_token的值
        authenticity_token = response.xpath("//input[@name=‘authenticity_token‘]/@value").extract_first()
        self.logger.info(‘authenticity_token=‘ + authenticity_token)
        # url可以从fiddler抓取中获取,dont_click作用是如果是True,表单数据将被提交,而不需要单击任何元素。
        return FormRequest.from_response(response,
                                         url=‘https://github.com/session‘,
                                         meta={‘cookiejar‘: response.meta[‘cookiejar‘]},
                                         headers=self.headers,
                                         formdata={‘utf8‘: ‘?‘,
                                                   ‘authenticity_token‘: authenticity_token,
                                                   # 这里是你自己的账号密码
                                                   ‘login‘: ‘[email protected]‘,
                                                   ‘password‘: ‘xxxxxx‘},
                                         callback=self.github_after,
                                         dont_click=True,
                                         )

    def github_after(self, response):
        # 获取登录页面主页中的字符串‘Browse activity‘
        list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()
        # 如果含有字符串,则打印日志说明登录成功
        if ‘Browse activity‘ in list:
            self.logger.info(‘我已经登录成功了,这是我获取的关键字:Browse activity‘)
        else:
            self.logger.error(‘登录失败‘)

执行后的结果如下:

登录成功了。

4 再来一个列子

不知不觉发现我也写了好多篇文章了,写完上面模拟登陆GitHub后,决定趁热打铁,模拟登陆51cto,将我写的博文全部列出来,整理成目录。
51cto的登陆和GitHub差不多,只不过获取的是csrf 而不是authenticity_token,用fiddler获取的结果如下:

这里就不多说了,直接附代码,51cto.py(spider)内容如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import FormRequest
from githubspider.items import CtospiderItem

class CtoSpider(scrapy.Spider):
    name = ‘51cto‘
    allowed_domains = [‘51cto.com‘]

    def start_requests(self):
        urls = [‘http://home.51cto.com/index‘]
        for url in urls:
            yield scrapy.Request(url, callback=self.cto_login, meta={‘cookiejar‘: 1})

    def cto_login(self, response):
        # 获取csrf值
        csrf = response.xpath("//input[@name=‘_csrf‘]/@value").extract_first()
        headers = {
            ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0‘,
            ‘Accept‘: ‘text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8‘,
            ‘Accept-Language‘: ‘zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2‘,
            ‘Accept-Encoding‘: ‘gzip, deflate, br‘,
            ‘Referer‘: ‘http://blog.51cto.com‘,
            ‘Content-Type‘: ‘application/x-www-form-urlencoded‘,
        }
        # 此处为logger输出供调试时使用
        # self.logger.info("获取csrf值为 %s" % csrf)
        yield FormRequest.from_response(response,
                                        url=‘http://blog.51cto.com/linuxliu?type=1‘,
                                        headers=headers,
                                        meta={‘cookiejar‘: response.meta[‘cookiejar‘]},
                                        formdata={
                                                  # 这个位置注意0要加引号,不然会报错,这个参数意思是是否记住密码10天内自动登录
                                                  ‘LoginForm[rememberMe]‘: ‘0‘,
                                                  ‘LoginForm[username]‘: ‘xxxx‘,
                                                  ‘LoginForm[password]‘: ‘xxxx‘,
                                                  ‘_csrf‘: csrf,
                                                  },
                                        callback=self.after_login,
                                        dont_click=True,
                                        )

    def after_login(self, response):
        # 定义item实例,items.py中已经定义好字段
        item = CtospiderItem()
        # 获取的网页内容
        resps = response.css("ul.artical-list li")
        for resp in resps:
            # 写入item字段中
            item[‘title_url‘] = resp.css("a.tit::attr(href)").extract_first()
            item[‘title‘] = resp.css("a.tit::text").extract_first().strip()
            # fullname的格式为“[名称](链接)”之所以这样是因为
            # markdown语法里这个表示链接的意思,点击名称直接打开链接内容
            item[‘fullname‘] = ‘[‘ + item[‘title‘] + ‘]‘ + ‘(‘ + item[‘title_url‘] + ‘)‘
            # 此处logger也是调试使用
            # self.logger.info("title url的值为:%s , title的值为%s" % (tit_url, tit))
            yield item

        # 下一页内容获取
        next_page = response.css(‘li.next a::attr(href)‘).extract_first()
        # self.logger.info("下一页链接为:%s" % next_page)
        if next_page is not None:
            yield scrapy.Request(next_page, callback=self.after_login)

items.py字段如下:

class CtospiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    title_url = scrapy.Field()
    fullname = scrapy.Field()

执行命令写入csv文件:

scrapy crawl 51cto -o cto.csv

文件结果如下:

把我需要的fullname粘到这里大家就明白了:
运维学python之爬虫高级篇(五)scrapy爬取豆瓣电影TOP250
运维学python之爬虫高级篇(四)Item Pipeline介绍(附爬取网站获取图片到本地代码)
运维学python之爬虫高级篇(三)spider和items介绍
运维学python之爬虫高级篇(二)用Scrapy框架实现简单爬虫
运维学python之爬虫高级篇(一)Scrapy框架入门
运维学python之爬虫中级篇(九)Python3 MySQL 数据库连接
运维学python之爬虫中级篇(八)MongoDB
运维学python之爬虫中级篇(七)Sqlite3
运维学python之爬虫中级篇(六)基础爬虫
运维学python之爬虫中级篇(五)数据存储(无数据库版)
运维学python之爬虫中级篇(四)网络编程
运维学python之爬虫中级篇(三)分布式进程
运维学python之爬虫中级篇(二)线程、协程
运维学python之爬虫中级篇(一)进程
运维学python之爬虫工具篇(六)Pyquery的用法
运维学python之爬虫工具篇(五)Selenium的用法
运维学python之爬虫工具篇(四)PhantomJS的用法
运维学python之爬虫工具篇(三)Xpath语法与lxml库的用法
运维学python之爬虫工具篇(二)Beautiful Soup的用法
运维学python之爬虫工具篇(一)Requests库的用法
运维学python之爬虫基础篇实战(七)爬取伯乐在线面向对象图片
运维学python之爬虫基础篇实战(六)爬取百度贴吧
运维学python之爬虫基础篇(五)正则表达式
运维学python之爬虫基础篇(四)Cookie
运维学python之爬虫基础篇(三)urllib模块高级用法
运维学python之爬虫基础篇(二)urllib模块使用
运维学python之爬虫基础篇(一)开篇

5 写在结尾

年前最后一更,过节期间有时间我就更,没时间可能就不更了,在这里提前给大家拜个早年,祝大家新春快乐,18年心想事成,另外今天情人节,也祝大家情人节快乐!!!

原文地址:http://blog.51cto.com/linuxliu/2071674

时间: 2024-08-09 19:47:39

运维学python之爬虫高级篇(六)scrapy模拟登陆的相关文章

运维学python之爬虫高级篇(七)scrapy爬取知乎关注用户存入mongodb

首先,祝大家开工大吉!本篇将要介绍的是从一个用户开始,通过抓关注列表和粉丝列表,实现用户的详细信息抓取并将抓取到的结果存储到 MongoDB. 1 环境需求 基础环境沿用之前的环境,只是增加了MongoDB(非关系型数据库)和PyMongo(Python 的 MongoDB 连接库),默认我认为大家都已经安装好并启动 了MongoDB 服务. 项目创建.爬虫创建.禁用ROBOTSTXT_OBEY设置略(可以参考上一篇) 2 测试爬虫效果 我这里先写一个简单的爬虫,爬取用户的关注人数和粉丝数,代码

运维学python之爬虫高级篇(五)scrapy爬取豆瓣电影TOP250

对于scrapy我们前面已经介绍了简单的应用,今天我们用一个完整的例子,爬取豆瓣电影TOP250来做一个小的练习,把scrapy阶段做一个总结. 1 环境配置 语言:Python 3.6.1 IDE: Pycharm 浏览器:firefox 爬虫框架:Scrapy 1.5.0 操作系统:Windows 10 家庭中文版 2 爬取前分析 2.1 需要保存的数据 首先确定我们要获取的内容,在items中定义字段,来将非结构化数据生成结构化数据,获取的内容主要包括:排名.电影名称.得分.评论人数.如下

运维学python之爬虫中级篇(五)数据存储(无数据库版)

本篇主要介绍,爬取html数据后,将html的正文内容存储为json或csv格式. 1 json格式存储 选定要爬取的网站后,我们利用之前学过的内容,如:Beautiful Soup.xpath等方式解析,来获取我们希望得到的内容. 1.1 获取数据 首先使用urllib访问页面https://www.lagou.com/zhaopin/Python/?labelWords=label获取html内容,代码如下: from urllib import request try: url = 'ht

运维学python之爬虫中级篇(六)基础爬虫

通过这么多天对爬虫的介绍, 我们对爬虫也有所了解,今天我们将引入一个简单爬虫的技术架构,解释爬虫技术架构中的几个模块,后面的爬虫也多是今天架构的延伸,只不过这个架构是简单的实现,对优化.爬取方式等不是很完善,主要为了方便大家对爬虫的理解和后面的编程. 1 基础架构和流程 简单的爬虫架构由以下几部分构成:爬虫调度器:总体协调其它几个模块的工作URL管理器:负责管理URL,维护已经爬取的URL集合和未爬取的URL集合网页下载器:对未爬取的URL下载网页解析器:解析已下载的html,并从中提取新的UR

运维学python之爬虫中级篇(八)MongoDB

1 MongoDB MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.具有高性能.高可用性和自动扩展性.MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成.MongoDB 文档类似于 JSON 对象的BSON.字段值可以包含其他文档,数组及文档数组.MongoDB最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引. 1.1 安装Mongo

学习《从零开始学Python网络爬虫》PDF+源代码+《精通Scrapy网络爬虫》PDF

学习网络爬虫,基于python3处理数据,推荐学习<从零开始学Python网络爬虫>和<精通Scrapy网络爬虫>. <从零开始学Python网络爬虫>是基于Python 3的图书,代码挺多,如果是想快速实现功能,这本书是一个蛮好的选择. <精通Scrapy网络爬虫>基于Python3,深入系统地介绍了Python流行框架Scrapy的相关技术及使用技巧. 学习参考: <从零开始学Python网络爬虫>PDF,279页,带目录,文字可复制: 配套

linux运维及Python运维免费公开课

适用人群:想从事linux运维及python运维开发的人员 企业网管.技术支持.linux运维人员.大中专学生 听课时间:2014年11月30日(周日)下午1:30 听课地点:北京市昌平区沙河青年创业大厦B座1519室(地铁昌平线沙河站B1口200米处) 听课内容: LINUX运维:(1.5小时) 1.软件开源的大发展趋势及如何把握这个趋势? 2.linux运维职位到底都做什么? 3.linux运维前景到底咋样? 4.到底是选择运维还是选择开发发展? 5.运维人员如何超越年薪30万,50万? 6

Linux运维 第二阶段 (七)高级文件系统管理

Linux运维第二阶段(七)高级文件系统管理 一.磁盘配额: 多用户共同使用一个硬盘,管理员应适当限制硬盘的空间,以妥善分配系统资源. #grepCONFIG_QUOTA /boot/config-2.6.32-279.el6.i686 #rpm–qa | grep quota 用户配额和组配额:磁盘容量限制和文件个数限制:软限制和硬限制:宽限时间. 注:如果用户的空间处于软限制和硬限制之间,系统会在用户登录时警告将满,宽限时间默认7天,如果达到了宽限时间未调整,软限制就会升级为硬限制. #mo

Linux运维 第四阶段 (六)MySQL备份&&还原(mysqldump、LV’s snapshot、xtrabackup)

Linux运维 第四阶段 (六)MySQL备份&&还原(mysqldump.LV's snapshot.xtrabackup) 一.相关概念 备份:副本,mysql-database备份不同于RAID(RAID是保证硬件损坏而不会业务终止) 备份内容:数据.配置文件.二进制日志.事务日志 1.备份类型: >热备份.温备份.冷备份 热备份:读写不受影响,复杂度高,InnoDB(xtrabackup,mysqldump),lvm快照功能可实现几乎热备: 温备份:仅可执行读操作,MyISA