初试Scrapy(三)上---CSDN自动登录获取博客分类列表

初试Scrapy(三)上—CSDN自动登录获取博客分类列表

上一篇文章中初试Scrapy(二)—抓取豆瓣电影排行TOP250实验,通过Scrapy框架简单实现了一个豆瓣TOP250电影排行的小例子,这篇文章来学习下Scrapy框架下创建工程,同样我们给自己定一个小目标—实现CSDN自动登录,并且获取博客分类列表。为了不至于文章太长,这篇文章我打算分上下两篇,上篇主要是记录下不通过Scrapy框架实现CSDN自动登录获取博客分类列表,下篇文章中将完整的解释Scrapy创建文件的过程,并且对比实现CSDN自动登录获取博客分类列表功能。
废话不多说,直接上第一部分不通过Scrapy框架实现的代码:

# -*- coding: utf-8 -*-
from fake_useragent import UserAgent
import urllib
import urllib2
import cookielib
import re


class CsdnAutoLogin(object):
    def __init__(self, username, password):
        self.url = 'http://passport.csdn.net/account/login'
        self.username = username
        self.password = password
        self.error_info = ''
        self.login_status = 0
        # the redirect url , after login succeed
        self.redirect = ''
        self.opener = CsdnAutoLogin.create_cookie()

    @staticmethod
    def create_cookie():
        # '创建cookie'
        cookie = cookielib.CookieJar()
        cookie_proc = urllib2.HTTPCookieProcessor(cookie)
        return urllib2.build_opener(cookie_proc)

    def get_key_before_login(self):
        # '在登录之前获取随机key'
        html = self.opener.open(self.url).read().decode("utf8")
        patten1 = re.compile(r'name="lt" value="(.*?)"')
        patten2 = re.compile(r'name="execution" value="(.*?)"')
        lt = patten1.search(html)
        execution = patten2.search(html)
        return {'lt': lt.group(1), 'execution': execution.group(1)}

    @property
    def login(self):
        # '登录csdn'
        response = None
        # for random useragent
        ua = UserAgent()
        res = self.get_key_before_login()
        opener = self.opener
        post_data = {
            'username': self.username,
            'password': self.password,
            'lt': res['lt'],
            'execution': res['execution'],
            '_eventId': 'submit',
        }
        opener.addheaders = [('host', 'passport.csdn.net'),
                             ('User-Agent', ua.random),
                             ('Referer', 'http://passport.csdn.net/account/login')
                             ]
        post_data = urllib.urlencode(post_data).encode(encoding='UTF8')
        try:
            response = opener.open(self.url, data=post_data)
        except urllib2.URLError, err:
            print(err)
        finally:
            # HTTP Error 500: Internal Server Error
            if response is None:
                self.login_status = 0
                self.redirect = ''
                self.error_info = u'服务器错误 HTTP Error 500: Internal Server Error'
                raise Exception(self.error_info)
            else:
                text = response.read().decode('utf-8', 'ignore')
                pattenerror = u'<span id="error-message">帐户名或登录密码不正确'
                error = re.search(pattenerror, text)
                if error is None:
                    self.login_status = 1
                    patten = re.compile(r'var redirect = "(.*?)"')
                    self.redirect = patten.search(text).group(1)
                else:
                    self.login_status = 0
                    self.redirect = ''
                    self.error_info = u'帐户名或登录密码不正确'
                    raise Exception(self.error_info)

    def visit_redirect_after_login(self, redirect):
        # '在登录之后访问跳转'
        opener = self.opener
        response = opener.open(redirect)
        # text = response.read().decode('utf-8', 'ignore')
        # tools.log(text, 'csdn_test.html')
        response.read().decode('utf-8', 'ignore')

    def visit_blog_category(self):
        # '访问博客分类'
        opener = self.opener
        response = opener.open('http://write.blog.csdn.net/category')
        text = response.read().decode('utf-8', 'ignore')
        return CsdnAutoLogin.handle_blog_category(text)

    @staticmethod
    def handle_blog_category(text):
        # '处理博客分类'
        pattern = r"<td class='tdleft'><span>(.*?)</span></td>([\s\S]*?)<a href='#([0-9]+)'"
        matchs = re.findall(pattern, text)
        res = []
        if matchs:
            for i in matchs:
                res.append({'name': i[0], 'id': i[2]})
        return res

    def add_blog_category(self, name):
        # '添加博客分类,返回博客分类列表'
        opener = self.opener
        name = name.encode('utf-8', 'ignore')
        name = urllib.quote(name)
        url = 'http://write.blog.csdn.net/category?t=add&name=%s' % name
        response = opener.open(url)
        text = response.read().decode('utf-8', 'ignore')
        return CsdnAutoLogin.handle_blog_category(text)

    def edit_blog_category(self, blog_id, name):
        # '修改博客分类名称'
        opener = self.opener
        name = name.encode('utf-8', 'ignore')
        name = urllib.quote(name)
        url = 'http://write.blog.csdn.net/category?t=edit&id=%s&name=%s' % (blog_id, name)
        response = opener.open(url)
        text = response.read().decode('utf-8', 'ignore')
        return CsdnAutoLogin.handle_blog_category(text)

    def main(self):
        # '主方法'
        try:
            self.login
        except Exception, err:
            print(err.message)
        finally:
            if self.login_status == 1:
                # print(self.redirect)
                categorys = self.visit_blog_category()
                for i in categorys:
                    print(i['name'].encode("UTF-8"))


if __name__ == '__main__':
    csdn = CsdnAutoLogin('aaaaaaaaaaa', 'bbbbbbbbb')
    csdn.main()

我的Python版本是:Python 2.7.5代码参考网上一哥们实现的,修改然后测试通过。下面是在pycharm上运行的输出:

/usr/bin/python2.7 /home/james_xie/PycharmProjects/Csdn_AutoLogin/csdn_autologin.py
C/C++学习
Gstreamer学习
Qt 学习
计算机网络通信
交叉编译环境的建立
shell脚本学习
Android学习
Python学习

Process finished with exit code 0

由于程序大体上都是参考前人的,总体上没遇到什么难题,不过还是有几个问题折腾了一会:
1, user-agent问题,在网上https://pypi.python.org/pypi/fake-useragent找到这样一个库,完美解决之,但是第一次运行的时候会有点慢,因为这个库会在会在第一次运行的时候收集当前所有可用的user-agent保存到你的操作系统的临时目录下面如:/tmp。
2, 服务器返回“HTTP Error 500: Internal Server Error”错误,没有找到很好的解决办法,网上有遇到类似问题多说是服务器那边问题,通过上面加载fake-useragent库之后,这个问题几乎很少再出现,然后通过添加try...except语句来对这个问题进行捕捉,后面就没更深入的研究。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值