Python学习笔记_实战篇(一)_模拟登陆之下载

news2024/11/18 23:45:37

中间涉及到的技术点有:

  • 模拟登陆
  • 模拟下载
  • 解析exal文件数据流
  • 读取exal文件,拿出订单号
  • 还有最后一点请求接口

下面就给大家挨个说一下,刚拿到需求其实还是很模糊的,因为一个都没做过,等静下心来去理解的时候,发现并没有那么难,反而很简单

模拟登陆

一、分析页面请求头

本次登陆地址是https://huoche.alitrip.com/hello.htm

1、先登陆了一遍查看了一下请求头,发现就携带了三个东西,隐藏token,用户名,密码

一看一目了然,就一个后台页面,可想而知相对来说还是很简单,哈哈,下一步我只需要封装一下cookie,然后带上tocken,username,passwd去登陆咯

给大家说下,python的requests模块可以忽略cookie,自己创建一个session对象,他自己去给咱们匹配cookie,不用去挨个试cookie,这样就节省了好多代码和时间

2、代码如下

 class TbTomas(object):
    def __init__(self):
        # 配置初始化
        self.session_obj = requests.session()

    def download_file(self,thomas_username,thomas_password,):
        hello_url = 'https://huoche.alitrip.com/hello.htm'
        # 获取原文
        hello_response = self.session_obj.get(hello_url)
        # 正则匹配原文
        h_u_s = re_search('<input type="hidden" id="h_u_s" name="h_u_s" value="(.*?)">', hello_response.text)
        
        h_u_s = base64.b64encode(h_u_s)
        headers = {
            'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
            'Referer': 'https://huoche.alitrip.com/hello.htm',
            'Accept-Language': 'zh-CN',

            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586',
            'Content-Type': 'application/x-www-form-urlencoded',

            'Accept-Encoding': 'gzip, deflate',
            'Host': 'huoche.alitrip.com',
            'Content-Length': '73',
            'Connection': 'Keep-Alive',
            'Cache-Control': 'no-cache'
        }

        post_data = {
            'h_u_s': base64.b64encode(h_u_s),
            'h_u_n': thomas_username,
            'h_u_p': base64.b64encode(thomas_password)
        }
        index_url = 'https://huoche.alitrip.com/index.htm'
        index_response = self.session_obj.post(index_url, headers=headers, data=post_data)

最后一提交post请求,就可以判断有没有登录成功了,是不是很简单,哈哈!

数据下载

下载也是和登录是一样的道理,下载的时候肯定也是像网页发一个post请求,然后就回去下载exal文件咯,python有这么一个模块xlrd,可以去操作exal文件,非常方便

1、原文是让我们输入时间看,下载那一天的数据,领导给的任务是下载前一天的,所以上一天时间要写几行代码来实现

代码如下:

today = datetime.datetime.now()
yesterday = today + datetime.timedelta(days=-1)
trade_date = yesterday.strftime('%Y-%m-%d')

2、查看下载文件请求的url,以及提交的数据,一张图一切都明白了

从图中可以看到,该文发送的url,请求方式,请求头,和返回的数据

3、模拟请求下载,只需用提交一下日期就OK搞定,文件下载完毕,接下开要读文件拿自己想要的东西啦

        post_data = {
             'orderExportDate': trade_date
        }
        sheet_content = ""
        for _ in xrange(3):
            try:
                # 得到exal文件流
                download_response = self.session_obj.post(download_url, data=post_data)
                # 打开exal文件
                xls_content = xlrd.open_workbook(file_contents=download_response.content)
                sheet_content = xls_content.sheets()[0]
                break
            except Exception as e:
                continue

4、这个就众所周知,和读取文件一样,for循环一行一行读取,然后把订单号挨个添加给一个列表啥啦乱七八糟的

        order_item = []
         for line_num in range(sheet_content.nrows):
            line_item = sheet_content.row_values(line_num)
            if line_item[2]:
                order_item.append(line_item[2], )  # 订单号 order_no
        # 获取到所有订单号
        order_item = order_item[1:]

拿到订单号要去获取订单详情了,但是领导给我说这个已经有同事写好代码了,只需要调用那个接口就好,所以别人的代码我就不往上面展示了,原理很简单

requests模块,请求url,get传入订单号,发送请求,就可以返回数据咯,web页面展示,那个需求,每个公司都不一样,存入数据库,自己取自己想要的吧。

本文就到这里吧,学到一点东西的请点赞,哈哈

最后附带源码,用户名和密码就不告诉大家啦,啊哈哈

#!/usr/bin/python
# coding:utf-8
import sys
import os
import django

reload(sys)
sys.setdefaultencoding('utf8')
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))  # 把manage.py所在目录添加到系统目录
os.environ['DJANGO_SETTINGS_MODULE'] = 'business.settings'  # 设置setting文件
django.setup()  # 初始化Django环境

import requests
import re
import logging
import base64
import xlrd
import datetime
import time
import MySQLdb
import threadpool
from business import settings
from train.depends.platform import Platform
from train.models import TbTomasOrder,TbTomasEpay,TtTicketThomas,TbTomasLinkman
from train import utils
from train.status import OrderStatus
from django.core.mail import EmailMultiAlternatives
from train.busi import insert_order,insert_ticket,insert_epay,insert_linkman

logger = logging.getLogger('django')





class TbTomas(object):

    succ_number = 0
    fail_number = 0
    fail_order = []
    def __init__(self,thread_num = 3):
        # 配置初始化
        self.session_obj = requests.session()
        self.fail_order = []
        self.succ_number = 0
        self.fail_number = 0
        self.thread_num = thread_num
        self.start_date = ""
        self.end_date = ""
        self.trade_date = utils.now()

    def login_thomas(self,thomas_username,thomas_password):
        hello_url = 'https://huoche.alitrip.com/hello.htm'
        hello_response = self.session_obj.get(hello_url)
        h_u_s = re_search('<input type="hidden" id="h_u_s" name="h_u_s" value="(.*?)">', hello_response.text)
        h_u_s = base64.b64encode(h_u_s)
        headers = {
            'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
            'Referer': 'https://huoche.alitrip.com/hello.htm',
            'Accept-Language': 'zh-CN',

            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586',
            'Content-Type': 'application/x-www-form-urlencoded',

            'Accept-Encoding': 'gzip, deflate',
            'Host': 'huoche.alitrip.com',
            'Content-Length': '73',
            'Connection': 'Keep-Alive',
            'Cache-Control': 'no-cache'
        }

        post_data = {
            'h_u_s': base64.b64encode(h_u_s),
            'h_u_n': thomas_username,
            'h_u_p': base64.b64encode(thomas_password)
        }
        index_url = 'https://huoche.alitrip.com/index.htm'
        index_response = self.session_obj.post(index_url, headers=headers, data=post_data)
        logger.info(u"登陆成功,等待下载文件...")


    def download_file(self,thomas_username,thomas_password,args):
        for _ in xrange(3):
            try:
                self.login_thomas(thomas_username,thomas_password)
                break
            except Exception as e:
                logger.error(e)
                continue

        # 处理时间
        all_time = self.date_time_handle(args)
        if not all_time:
            logger.error(u"日期格式错误!!")
            return
        for trade_date in all_time:
            try:
                self.trade_date = trade_date
                post_data = {
                    'orderExportDate': trade_date
                }
                download_url = 'https://huoche.alitrip.com/orderlistexp.do'
                sheet_content = ""
                for _ in xrange(3):
                    try:
                        # 得到exal文件流
                        download_response = self.session_obj.post(download_url, data=post_data)
                        # 打开exal文件
                        xls_content = xlrd.open_workbook(file_contents=download_response.content)
                        sheet_content = xls_content.sheets()[0]
                        logger.info(u"下载文件成功,正在拿取订单号")
                        break
                    except Exception as e:
                        logger.error(u"下载文件超时,正在等待重新登录后下载...")
                        self.login_thomas(thomas_username, thomas_password)
                        continue
                order_item = []
                if not  sheet_content:
                    logger.error(u'下载文件失败,正在重新登录...')
                    continue
                for line_num in range(sheet_content.nrows):
                    line_item = sheet_content.row_values(line_num)
                    if line_item[2] and line_item[2] not in order_item:
                        order_item.append(line_item[2], )  # 订单号 order_no

                # 获取到所有订单号
                order_item = order_item[1:]
                # 根据订单号去拿订单详情
                logger.info(u"正在写入数据库")

                # 多线程去执行
                pool = threadpool.ThreadPool(self.thread_num)
                reqs = threadpool.makeRequests(self.create_order_info, order_item)
                [pool.putRequest(req) for req in reqs]
                pool.wait()
                logger.info(u'写入完成,完成时间为:%s'% self.trade_date)

                content = self.add_content(len(order_item), self.succ_number, self.fail_number, self.fail_order)
                self.send_mail(content=content)
                self.succ_number,self.fail_order = 0,0
                self.fail_order = []
                # self.create_order_info(order_item)
            except Exception as e:
                logger.error(e)
    def date_time_handle(self,args):
        all_time = []
        if args:
            if len(args) == 1:
                self.start_date = datetime.datetime.strptime(args[0], "%Y-%m-%d").date()
                self.end_date = datetime.datetime.strptime(datetime.datetime.now().strftime("%Y-%m-%d"), "%Y-%m-%d").date()
            elif len(args) == 2:
                self.start_date = datetime.datetime.strptime(args[0], "%Y-%m-%d").date()
                self.end_date = datetime.datetime.strptime(args[1], "%Y-%m-%d").date()
            elif len(args) == 3:
                self.start_date = datetime.datetime.strptime(args[0], "%Y-%m-%d").date()
                self.end_date = datetime.datetime.strptime(args[1], "%Y-%m-%d").date()
                self.thread_num = int(args[2])
            else:
                logger.error(u"传入参数错误,请重新执行")
                return
            i = 0
            while True:
                tomoary = self.start_date + datetime.timedelta(days=i)
                trade_date = tomoary.strftime('%Y-%m-%d')
                all_time.append(trade_date)
                i += 1
                if tomoary == self.end_date:
                    break
        else:
            today = datetime.datetime.now()
            yesterday = today + datetime.timedelta(days=-1)
            trade_date = yesterday.strftime('%Y-%m-%d')
            all_time.append(trade_date)
        return all_time

    def create_order_info(self, order):
        platform_obj = Platform()

        order_info = platform_obj.get_order(order)
        if not order_info:
            self.fail_order.append(order)
            self.fail_number += 1
            logger.error('获取订单号:[%s]失败'%order)
            return

        try:
            # 插入order表
            if TbTomasOrder.objects.filter(order_no=order).exists():
                logger.error('订单号:[%s]已经存在于TbTomasOrder'%order)
                self.fail_order.append(order)
                self.fail_number += 1
                return
            else:
                insert_order(order_info,order,self.trade_date)
                self.succ_number += 1

            # 插入ticket表
            insert_ticket(order_info,order,self.trade_date)

            # 插入联系人
            if TbTomasLinkman.objects.filter(order_no=order).exists():
                logger.error('订单号:[%s]已经存在于TbTomasLinkman'%order)
            else:
                insert_linkman(order_info,order,self.trade_date)

            # 插入epay表
            if TbTomasEpay.objects.filter(order_no=order).exists():
                logger.error('订单号:[%s]已经存在于TbTomasEpay'%order)
            else:
                insert_epay(order_info,order,self.trade_date)

        except Exception as e:
            logger.error(e)
            self.fail_number +=1



    def add_content(self,total,succ_number,fail_number,fail_order):
        content = u'''
        <h3>托马斯导入订单报表</h3>
        <div class="col-xs-12">
            <table border="1" cellpadding="3" cellspacing="1">
                <tr>
                    <td>日期</td>
                    <td>总单数</td>
                    <td>成功单数</td>
                    <td>失败单数</td>
                    <td>失败订单号</td>
                </tr>
                <tr>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                </tr>
            </table>
        </div>
        '''%(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),total,succ_number,fail_number,fail_order)
        return content

    def send_mail(self, content):
        time_target = self.trade_date
        subject = u'托马斯数据抓取邮件 %s' % (time_target)

        logger.info(u'准备发送邮件....%s', subject)
        mail_address = settings.mail_address_thomas

        to_addr = []

        if isinstance(mail_address, list):
            to_addr += mail_address
        elif isinstance(mail_address, str):
            to_addr.append(mail_address)

        logger.debug(to_addr)

        from_email = settings.DEFAULT_FROM_EMAIL
        msg = EmailMultiAlternatives(subject, 'result', from_email, to_addr)
        msg.attach_alternative(content, "text/html")
        flag = msg.send()
        if flag:
            logger.info(u'%s发送成功', subject)
        else:
            logger.error(u'%s发送失败', subject)
        return

    def run(self, username,passwd,args):
        # 登陆托马斯后台
        for _ in xrange(3):
            try:
                self.download_file(username,passwd,args)
                break
            except Exception as e:
                logger.error(e)
                continue


def re_search(regex, subject):
    subject = str(subject)
    obj = re.compile(regex)
    match = obj.search(subject)
    if match:
        result = match.group(1)
    else:
        result = ''
    return result


def main():
    username = base64.b64decode(settings.THOMAS_USERNAME)
    passwd = base64.b64decode(settings.THOMAS_PASSWORD)
    args = sys.argv[1:] if sys.argv[1:] else ""
    TbTomas().run(username,passwd,args)


if __name__ == "__main__":
    main()

thread_code

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/905582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux中shell脚本——for、while循环及脚本练习

目录 一.for循环 1.1.基本格式 1.2.类C语言格式 二.while循环 2.1.基本格式 2.2.死循环语句 三.跳出循环 3.1.continue跳出循环 3.2.break跳出循环 四.常用循环 4.1.循环打印九九乘法表 4.2.循环ping测试某个网段网络连通性 4.3.while死循环实现猜数字游戏 4.4.数…

springboot之多数据源配置

文章目录 一、多数据源的典型使用场景1 业务复杂&#xff08;数据量大&#xff09;2 读写分离 二、如何实现多数据源通过AbstractRoutingDataSource动态指定数据源多数据源切换方式AOPMyBatis插件 三、spring集成多个Mybatis框架 实现多数据源控制四、dynamic-datasource 多数据…

YOLO目标检测算法训练过程学习记录

先前已经完成过YOLO系列目标检测算法的调试过程&#xff0c;今天主要是将所有的调试加以总结 这里的conda环境就不再赘述了&#xff0c;直接使用requirement.txt文件的即可&#xff0c;也可以参考YOLOX的配置过程5 数据集处理 YOLOv5有自己的数据集格式&#xff0c;博主的数据…

70 # 协商缓存的配置:通过修改时间

对比&#xff08;协商&#xff09;缓存 比较一下再去决定是用缓存还是重新获取数据&#xff0c;这样会减少网络请求&#xff0c;提高性能。 对比缓存的工作原理 客户端第一次请求服务器的时候&#xff0c;服务器会把数据进行缓存&#xff0c;同时会生成一个缓存标识符&#…

iOS_Crash报告的组成结构

崩溃报告结构如下&#xff0c;每个部分都包含可帮助定位崩溃位置的信息&#xff1a; 1. Header 描述崩溃发生的环境&#xff0c;包含设备、系统、时间、版本等信息。如&#xff1a; Incident Identifier: 6156848E-344E-4D9E-84E0-87AFD0D0AE7B CrashReporter Key: 76f2fb…

【C++STL基础入门】深入浅出string类insert和appand

文章目录 前言一、插入1.中间插入2.尾巴插入拼接appand 总结 前言 本系列STL是使用vs2022C20版本特性来写的。 在C标准模板库&#xff08;STL&#xff09;的众多容器中&#xff0c;string类是处理字符串的重要工具。它提供了丰富的函数和操作符&#xff0c;使得字符串的操作…

真机二阶段之堆叠技术

堆叠技术 --- 可以将多台真实的物理设备逻辑上抽象成一台 思科 -- VPC 华为 -- iStack和CSS 华三 -- IRF 锐捷 -- VSU iStack和CSS的区别&#xff1a; CSS --- 集群 --- 它仅支持将两台支持集群的交换机逻辑上整合成一台设备。 iStack --- 堆叠 --- 可以将多台支持堆叠的交换…

Agile Iteration Velocity

【agile iteration velocity】敏捷速度指的平均速度 第四次迭代结束速度&#xff1a; 76 / 4 19 第五次迭代结束速度&#xff1a; &#xff08;76 24 &#xff09; / 5 100 / 5 20

【地理专题】2023年最新全国A级景区数

数据来源&#xff1a;中国文化和旅游部时间跨度&#xff1a;2023年区域范围&#xff1a;全国范围数据字段&#xff1a; 景区名称&#xff1b;地址&#xff1b;等级&#xff1b;城市&#xff1b;经度&#xff1b;纬度 该图基于自然资源部地图技术审查中心标准地图服务网站下载…

The internal rate of return (IRR)

内部收益率 NPV(Net Present Value)_spencer_tseng的博客-CSDN博客

华为网络篇 OSPF的Silent-Interface-33

难度1复杂度1 目录 一、实验拓扑 二、实验步骤 三、实验过程 总结 一、实验拓扑 二、实验步骤 1.搭建如图所示的网络拓扑&#xff1b; 2.初始化各设备&#xff0c;配置相应的IP地址&#xff0c;测试直连网络的连通性&#xff1b; 3.整个网络配置OSPF协议&#xff0c;查看…

使用预制体画刷在游戏场景中快速布置预制体、粒子特效等

有时候在使用tilemap的时候&#xff0c;会希望在场景中添加更复杂的对象。 在2d-extras中&#xff0c;加入了预制件笔刷&#xff08;Prefab Brush&#xff09;&#xff0c;可以将游戏物体预制体作为瓦片&#xff0c;来方便的在游戏场景中快速的绘制。可以自动适应游戏物体的位置…

Docker容器:docker镜像的创建及dockerfile

Docker容器&#xff1a;docker镜像的创建及dockerfile案例 一.docker镜像的三种创建方法 创建镜像有三种方法&#xff1a;基于现有镜像创建、基于本地模板创建及基于dockerfile创建 1.基于现有镜像创建 1.1 启动镜像 #首先启动一个镜像&#xff0c;在容器里做修改 docker …

Linux笔试题(1)

1、以长格式列目录时&#xff0c;若文件test的权限描述为&#xff1a;drwxrw-r–&#xff0c;则文件test的类型及文件主的权限是__A____。 A.目录文件、读写执行 B.目录文件、读写 C.普通文件、读写 D.普通文件、读 在这个问题中&#xff0c;我们需要解析文件权限的描述&…

Java面向对象三大特性之多态及综合练习

1.1 多态的形式 多态是继封装、继承之后&#xff0c;面向对象的第三大特性。 多态是出现在继承或者实现关系中的。 多态体现的格式&#xff1a; 父类类型 变量名 new 子类/实现类构造器; 变量名.方法名(); 多态的前提&#xff1a;有继承关系&#xff0c;子类对象是可以赋…

Android11 中 LED 使用-RK3568

文章目录 前言原理图设备树驱动前言 现在我们来学习点亮LED 原理图 然后对应在核心板原理图上查找 Working_LEDEN_H_GPIO0_B7,如下图所示: 那么我们只要控制 GPIO0_B7 即可控制 led 的亮灭。 设备树 leds: leds {compatible = "gpio-leds";work_led: work {gpi…

AgentBench——AI智能体基准测试官方

ModaGPT 简介 排行榜 提交模型 提问 AgentBench是第一个系统性的基准测试,用于评估LLM作为智能体在各种真实世界挑战和8个不同环境中的表现。 Models

shell脚本——文件三剑客之grep

一.grep选项 -A<显示行数>&#xff1a;除了显示符合样式的那一列之外&#xff0c;并显示该行之后的内容&#xff0c;下几行内容&#xff0c;本行也会显示 -B<显示行数>&#xff1a;除了显示符合样式的那一行之外&#xff0c;并显示该行之前的内容&#xff0c;上几行…

回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介…

【脚踢数据结构】常见树总结(图码结和版)

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;软件配置等领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff01;送给自己和读者的…