Python模拟登陆 —— 征服验证码 3 CSDN

CSDN使用了spring的webflow

<input type="hidden" name="lt" value="LT-58187-6D0O7tpTNBVqzLTbyULoyeLt9fMZd1" />

这个隐藏参数可以理解成每个需要登录的用户都有一个流水号。只有有了webflow发放的有效的流水号,用户才可以说明是已经进入了webflow流程。否则,没有流水号的情况下,webflow会认为用户还没有进入webflow流程,从而会重新进入一次webflow流程,从而会重新出现登录界面。

import requests
from bs4 import BeautifulSoup
#######################################################
#  Replace special characters in string using the %xx escape. Letters, digits,
#          and the characters '_.-' are never quoted.
# Python 3 可以这么引入
from urllib.parse import quote


#### 控制台输入账号密码相关, 如有特殊密码保护,应使用getpass(需要注意的是Pycharm对此支持的不好)
import getpass


# Python 2 需要这么引入
# import urllib.quote

class CSDN(object):
    """
    CSDN模拟登陆并加上点赞,评论,私信等功能。
    """
    def __init__(self, headers):
        """
        :param session: 创建全局的session对象,保证会话的一致性,有效性。
        :param headers: 防止服务器端反爬虫,添加伪装头部信息
        """
        self.session = requests.Session()
        self.headers = headers

    def login(self, account, passwd):
        """
        模拟登陆,点赞, 发评论,发私信的前提都是已在登录状态下进行的,这是前提。
        :param account: 用户名
        :param passwd:  密码
        :return:
        """

        self.username = account
        self.password = passwd

        # 只有获取到webflow流水号,才会正式进入登陆通道,服务器端对此进行了限制。
        lt, execution = self.get_webflow()
        # 要提交的表单数据
        postdata = {
            'username': account,
            'password': passwd,
            "lt": lt,
            "execution": execution,
            "_eventId": "submit"
        }

        ## 开始登陆
        loginurl = 'https://passport.csdn.net/account/login'
        response = self.session.post(url=loginurl, headers=self.headers, data=postdata)
        if response.status_code == 200:
            print('恭喜您登陆成功!')
        else:
            print(response.text)
            print('登录失败,请重试!')


    def get_webflow(self):
        """
        流水号webflow获取。随便访问包含登陆页链接的CSDN网页就可以得到这串数据。应为是动态变化的
        所以,先获取下来,以备使用。
        :return:
        """
        url = 'https://passport.csdn.net/account/login?ref=toolbar'
        response = self.session.get(url=url, headers=self.headers)
        soup = BeautifulSoup(response.text, 'html.parser')
        lt = soup.find('input', {'name': 'lt'})['value']
        execution = soup.find('input', {'name': 'execution'})['value']
        # 释放不必要的对象
        soup.clear()
        return (lt, execution)

    def digg(self, articleurl, digg=True):
        """
        把给定的文章路径 http://blog.csdn.net/marksinoberg/article/details/69569353
        先转化一下为: http://blog.csdn.net/marksinoberg/article/digg?ArticleId=69569353

        :param articleurl 待操作的文章路径
        :param digg: 给文章点赞还是踩一下
        :return:
        """
        try:
            bloguser, blogid = articleurl.split('/')[3], articleurl.split('/')[-1]
            if digg==True:
                diggurl = 'http://blog.csdn.net/{}/article/digg?ArticleId={}'.format(bloguser, blogid)
            else:
                diggurl = 'http://blog.csdn.net/{}/article/bury?ArticleId={}'.format(bloguser, blogid)
        except:
            print('您输入的文章路径非法!')
        print("待操作文章的路径: ", diggurl)
        self.headers['X-Requested-With'] = 'XMLHttpRequest'
        self.headers['Host'] = 'blog.csdn.net'
        self.headers['Referer'] = articleurl

        response = self.session.get(url=diggurl, headers=self.headers)
        if response.status_code == 200:
            # print("Digg 操作成功", response.text)
            articlejson = response.json()
            digg, bury = articlejson['digg'], articlejson['bury']
            print('文章:{}\n:被点赞数:{}, 被踩数:{}'.format(articleurl, digg, bury))

        else:
            print('网络或服务器出现了问题,点赞操作出现了点故障!')
        self.headers['Referer'] = ''

    def comment(self, articleurl, content):
        """
        给定一个文章的路径http://blog.csdn.net/marksinoberg/article/details/69569353,
        需要转化为形如: http://blog.csdn.net/Marksinoberg/comment/submit?id=69569353
        :param articleurl:
        :param content:
        :return:
        """
        try:
            bloguser, blogid = articleurl.split('/')[3], articleurl.split('/')[-1]
            commenturl = 'http://blog.csdn.net/{}/comment/submit?id={}'.format(bloguser, blogid)
        except:
            print(commenturl, ' 不是一个合法的路径!')
        print(commenturl)
        postdata = {
            'commentid': self.username,
            'replyid': bloguser,
            'content': content
        }
        response = self.session.post(url=commenturl, headers=self.headers, data=postdata)
        if response.status_code == 200:
            print(response.json())
            if response.json()['result'] == 1:
                print('评论成功咯!')
            else:
                print('服务器访问成功,但评论操作失败了!')
        else:
            print('评论出现了点异常!')

    def letter(self, receiver, content):
        letterurl = 'http://msg.csdn.net/letters/send_message?receiver={0}&body={1}'.format(receiver, quote(content))
        response = self.session.get(url=letterurl, headers=self.headers)
        if response.status_code == 200:
            print("私信内容发送成功!")
            # print(response.text)
            ## 这里服务器返回的是一大串HTML代码。通过解析还可以得到本人和其他博友的私信记录。
        else:
            print('私信发送失败!请检查网络是否通畅。')


    def publish_article(self):
        """
        核心URL: http://write.blog.csdn.net/postedit?edit=1&isPub=1&joinblogcontest=undefined&r=0.14573376474383326
        有兴趣的可以尝试着做一下。

        需要提交的表单信息为:
                titl:1234567                           # 博客标题
                typ:1                                  # 原创1, 转载2, 翻译3
                cont:自动发现一篇好文章的前提是什么?    #  发表的文章内容
                desc:自动发现一篇好文章的前提是什么?    # 发表的摘要信息
                tags:                                  # 标签们
                flnm:69803183                          # 博客ID(如果是新文章默认没有的)
                chnl:0                                 # 文章类型: 编程语言啊, 系统架构啊什么的
                comm:2
                level:0
                tag2:
                artid:0
                checkcode:undefined
                userinfo1:713
                stat:publish
        :return:
        """

if __name__ == '__main__':
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36",
    }
    csdn = CSDN(headers=headers)
    account = input('请输入您的账号:')
    password = getpass.getpass(prompt='请输入您的密码:')
    csdn.login(account=account, passwd=password)
    # 评论测试
    # csdn.comment('http://blog.csdn.net/marksinoberg/article/details/69569353', '哈哈,爬虫评论')
    # 点赞,踩测试。digg为True为顶, 为False即踩
    # csdn.digg('http://blog.csdn.net/marksinoberg/article/details/69569353', digg=True)
    # 私信测试
    # csdn.letter(receiver='marksinoberg', content='僚机呼叫主机,收到请回复,Over!')

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯移动品质中心TMQ的专栏

Android内存泄露测试不再蓝瘦,香菇

在进行Android内存泄露分析时,面对成千上万个对象,你是否蓝瘦,香菇?作为测试人员你在进行内存泄露测试之后,是否有勇气告诉开发同事程序已经没有内存泄露,可以...

32170
来自专栏大数据文摘

业界 | Dropbox力荐!我们如何应对Python桌面应用程序的崩溃

揭秘Crashpad系统如何帮助Dropbox这样复杂的桌面程序捕获并报告崩溃,且兼容Python的多种语言。

11110
来自专栏進无尽的文章

多线程-概述及底层实现机制浅析

在打算写这篇多线层底层实现机制的时候,突然发现自己对于计算机竟然懂得这么表面,对于CPU的工作原理都不完全清楚,于是又转头查看了一些CPU相关的资料。也不敢钻的...

21810
来自专栏IT大咖说

VMware vSAN 架构解析及存储策略

摘要 VMware vSAN 通过 vSphere 原生的高性能体系结构支持业界领先的超融合基础架构解决方案。 vSAN是 Software-Defined D...

61630
来自专栏Android开发实战

警告:Android P(禁用非官方API)

Android P(禁用非官方API)目前类似的消息此起彼伏,关于国外移动开发者社区 XDA 的活跃者们在 AOSP(Android 开放源代码...

34830
来自专栏生信宝典

测序文章数据上传找哪里

在我们发表高通量测序文章之前通常要上传测序数据到GEO数据库,现总结流程如下。 注册账户、填写MetaSheet 在NCBI GEO官网注册一个账号,然后登陆。...

25560
来自专栏linux、Python学习

Linux吃掉了我的内存

在Windows下资源管理器查看内存使用的情况,如果使用率达到80%以上,再运行大程序就能感觉到系统不流畅了,因为在内存紧缺的情况下使用交换分区,频繁地从磁盘上...

22250
来自专栏Android群英传

Android NDK层发起HTTP请求的问题及解决

12620
来自专栏美团技术团队

Lego:美团点评接口自动化测试实践

概述 接口自动化概述 众所周知,接口自动化测试有着如下特点: 低投入,高产出。 比较容易实现自动化。 和UI自动化测试相比更加稳定。 如何做好一个接口自动化测试...

1.5K130
来自专栏JAVA高级架构

JVM内存管理--计算机内存和Java内存组件

JVM一向很好的帮我们管理内存,它就是一个贤内助:“向政府(内存空间)能要到地盘,还能有效的对自己的一亩三分地进行管理。”但是有时候呢,我们不懂怜香惜玉的一而再...

404140

扫码关注云+社区

领取腾讯云代金券