Flask框架小程序后端分离开发学习笔记《4》向服务器端发送模拟请求-爬虫

news/2024/7/20 3:01:48 标签: flask, 小程序, 学习

Flask框架小程序后端分离开发学习笔记《4》向服务器端发送模拟请求-爬虫

Flask是使用python的后端,由于小程序需要后端开发,遂学习一下后端开发。
下面代码,是一个比较老的版本了,可以借鉴一下。

import socket
import ssl


def parsed_url(url):
    #检查协议
    protocol = 'http'
    if url[:7] == 'http://':
        u = url.split('://')[1]
    elif url[:8] == 'https://':
        protocol = 'https'
        u = url.split('://')[1]
    else:
        #':/l '定位然后取第一个/的位置来切片
        u = url
    # 经过这样,url中的协议被切掉了,注意切片后数组下标由0开始
    # 例如 https://www.baidu.com:2024/apple
    # 切除后 www.baidu.com:2024/apple


    # 检查默认path
    i = u.find('/')
    if i == -1:
        host = u
        path ='/'
    else:
        host = u[:i]
        path = u[i:]
    # 这一步处理过后
    # host = www.baidu.com:2024
    # path = apple


    # 检查端口
    # 默认端口
    port_dict = {
        'http': 80,
        'https': 443,
    }
    # 非默认端口
    port = port_dict[protocol]
    if ':' in host:
        h = host.split(':')
        # print(h)  测试用,当控制台说哪有问题,阔以尝试使用打印大法,看看是啥问题
        host = h[0]
        port = int(h[1])
    return protocol, host, port, path


#以下test开头的函数是单元测试
def test_parsed_url():
    #parsed_url函数很容易出错,所以我们写测试函数来运行看检测是否正确运m
    http = 'http'
    https = 'https'
    host = 'g.cn'
    path = '/'
    test_items = [
        ('http://g.cn', (http,host,80,path)),
        ('http://g.cn/', (http,host,80,path)),
        ('http://g.cn:90',(http, host,90,path)),
        ('http://g.cn:90/', (http,host, 90,path)),

        # 这里面的都是典型测试用例即可
        ('https://g.cn', (https,host,443,path)),
        ('https://g.cn:233/',(https,host,233,path)),
    ]

    for t in test_items:
        url, expected = t
        u = parsed_url(url)
        # assert是一个语句,名字叫断言
        # 如果断言成功,条件成立,则通过测试,否则为测试失败,中断程序报错
        e = "parsed_url ERROR,{}{}{}".format(url,u,expected)
        assert u == expected, e    # 如果u == expected为true,就没问题,继续;否则就会中断,然后打印e
        # print("test_parsed_url测试通过!")


def socket_by_protocol(protocol,host):
    # 根据协议返回一个socket实例
    s = socket.socket()
    if protocol == 'https':
        # 创建一个默认的SSL上下文环境
        context = ssl.create_default_context()
        # 使用SSL上下文环境来包装socket对象
        s = context.wrap_socket(s, server_hostname=host)
    return s

def response_by_socket(s):
    # 持续接收响应,返回响应的byte型
    # 参数是一个socket实例
    # 返回这个socket读取的所有数据
    response = b''
    buffer_size = 1024
    while True:
        r = s.recv(buffer_size)
        if len(r) == 0:
            break
        response += r
    return response

def parsed_response(r):
    # 把response解析出状态码headers body返回
    # 状态码是int
    # headers 是dict
    # body是str
    header, body = r.split('\r\n\r\n',1)     # \r\n\r\n是其分界线
    h = header.split('\r\n')   # 就会切分很多行  例如:HTTP/1.1 301 Moved Permanently
    status_code = h[0].split()[1]   # h[0]就是响应行 status_code=301  按照空格切分
    status_code = int(status_code)

    headers = {}
    for line in h[1:]:   # 把响应Header部分每一行都存成字典
        k, v = line.split(': ')
        headers[k] = v
    return status_code, headers, body


def get(url):
    # 用GET请求url并返回响应
    protocol,host,port,path= parsed_url(url)

    # 因为协议不一样,socket实例构建方式不同
    s = socket_by_protocol(protocol,host)
    s.connect((host,port))
    request = 'GET HTTP/1.1\r\nhost: {}\r\nconnectibn: close\r\n\r\n'.format(path,host)
    encoding = 'utf-8'
    s.send(request.encode(encoding))

    response = response_by_socket(s)
    r = response.decode(encoding)

    # 利用parsed_response处理接收到的响应,分别得到想要的东西
    status_code, headers, body = parsed_response(r)
    if status_code in [301, 302]:     # 301、302说明是需要重定向
        url = headers['Location']
        return get(url)

    return status_code, headers, body

def test_get():
    # 测试是否能正确处理HTTP和HTTPS
    urls = [
        'http://movie.douban.com/top250',
        'https://movie.douban.com/top250',
    ]
    # 这里就直接调用了get如果出错就会挂,测试得比较简单
    for u in urls:
        status_code, headers, body = get(u)
        print(status_code,headers,body)


def test():
    # 用于测试的主函数
    test_parsed_url()
    test_get()
    # test_parsed_response()

if __name__ == '__main__':
    test()
    # main()


# 代码注意模块化,写what不写how,不写具体怎么实现,具体怎么实现就封装起来

最后尝试请求豆瓣的网页,并未得到,我怀疑是有反爬手段,我们的请求数据还有很多东西没加进去,所以看起来不像是浏览器发送的请求,后续会继续学习,解决这个问题。


http://www.niftyadmin.cn/n/5335797.html

相关文章

【鸿蒙4.0】harmonyos Day 04

文章目录 一.Button按钮组件1.声明Button组件,label是按钮文字2.添加属性和事件 二.Slider滑动条组件 一.Button按钮组件 1.声明Button组件,label是按钮文字 Button(label?:ResourceStr) // ResourceStr:可以是普通字符串,也可以是引用定义…

大数据Hadoop入门——HDFS分布式文件系统基础

HDFS总结 在现代的企业环境中,海量数据超过单台物理计算机的存储能力,分布式文件系统应运而生,对数据分区存储于若干物理主机,管理网络中跨多台计算机存储的文件系统。 HDFS只是分布式文件管理系统中的一种。 HDFS命令 基础语法…

MeterSphere本地化部署实践

项目结构 搭建本地环境 安装JDK11,配置好JDK环境,系统同时支持JDK8和JDK11安装IEAD,配置JDK环境配置maven环境,IDEA配置(解压可以直接使用)无限重置IDEA试用期配置redis环境(解压可以直接使用) 配置kafka环境 安装mysql-5.7环境&#xff…

使用 Swift 代码优化项目编译速度

引言 软件的性能是评价一个软件质量的重要指标,尤其在今天这个时代,性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件,如网银系统、在线购物商城等,更是必须保证其高效稳定的性能。在这种背景下,优化…

分布式ID(2):雪花算法生成ID

1 雪花算法简介 这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间等,比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示: 41-bit的时间可以表示(1L&l…

TypeScript语法总结

JavaScript 与 TypeScript 的区别 TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已…

Spring.Shell.History内置命令覆盖

文章目录 问题解决方案覆盖方法代码yaml配置:指定保存历史命令文件的路径 问题 最近工作上遇到的一个小问题,在Spring Shell中,我们可以自己定义一些命令,已完成我们想要的功能,也可以使用内置命令如help、history、c…

HBase学习五:运维排障

1、负载均衡 1.1 Rgion迁移 在当前的HBase版本中,Region迁移虽然是一个轻量级操作,但实现逻辑依然比较复杂,≈复杂性主要表现在两个方面:其一,Region迁移过程涉及多种状态的改变;其二,迁移过程中涉及Master、ZooKeeper(ZK)以及RegionServer等多个组件的相互协调。 …