zoukankan      html  css  js  c++  java
  • 【python】抄写爬淘宝已买到的宝贝的代码

    教程地址:http://cuiqingcai.com/1076.html

    这一篇掌握的不好。虽然代码可以跑,但是里面的很多东西都一知半解。需要有空的时候系统整理。

    原代码中的正则表达式已经失效了,我自己又重新写的。

    知识点:

    1.cookie的使用

    2.验证码的处理,填写后的提交方式

    3.浏览器打开页面

    4.提交的表单信息可以通过火狐浏览器中  F12-网络-POST方法-参数-表单数据 来获得。

    疑问:

    1.无法获取翻页信息,只能重复的输出第一页信息。且第一页信息不全。

    2.一次性下了多个订单时,只显示第一个。

    3.为何用gbk解码? 

    4.为何正则表达式中用 u****的编码形式,而不是直接写汉字?

    5.为何谷歌浏览器和火狐浏览器用F12看到的内容不一样?谷歌浏览器的要长很多,结构非常复杂,且没有明晰的关键字,都是0.2.3.1这样的东西;火狐浏览器的关键字就比较明了,但结构不好,内容都写在同一行里。

    6.用到的很多中转的url不知道是怎么来的?我用这些url可以得到正确的内容,但是我自己的浏览器上的url跟代码中的不同。这是为什么??

    7.ua, st, token是什么?为什么要这些?如何知道登陆时需要哪些信息?

    8.stURL怎么来的?教程中说直接用

        https://login.taobao.com/member/vst.htm?st=1uynJELa4hKfsfWU3OjPJCw&TPL_username=cqcre

      的形式可以直接打开登陆后的页面,可是我获取了st,并输入我自己的用户名,结果在浏览器中登陆失败。可是代码中确实可以成功。为什么?

    9. 为什么通过 pattern = re.compile('top.location = "(.*?)"', re.S) 就可以判断是否登陆成功?我在浏览器中,分别尝试登陆和未登录情况,都不能获得top.location这个关键字。

    10.已买到的宝贝的url,代码中的和实际浏览器中显示的不同。且代码中无法获取翻页后的信息。

         代码中的是:'http://buyer.trade.taobao.com/trade/itemlist/listBoughtItems.htm?action=itemlist/QueryAction&event_submit_do_query=1' + '&pageNum=' + str(pageIndex)

         浏览器中的是:https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm?spm=xxxx.xxxxxxxxx.xxxxxxx.x.xxxxxxx

       spm的用途:导购效果跟踪http://open.taobao.com/doc2/detail.htm?articleId=959&docType=1&treeId=null

    整体代码如下:(一些个人信息我删掉了)

    import urllib.request
    import urllib.parse
    import re
    import http.cookiejar
    import webbrowser
    
    #处理获得的宝贝页面
    class Tool:
        #初始化
        def __init__(self):
            pass
        
        #获得页码数
        def getPageNum(self,page):
            pattern = re.compile('"totalPage":(.*?)}',re.S)
            result = re.search(pattern,page)
            if result:
                print("找到了共多少页")
                pageNum = result.group(1).strip()
                print('',pageNum,'')
                return pageNum
        def getGoodsInfo(self,page):
            #u'u8ba2u5355u53f7'是订单号的编码
            pattern = re.compile(u'createTime":"(.*?)","id":"(.*?)".*?"shopName":"(.*?)".*?snapUrl.*?"title":"(.*?)".*?priceInfo":{"original":"(.*?)".*?"realTotal":"(.*?)".*?"quantity":"(.*?)"', re.S)
            #pattern = re.compile(u'dealtime.*?>(.*?)</span>.*?u8ba2u5355u53f7.*?<em>(.*?)</em>.*?shopname.*?title="(.*?)".*?baobei-name">.*?<a.*?>(.*?)</a>.*?'
            #                    u'price.*?title="(.*?)".*?quantity.*?title="(.*?)".*?amount.*?em.*?>(.*?)</em>.*?trade-status.*?<a.*?>(.*?)</a>',re.S)
            result = re.findall(pattern,page)
            for item in result:
                print('------------------------------------------------------------')
                print("购买日期:",item[0].strip(), '订单号:',item[1].strip(),'卖家店铺:',item[2].strip())
                print('宝贝名称:',item[3].strip())
                print('原价:',item[4].strip(),'购买数量:',item[6].strip(),'实际支付:',item[5].strip())
    
    
    #模拟登陆淘宝类
    class Taobao:
        #初始化方法
        def __init__(self):
            #登陆的URL
            self.loginURL = "https://login.taobao.com/member/login.jhtml"
            #代理IP地址,防止自己的IP被封禁
            self.proxyURL = 'http://120.193.146.97:843'
            #登陆POST数据时发送的头部信息
            self.loginHeaders = {
            'Host':'login.taobao.com',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0',
            'Referer':'https://login.taobao.com/member/login.jhtml',
            'Content-Type':'application/x-www-form-urlencoded',
            'Connection':'keep-alive'
            }
            #用户名
            self.username = '自己的用户名'
            #ua字符串,经过淘宝ua算法计算得出,包含了时间戳,浏览器,屏幕分辨率,随机数,鼠标移动,鼠标点击,其实还有键盘输入记录,鼠标移动的记录、点击的记录等等的信息
            self.ua = '自己获取'
            #密码
            self.password2 = '自己获取'
            #post的数据就是F12后网络-POST方法-参数-表单数据 里的全部内容
            self.post = post = {
            'ua':self.ua,
            'TPL_username':self.username,
            'TPL_password':"",
            'TPL_checkcode':"",
            'loginsite':"0",
            'newlogin':"0",
            'TPL_redirect_url':"https://www.taobao.com/?spm=axxxxxxxxxxxxxx",
            'from':"tbTop",
            'fc':"default",
            'style':"default",
            'css_style':"",
            'keyLogin':"false",
            'qrLogin':"true",
            'newMini':"false",
            'tid':"",
            'support':"000001",
            'CtrlVersion':"1,0,0,7",
            'loginType':"3",
            'minititle':"",
            'minipara':"",
            'umto':"NaN",
            'pstrong':"",
            'sign':"",
            'need_sign':"",
            'isIgnore':"",
            'full_redirect':"",
            'popid':"",
            'callback':"",
            'guf':"",
            'not_duplite_str':"",
            'need_user_id':"",
            'poy':"",
            'gvfdcname':"10",
            'gvfdcre':"xxxxxxxxxxxxxxxxxxx",
            'from_encoding':"",
            'sub':"",
            'TPL_password_2':self.password2,
            'loginASR':"1",
            'loginASRSuc':"1",
            'allp':"",
            'oslanguage':"zh-CN",
            'sr':"1366*768",
            'osVer':"windows|6.3",
            'naviVer':"firefox|41"
            }
            #将POST的数据进行编码转换
            self.postData = urllib.parse.urlencode(self.post).encode(encoding='UTF8')
            #设置代理
            self.proxy = urllib.request.ProxyHandler({'http':self.proxyURL})
            #设置cookie
            self.cookie = http.cookiejar.CookieJar()
            #设置cookie处理器
            self.cookieHandler = urllib.request.HTTPCookieProcessor(self.cookie)
            #设置登陆用到的opener
            self.opener = urllib.request.build_opener(self.cookieHandler,self.proxy,urllib.request.HTTPHandler)
            #赋值J_HToken
            self.J_HToken = ''
            #登陆成功时,需要的Cookie
            self.newCookie = http.cookiejar.CookieJar()
            #登陆成功时,需要一个新的opener
            self.newOpener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.newCookie))
            #引入工具类
            self.tool = Tool()
            
        #得到是否需要输入验证码,有时需要,有时不需要
        def needIdenCode(self):
            #第一次登陆获取验证码尝试,构建request
            request = urllib.request.Request(self.loginURL,self.postData,self.loginHeaders)
            #得到第一次登陆尝试的响应
            response = self.opener.open(request)
            #获取其中的内容
            content = response.read().decode('gbk')
            #获取状态码
            status = response.getcode()
            #状态码为200,获取成功
            if status == 200:
                print(u"获取请求成功")
                #u8bf7u8f93u5165u9a8cu8bc1u7801这六个字是请输入验证码的utf-8编码
                pattern = re.compile(u'u8bf7u8f93u5165u9a8cu8bc1u7801', re.S)
                result = re.search(pattern, content)
                if result:
                    print(u"您需要输入验证码")
                    return content
                else:
                    print(u"不需要输入验证码")
                    #返回结果直接带有J_HToken,表明直接验证通过
                    tokenPattern = re.compile('id="J_HToken" value="(.*?)"')
                    tokenMatch = re.search(tokenPattern,content)
                    if tokenMatch:
                        self.J_HToken = tokenMatch.group(1)
                        print(u"此次安全验证通过,您这次不需要输入验证码")
                        return False
            else:
                print(u"获取请求失败")
                return None
        
        #得到验证码图片
        def getIdenCode(self, page):
            #得到验证码的图片
            pattern = re.compile('img id="J_StandardCode_m.*?data-src="(.*?)"',re.S)
            #匹配的结果
            matchResult = re.search(pattern, page)
            #已经匹配得到内容,并且验证码图片链接不为空
            if matchResult and matchResult.group(1):
                print(matchResult.group(1))
                return matchResult.group(1)
            else:
                print(u"没找到验证码内容")
                return False
        
        #输入验证码,重新请求,如果验证成功,则返回J_HToken
        def loginWithCheckCode(self):
            #提示用户输入验证码
            checkcode = input('请输入验证码:')
            self.post['TPL_checkcode'] = checkcode
            #对post数据重新进行编码
            self.postData = urllib.parse.urlencode(self.post).encode(encoding='UTF8')
            try:
                #再次构建请求,加入验证码之后的第二次登陆尝试
                request = urllib.request.Request(self.loginURL,self.postData,self.loginHeaders)
                #得到第一次登陆尝试的响应
                response = self.opener.open(request)
                #获取其中的内容
                content = response.read().decode('gbk')  #为什么这里是用gbk解码呢 如何判断解码格式?
                #检测验证码错误的正则表达式,u9a8cu8bc1u7801u9519u8bef 是验证码错误五个字的编码
                pattern = re.compile(u'u9a8cu8bc1u7801u9519u8bef',re.S)
                result = re.search(pattern,content)
                #如果返回页面包括了,验证码错误五个字
                if result:
                    print(u"验证码输入错误")
                    return False
                else:
                    #返回结果直接带有J_HToken字样,说明验证码输入成功,成功跳转到了获取HToken的界面
                    tokenPattern = re.compile('id="J_HToken" value="(.*?)"')
                    tokenMatch = re.search(tokenPattern,content)
                    #如果匹配成功,找到了J_HToken
                    if tokenMatch:
                        print(u"验证码输入正确")
                        print(tokenMatch.group(1))
                        self.J_HToken = tokenMatch.group(1)
                        return tokenMatch.group(1)
                    else:
                        print(u"J_HToken获取失败")
                        return False
            except urllib.error.HTTPError as e:
                print(u"连接服务器出错,错误原因",e.reason)
                return False
        
        #通过token获得st
        def getSTbyToken(self, token):
            #下面的URL怎么来的??
            tokenURL = 'https://passport.alipay.com/mini_apply_st.js?site=0&token=%s&callback=stCallback6' % token
            request = urllib.request.Request(tokenURL)
            response = urllib.request.urlopen(request)
            #处理st,获得用户淘宝主页的登陆地址
            pattern = re.compile('{"st":"(.*?)"}',re.S)
            result = re.search(pattern,response.read().decode('gbk')) #这里原本没有decode,但我觉得要加
            if result:
                print(u"获取st码成功")
                st = result.group(1)
                print(st)
                return st
            else:
                print(u"未找到st")
                return False
        
        #利用st码进行登陆,获取重定向网址
        def loginByST(self, st, username):
            stURL = 'https://login.taobao.com/member/vst.htm?st=%s&TPL_username=%s' % (st,username)
            headers = {
            'Host':'login.taobao.com',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0',
            'Connection':'keep-alive'
            }
            request = urllib.request.Request(stURL, headers = headers)
            response = self.newOpener.open(request)
            content = response.read().decode('gbk')
            #检测结果,看是否登陆成功
            pattern = re.compile('top.location = "(.*?)"', re.S)  #这里不懂??
            match = re.search(pattern, content)
            if match:
                print(u"登陆网址成功")
                location = match.group(1)
                return True
            else:
                print(u"登陆失败")
                return False
        
        #获得已买到的宝贝页面
        def getGoodsPage(self,pageIndex):
            goodsURL = 'http://buyer.trade.taobao.com/trade/itemlist/listBoughtItems.htm?action=itemlist/QueryAction&event_submit_do_query=1' + '&pageNum=' + str(pageIndex)
            response = self.newOpener.open(goodsURL)
            page =  response.read().decode('gbk')
            return page
        
        #获取所有已买到的宝贝信息
        def getAllGoods(self,pageNum):
            print(u"获取到的商品列表如下")
            for x in range(1,int(pageNum)+1):
                page = self.getGoodsPage(x)
                self.tool.getGoodsInfo(page)
        
        
        #程序运行主干
        def main(self):
            #是否需要验证码,是则得到页面内容,不是则返回False
            needResult = self.needIdenCode()
            if not needResult == None:
                if not needResult == False:
                    print(u"您需要手动输入验证码")
                    idenCode = self.getIdenCode(needResult)
                    if not idenCode == False:
                        print(u"获取验证码成功")
                        print(u"请在浏览器中输入您看到的验证码")
                        webbrowser.open_new_tab(idenCode)
                        self.loginWithCheckCode()
                    else:
                        print(u"验证码获取失败,请重试")
                else:
                    print("不需要输入验证码")
            else:
                print(u"请求登陆页面失败,无法确认是否需要验证码")
            
            #判断token是否正常获取到
            if not self.J_HToken:
                print(u"获取Token失败,请重试")
                return
            #获取st码
            st = self.getSTbyToken(self.J_HToken)
            #利用st进行登陆
            result = self.loginByST(st, self.username)
            if result:
                #获得所有宝贝的页面
                page = self.getGoodsPage(1)
                pageNum = self.tool.getPageNum(page)
                self.getAllGoods(pageNum)
            else:
                print(u"登陆失败")
    
    taobao = Taobao()
    taobao.main()
        
  • 相关阅读:
    用DirectX Audio和DirectShow播放声音和音乐(7)
    [转载]如何自学中医
    光照示例
    用DirectX Audio和DirectShow播放声音和音乐(5)
    DirectX 图形接口指南
    程序员的灯下黑:临渊羡鱼和退而织网
    使用DirectInput进行交互(3)
    Win32开发中最易踏上的地雷
    D3D中粒子效果实现示例
    用DirectX Audio和DirectShow播放声音和音乐(3)
  • 原文地址:https://www.cnblogs.com/dplearning/p/4859466.html
Copyright © 2011-2022 走看看