python爬虫学习笔记4模拟登录函数的优化

前言

前面写的代码虽然完成了爬取的功能,但是过于凌乱,于是打算重构一遍。首先从登陆开始。

前文传送门:

个人博客本文传送门:

python爬虫学习笔记4模拟登录函数的优化

改进前的代码

面向过程

这是第一次写的登录函数,获取登录信息和登录本身是放在一起的。

def login():
    """
    登录并返回已经登录的会话
    :return: 已经登录的会话(session)
    """
    #设置
    login_url = 'http://ids.chd.edu.cn/authserver/login?service=http%3A%2F%2Fportal.chd.edu.cn%2F'
    headers={
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36',
    }
    #新建会话
    session=requests.session()

    #获取登录校验码
    html=session.post(login_url,headers=headers).text
    soup=BeautifulSoup(html,'lxml')
    lt=soup.find('input',{'name':'lt'})['value']
    dllt=soup.find('input',{'name':'dllt'})['value']
    execution = soup.find('input', {'name': 'execution'})['value']
    _eventId = soup.find('input', {'name': '_eventId'})['value']
    rmShown = soup.find('input', {'name': 'rmShown'})['value']
    login_data={
        'username': input("请输入学号:"),
        'password': input("请输入密码:"),
        'btn':'',
        'lt': lt,
        'dllt': dllt,
        'execution': execution,
        '_eventId': _eventId,
        'rmShown': rmShown
    }

    #登录
    response=session.post(login_url,headers=headers,data=login_data)
    if response.url=='http://portal.chd.edu.cn/':
        print('登录成功!')

    return session

面向对象

第二次是将全部函数封装到类中,这次将获取登录信息从其中分出来。但是两者关系仍然太过于紧密。

class spider:
    '''
    爬虫类
    '''

    def __init__(self,headers):
        self.session=requests.session()#初始化登录session
        self.is_login=False#登录状态
        self.headers=headers#头信息
        self.cookiejar=http.cookiejar.LWPCookieJar('cookie.txt')

    def get_login_data(self,login_url):
        '''
        获取登录需要的数据
        :param login_url: 登录页面url
        :return: 一个存有登录数据的字典
        '''
        # 获取登录校验码
        html = self.session.post(login_url, headers=self.headers).text
        soup = BeautifulSoup(html, 'lxml')
        lt = soup.find('input', {'name': 'lt'})['value']
        dllt = soup.find('input', {'name': 'dllt'})['value']
        execution = soup.find('input', {'name': 'execution'})['value']
        _eventId = soup.find('input', {'name': '_eventId'})['value']
        rmShown = soup.find('input', {'name': 'rmShown'})['value']
        login_data = {
            'username': input("请输入学号:"),
            'password': input("请输入密码:"),
            'btn': '',
            'lt': lt,
            'dllt': dllt,
            'execution': execution,
            '_eventId': _eventId,
            'rmShown': rmShown
        }
        return login_data

    def login(self,login_url):
        """
            登录并返回已经登录的会话
            :return: 已经登录的会话(session)
        """
        if self.load_cookie():
            self.is_login = True

        else:

            #获取登录信息
            login_data=self.get_login_data(login_url)

            # 登录
            response = self.session.post(login_url, headers=self.headers, data=login_data)
            if response.url!=login_url:
                print("登录成功")
                self.is_login=True
                self.save_cookie()
            else:
                print("登录失败")
        return self.session
    
    #省略后面的函数

改进

这次改进,我打算让login()函数与获取登录信息用的函数关系没有那么紧密,让后者可以被替换或者不用。

所以使用了回调函数,也就是将函数指针作为参数传入,不过python变量本身就像指针一样,直接传变量即可。

函数头

def login(self,login_url,login_data_parser=None,target_url=None):

传入了三个参数,

  • login_url : 显而易见,这是登录页面的url
  • login_data_parser : 这是一个函数,用于解析页面中随机生成的隐藏域代码的函数,可以不传入
  • target_url : 用于判断是否登录成功,这是登录之后会跳转到的页面

获取登录信息

接着判断参数是否为函数(是否可调用),如果可以调用,就调用它获取登录信息。在这里不需要关心函数内部具体如何获取,而只用关心它的接口。

这个函数的返回值是一个装有登录信息的dict,和一个cookies。

def login(self,login_url,login_data_parser=None,target_url=None):
        login_data=None
        #get the login data
        if(login_data_parser!=None and callable(login_data_parser)):
            login_data,cookies=login_data_parser(login_url)

登录

然后就完成了

def login(self,login_url,login_data_parser=None,target_url=None):
        '''
        login
        :param login_url: the url you want to login
        :param login_data_parser: a callback function to get the login_data you need when you login,return (login_data,response.cookies)
        :param target_url: Used to determine if you have logged in successfully

        :return: response of login
        '''
        login_data=None

        #get the login data
        if(login_data_parser!=None and callable(login_data_parser)):
            login_data,cookies=login_data_parser(login_url)

        #login
        response=requests.post(login_url,headers=self.headers,data=login_data,cookies=cookies)

        if(target_url!=None and response.url==target_url):
            print("login successfully")

        self.cookies=cookies
        return response

获取登录信息函数

这个和前面就是一样的了。只要修改传给login函数的函数,就可以获取不同网站的登录信息。login函数变得更加通用了,不再过于依赖登录信息函数存在。

def chd_login_data_parser(self,url):
        '''
        This parser is for chd
        :param url: the url you want to login
        :return (a dict with login data,cookies)
        '''
        response=requests.get(login_url)
        html=response.text
        # parse the html
        soup=BeautifulSoup(html,'lxml')
        lt=soup.find('input',{'name':'lt'})['value']
        dllt=soup.find('input',{'name':'dllt'})['value']
        execution = soup.find('input', {'name': 'execution'})['value']
        _eventId = soup.find('input', {'name': '_eventId'})['value']
        rmShown = soup.find('input', {'name': 'rmShown'})['value']
        login_data={
            'username': input('input account:'),
            'password': input('input passwd:'),
            'btn':'',
            'lt': lt,
            'dllt': dllt,
            'execution': execution,
            '_eventId': _eventId,
            'rmShown': rmShown
        }
        return login_data,response.cookies
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值