精华内容
下载资源
问答
  • 于是,便采取以下方法实现在没有Internet连接的server上安装Python第三方库: 先准备一个能连接Internet网络的server:server A, 该server配置与要部署的内网server一致 下载pip...

    在本地用Python + Flask开发了个web应用,要部署到内网的server上,内网的server默认只安装了Python2.6, 没有Internet网络连接,不能直接安装Flask库。于是,便采取以下方法实现在没有Internet连接的server上安装Python第三方库:
    先准备一个能连接Internet网络的server:server A, 该server配置与要部署的内网server一致

    1. 下载pip(https://pypi.org/project/pip/#files): pip-20.1.1.tar.gz
    2. 上传至server A
    3. 解压: tar -xvf pip-20.1.1.tar.gz
    4. 安装pip:
      sudo su -
      cd pip-20.1.1
      python setup.py install
      备注: 我的server A上没有pip,所以要先安装pip。如果server A上已经安装有pip,则1-4 步可以省略
    5. pip安装flask: pip install flask
    6. 将安装的所有依赖包list到文件中(可以在装之前生成一个list,装之后再生个list,做个对比,只需要新增的依赖包):pip freeze > flask_modules.txt
    7. 创建依赖包目录:mkdir python_packages
    8. 根据list文件下载所有依赖包: pip download -r flask_modules.txt -d ./python_packages
    9. 将下载完的文件夹打包: mv flask_modules.txt python_packages/ && tar -czf python_packages.tar.gz python_packages
    10. 将压缩文件python_packages.tar.gz上传到最终要部署的内网server(该服务器如果没有 pip, 要先安装pip,参考上面的步骤1-4)
    11. 解压python_packages.tar.gz: tar -xvf python_packages.tar.gz
    12. 安装依赖包即可: cd python_packages && pip install --no-index --find-links=file:. -r flask_modules.txt
    展开全文
  • 前言 更多内容,请访问我的 个人博客。 Python 访问网络资源有很多方法,urllib, urllib2, urllib3, httplib, httplib2, requests ,现介绍如下两种方法: ...内置的 urllib 模块 ...缺点:需要下载安装第三方...

    前言

    更多内容,请访问我的 个人博客


    Python 访问网络资源有很多方法,urllib, urllib2, urllib3, httplib, httplib2, requests ,现介绍如下两种方法:

    • 内置的 urllib 模块
      • 优点:自带模块,无需额外下载第三方库
      • 缺点:操作繁琐,缺少高级功能
    • 第三方库 requests
      • 优点:处理URL资源特别方便
      • 缺点:需要下载安装第三方库

    内置的 urllib 模块

    发起GET请求

    主要使用urlopen()方法来发起请求,如下:

    from urllib import request
    
    resp = request.urlopen('http://www.baidu.com')
    print(resp.read().decode())
    

    访问的结果会是一 个http.client.HTTPResponse 对象,使用此对象的 read() 方法,则可以获取访问网页获得的数据。但是要注意的是,获得的数据会是 bytes 的二进制格式,所以需要 decode() 一下,转换成字符串格式。

    发起POST请求

    urlopen() 默认的访问方式是GET,当在 urlopen() 方法中传入data参数时,则会发起POST请求。注意:传递的data数据需要为bytes格式。

    设置timeout参数还可以设置超时时间,如果请求时间超出,那么就会抛出异常。如下:

    from urllib import request
    
    resp = request.urlopen('http://www.baidu.com', data=b'word=hello', timeout=10)
    print(resp.read().decode())
    

    添加Headers

    通过 urllib 发起的请求会有默认的一个Headers:“User-Agent”:“Python-urllib/3.6”,指明请求是由 urllib 发送的。
    所以遇到一些验证User-Agent的网站时,我们需要自定义Headers,而这需要借助于urllib.request中的 Request 对象。

    from urllib import request
    
    url = 'http://httpbin.org/get'
    headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'}
    
    # 需要使用url和headers生成一个Request对象,然后将其传入urlopen方法中
    req = request.Request(url, headers=headers)
    resp = request.urlopen(req)
    print(resp.read().decode())
    

    Request对象

    如上所示, urlopen() 方法中不止可以传入字符串格式的url,也可以传入一个 Request 对象来扩展功能,Request 对象如下:

    class urllib.request.Request(url, data=None, headers={},
                                    origin_req_host=None,
                                    unverifiable=False, 
                                    method=None)
    

    构造 Request 对象必须传入url参数,data数据和headers都是可选的。

    最后, Request 方法可以使用method参数来自由选择请求的方法,如PUT,DELETE等等,默认为GET。

    添加Cookie

    为了在请求时能带上Cookie信息,我们需要重新构造一个opener。

    使用request.build_opener方法来进行构造opener,将我们想要传递的cookie配置到opener中,然后使用这个opener的open方法来发起请求。如下:

    from http import cookiejar
    from urllib import request
    
    url = 'https://www.baidu.com'
    # 创建一个cookiejar对象
    cookie = cookiejar.CookieJar()
    # 使用HTTPCookieProcessor创建cookie处理器
    cookies = request.HTTPCookieProcessor(cookie)
    # 并以它为参数创建Opener对象
    opener = request.build_opener(cookies)
    # 使用这个opener来发起请求
    resp = opener.open(url)
    
    # 查看之前的cookie对象,则可以看到访问百度获得的cookie
    for i in cookie:
        print(i)
    

    或者也可以把这个生成的opener使用install_opener方法来设置为全局的。

    则之后使用urlopen方法发起请求时,都会带上这个cookie。

    # 将这个opener设置为全局的opener
    request.install_opener(opener)
    resp = request.urlopen(url)
    

    设置Proxy代理

    使用爬虫来爬取数据的时候,常常需要使用代理来隐藏我们的真实IP。如下:

    from urllib import request
    
    url = 'http://www.baidu.com'
    proxy = {'http':'222.222.222.222:80','https':'222.222.222.222:80'}
    # 创建代理处理器
    proxies = request.ProxyHandler(proxy)
    # 创建opener对象
    opener = request.build_opener(proxies)
    
    resp = opener.open(url)
    print(resp.read().decode())
    

    下载数据到本地

    在我们进行网络请求时常常需要保存图片或音频等数据到本地,一种方法是使用python的文件操作,将read()获取的数据保存到文件中。

    而urllib提供了一个urlretrieve()方法,可以简单的直接将请求获取的数据保存成文件。如下:

    from urllib import request
    
    url = 'http://python.org/'
    request.urlretrieve(url, 'python.html')
    

    urlretrieve() 方法传入的第二个参数为文件保存的位置,以及文件名。

    注意:urlretrieve() 方法是python2直接移植过来的方法,以后有可能在某个版本中弃用。

    第三方库 requests

    安装

    由于 requests是第三方库,所以要先安装,如下:

    pip install requests
    

    发起GET请求

    直接用 get 方法,如下:

    import requests
    
    r = requests.get('http://www.baidu.com/')
    print(r.status_code)    #状态
    print(r.text)   #内容
    

    对于带参数的URL,传入一个dict作为params参数,如下:

    import requests
    
    r = requests.get('http://www.baidu.com/', params={'q': 'python', 'cat': '1001'})
    print(r.url)    #实际请求的URL
    print(r.text)
    

    requests的方便之处还在于,对于特定类型的响应,例如JSON,可以直接获取,如下:

    r = requests.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json')
    r.json()
    
    # {'query': {'count': 1, 'created': '2017-11-17T07:14:12Z', ...
    

    添加Headers

    需要传入HTTP Header时,我们传入一个dict作为headers参数,如下:

    r = requests.get('https://www.baidu.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})
    

    获取响应头,如下:

    r.headers
    # {Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Content-Encoding': 'gzip', ...}
    
    r.headers['Content-Type']
    # 'text/html; charset=utf-8'
    

    发起POST请求

    要发送POST请求,只需要把get()方法变成post(),然后传入data参数作为POST请求的数据,如下:

    r = requests.post('https://accounts.baidu.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})
    

    requests默认使用application/x-www-form-urlencoded对POST数据编码。如果要传递JSON数据,可以直接传入json参数,如下:

    params = {'key': 'value'}
    r = requests.post(url, json=params) #内部自动序列化为JSON
    

    上传文件

    上传文件需要更复杂的编码格式,但是requests把它简化成files参数,如下:

    upload_files = {'file': open('report.xls', 'rb')}
    r = requests.post(url, files=upload_files)
    

    在读取文件时,注意务必使用 'rb' 即二进制模式读取,这样获取的 bytes 长度才是文件的长度。

    post() 方法替换为 put()delete() 等,就可以以PUT或DELETE方式请求资源。

    添加Cookie

    在请求中传入Cookie,只需准备一个dict传入cookies参数,如下:

    cs = {'token': '12345', 'status': 'working'}
    r = requests.get(url, cookies=cs)
    

    requests对Cookie做了特殊处理,使得我们不必解析Cookie就可以轻松获取指定的Cookie,如下:

    r.cookies['token']
    # 12345
    

    指定超时

    要指定超时,传入以秒为单位的timeout参数。超时分为连接超时和读取超时,如下:

    try:
        # 3.1秒后连接超时,27秒后读取超时
        r = requests.get(url, timeout=(3.1, 27))
    except requests.exceptions.RequestException as e:
        print(e)
    

    超时重连

    def gethtml(url):
        i = 0
        while i < 3:
            try:
                html = requests.get(url, timeout=5).text
                return html
            except requests.exceptions.RequestException:
                i += 1
    

    添加代理

    同添加headers方法,代理参数也要是一个dict,如下:

    heads = {
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'
    }
    proxy = {
        'http': 'http://120.25.253.234:812',
        'https' 'https://163.125.222.244:8123'
    }
    r = requests.get('https://www.baidu.com/', headers=heads, proxies=proxy)
    

    更多编程教学请关注公众号:潘高陪你学编程

    image


    展开全文
  • 本文代码都由python编写,无需安装第三方拓展,代码更新:https://github.com/mengdj/python tcp/ip协议 4层架构   .pcap文件是一种简单网络包记录文件,较它的升级版.pcapng简单多了 pcap结构图 可以看到....

    本文代码都由python编写,无需安装第三方拓展库,代码更新:https://github.com/mengdj/python

    tcp/ip协议 4层架构

     

    .pcap文件是一种简单网络包记录文件,较它的升级版.pcapng简单多了

    pcap结构图

    可以看到.pcap文件,就由一个pcap文件头+无数个(pcap包头+包数据组成),我们只需要一个个解析即可,文件头用于描述.pcap文件本身(就一个文件头),包头则描述包的信息(抓取时间、长度等等),包的数据就是我们要的4层数据了(链路+网络+传输+应用),值得注意的是.pcap文件抓取的包是链路层抓取的,所以此时的包还没有经过重组,网络包重组(ip重组、tcp重组),本文暂不说明,后期可关注github,会用python实现的

    Pcap文件头24B各字段说明:
    Magic:        4B:0×1A 2B 3C 4D:用来识别文件自己和字节顺序。0xa1b2c3d4用来表示按照原来的顺序读取,0xd4c3b2a1表示下面的字节都要交换顺序读取。一般,我们使用0xa1b2c3d4
    Major:        2B,0×02 00:当前文件主要的版本号
    Minor:        2B,0×04 00当前文件次要的版本号
    ThisZone:    4B 时区。GMT和本地时间的相差,用秒来表示。如果本地的时区是GMT,那么这个值就设置为0.这个值一般也设置为0 SigFigs:4B时间戳的精度;全零
    SnapLen:    4B最大的存储长度(该值设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将该值设置为65535; 例如:想获取数据包的前64字节,可将该值设置为64)
    LinkType:    4B链路类型
    常用类型:
    0           BSD loopback devices, except for later OpenBSD
    1           Ethernet, and Linux loopback devices
    6           802.5 Token Ring
    7           ARCnet
    8           SLIP
    9           PPP
    10          FDDI
    100         LLC/SNAP-encapsulated ATM
    101         “raw IP”, with no link
    102         BSD/OS SLIP
    103         BSD/OS PPP
    104         Cisco HDLC
    105         802.11
    108         later OpenBSD loopback devices (with the AF_value in network byte order)
    113         special Linux “cooked” capture
    114         LocalTalk

     现在我们分别用python来解析(注意解析时,每一层代码都只拆分出上层数据,然后交给上层自己处理,)

    .pcap文件头处理 ==> .pcap包处理 ==> 链路层==> 网络层==> 传输层==> 应用层

    1.pcap.py 文件头处理

    解析文件头以及众多包,拿到包数据但不细节,解析包的工作我们放到包处理来做,同时考虑到文件通常很大,我们用生成器来处理遍历操作

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.packet import Packet
    from pcap.proc.util import BytesBuffer
    from pcap.proc.util import BytesOrder
    
    
    class PcapHead(object):
        """pcap文件头 24B"""
        _magic_number = None
        _version_major = None
        _version_minor = None
        _thiszone = None
        _sigfigs = None
        _snaplen = None
        _link_type = None
    
        def __init__(self, data):
            assert len(data) == 24
            self._magic_number = data[:4]
            if PcapHead.signature(self._magic_number) is False:
                raise Exception("不支持的文件格式")
            self._version_major = BytesOrder.bytes2int(data[4:6])
            self._version_minor = BytesOrder.bytes2int(data[6:8])
            self._thiszone = BytesOrder.bytes2int(data[8:12])
            self._sigfigs = BytesOrder.bytes2int(data[12:16])
            self._snaplen = BytesOrder.bytes2int(data[16:20])
            self._link_type = BytesOrder.bytes2int(data[20:24])
    
        def __str__(self):
            return "order:%s magor:%d minor:%d zone:%d sig:%d snap_len:%d type:%d" % (
                BytesOrder.order, self._version_major, self._version_minor, self._thiszone, self._sigfigs, self._snaplen,
                self._link_type)
    
        @staticmethod
        def signature(data):
            """验证签名同时确定排序,虽然还无法读取到大小端但不影响"""
            sig = BytesOrder.bytes2int(data)
            if sig == 0xa1b2c3d4:
                BytesOrder.order = "big"
                return True
            elif sig == 0xd4c3b2a1:
                BytesOrder.order = "little"
                return True
            return False
    
    
    class Pcap(object):
        """.pcap解析类"""
        __head = None
        __ret = 0
    
        def parse(self, file, buffSize=2048):
            """
            解析pcap文件,返回值为一个生成器 yield
            :param file:缓冲文件大小
            :param buffSize:
            :return:返回一个生成器(用于处理大包)
            """
            assert file != ""
            _buff = BytesBuffer()
            _packet = None
            ret = 0
            with open(file, "rb") as o:
                ctx = None
                while 1:
                    # 优先处理缓冲区数据(如果缓存数据超过了指定大小)
                    bsize = len(_buff)
                    if bsize > 0:
                        if bsize >= buffSize:
                            ctx = _buff.getvalue()
                        else:
                            _buff.write(o.read(buffSize))
                            ctx = _buff.getvalue()
                        _buff.clear()
                    else:
                        ctx = o.read(buffSize)
                    size = len(ctx)
                    if size > 0:
                        if self.__head is None:
                            # 文件头占24字节
                            if size >= 24:
                                self.__head = PcapHead(ctx[:24])
                                size -= 24
                                ctx = ctx[24:]
                            else:
                                _buff.write(ctx)
                        # 分析包头(包头占16字节)
                        if size > 16:
                            if _packet is None:
                                _packet = Packet()
                                ctx, size = _packet.parse(ctx)
                                if _packet.finish():
                                    yield _packet
                                    ret += 1
                                    _packet = None
                                if size > 0:
                                    _buff.write(ctx)
                            else:
                                ctx, size = _packet.parse(ctx)
                                if _packet.finish():
                                    yield _packet
                                    ret += 1
                                    _packet = None
                                if size > 0:
                                    _buff.write(ctx)
                        else:
                            _buff.write(ctx)
                    else:
                        break
                del ctx
            del _buff
            self.__ret = ret
    
        def __len__(self):
            return self.__ret
    
        @property
        def head(self):
            """获取包头,务必保证有调用parse后才能获得包头"""
            return self.__head
    

    2.packet.py 数据包处理

    处理详细包数据,并解析一层数据(交给链路层处理,获得链路层MAC实例)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.mac import MAC
    from pcap.proc.util import BytesBuffer, BytesOrder, ProcData
    
    
    class PacketHead(object):
        """包头 16B"""
        _ts_sec = 0
        _ts_usec = 0
        _incl_len = 0
        _orig_len = 0
    
        def __init__(self, data):
            self._ts_sec = BytesOrder.bytes2int(data[:4])
            self._ts_usec = BytesOrder.bytes2int(data[4:8])
            self._incl_len = BytesOrder.bytes2int(data[8:12])
            self._orig_len = BytesOrder.bytes2int(data[12:16])
    
        @property
        def sec(self):
            return self._ts_sec
    
        @property
        def usec(self):
            return self._ts_usec
    
        @property
        def incl(self):
            return self._incl_len
    
        @property
        def orig(self):
            return self._orig_len
    
        def __str__(self):
            return "PACKET sec:%d usec:%d incl len:%d orig len:%d" % (
                self._ts_sec, self._ts_usec, self._incl_len, self._incl_len)
    
    
    class Packet(ProcData):
        """数据包(未拆包)"""
        _head = None
        _buff = None
        name = "Packet"
    
        def __init__(self):
            super(ProcData, self).__init__()
            self._buff = BytesBuffer()
    
        def parse(self, data):
            """
            解析包数据
            :param data: 字节数据
            :return:    data,size
            """
            size = len(data)
            assert size > 0
            if self._head is None:
                self._head = PacketHead(data)
                size -= 16
                data = data[16:]
            if size > 0:
                _bs = len(self._buff)
                if _bs + size < self._head.incl:
                    self._buff.write(data)
                    size = 0
                    data = None
                else:
                    offset = self._head.incl - _bs
                    self._buff.write(data[:offset])
                    data = data[offset:]
                    size -= offset
                    assert len(data) == size
            return data, size
    
        def __del__(self):
            self._buff.close()
    
        @property
        def head(self):
            return self._head
    
        @property
        def data(self):
            return MAC(self._buff.getvalue(),None)
    
        def finish(self):
            return len(self._buff) == self._head.incl
    

    3.mac.py 链路层

    链路层其实很简单,链路层由 14字节(存储目标mac,来源mac,上层协议类型)包头+数据构成 其实我们可以发现底层协议都会有一个字段,然后后面直接上层协议数据

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.arp import ARP
    from pcap.proc.ip import IP
    from pcap.proc.ipv6 import IPV6
    from pcap.proc.util import ProcData
    
    
    class MAC(ProcData):
        """mac协议 14B+"""
        _dst = None
        _src = None
        _type = None
        _data = None
    
        def __init__(self, data, upper):
            super(MAC, self).__init__(upper)
            size = len(data)
            assert size > 18
            self._dst = data[:6]
            self._src = data[6:12]
            self._type = data[12:14]
            # fcs校验字段 self._fcs = data[size - 4:]
            self._data = data[14:]
    
        def __str__(self):
            return "MAC dst=>%s src=>%s type:%s" % (self.dst_desc, self.src_desc, self.type_desc)
    
        @property
        def dst_desc(self):
            return [hex(s).replace("0x", "").upper() for s in self._dst]
    
        @property
        def src_desc(self):
            return [hex(s).replace("0x", "").upper() for s in self._src]
    
        @property
        def type_desc(self):
            return [hex(i) for i in self._type]
    
        @property
        def dst(self):
            return self._dst
    
        @property
        def src(self):
            return self._src
    
        @property
        def type(self):
            return self._type
    
        @property
        def data(self):
            ret = None
            if self._type[0] == 0x08:
                if self._type[1] == 0x00:
                    # ipv4 0x0800
                    ret = IP(self._data, self)
                elif self._type[1] == 0x06:
                    # arp 0x0806
                    ret = ARP(self._data, self)
            elif self._type[0] == 0x86:
                if self._type[1] == 0xdd:
                    # ipv6 0x86dd
                    ret = IPV6(self._data, self)
            return ret
    

    4.ip.py 网络层(ip协议)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.tcp import TCP
    from pcap.proc.udp import UDP
    from pcap.proc.util import BytesOrder, ProcData
    
    
    class Services(object):
        """IP服务类型"""
        PRIORITY = 0
        DELAY = 0
        THROUGHPUT = 0
        RELIABILITY = 0
        COST = 0
        RESERVED = 0
    
        def __init__(self, ser):
            pass
    
    
    class Flag(object):
        """IP分片标志(python偏移真坑)"""
        DF = 0
        MF = 0
    
        def __init__(self, flag):
            """
                如果DF=0,那么标识不允许分段;DF=1则是表示这个数据包允许分段。MF=0表示分完段
                之后这个数据段是整个包的最后那段,MF=1则是不是最后段的标志
            """
            self.DF = ((~(~(1 << 6))) & flag) >> 6
            self.MF = ((~(~(1 << 5))) & flag) >> 5
    
        def __str__(self):
            return "(DF:%d MF:%d)" % (self.DF, self.MF)
    
    
    class IP(ProcData):
        """ip协议(ipv4) 20B"""
        _header_version_len = 0
        _service_set = 0
        # 标示IP头部有多少个4字节,IP头部最长是60字节
        _total_len = 0
        _id = 0
        _flag_offset = 0
        _time_to_live = 0
        _protocol = 0
        _check_sum = 0
        _src = 0
        _dst = 0
        _data = None
        _flag = None
    
        def __init__(self, data, upper):
            super(IP, self).__init__(upper)
            # 版本和长度各占4位,一共1个字节
            self._header_version_len = data[0]
            self._service_set = data[1]
            self._total_len = data[2:4]
            self._id = data[4:6]
            self._flag_offset = data[6:8]
            self._time_to_live = data[8]
            self._protocol = data[9]
            self._check_sum = data[10:12]
            self._src = data[12:16]
            self._dst = data[16:20]
            self._data = data[self.head_len_byte:]
    
        def __str__(self):
            return (
                    "IPv%d src:%s dst:%s len(header):%d service:%s len(total):%d id:%d flag:%s "
                    "time to live:%d protocol:%d check sum:%s payload:%d" %
                    (
                        self.version, self.src, self.dst, self.head_len_byte, bin(self._service_set), self.total_len,
                        self.id,
                        self.flag, self.time_to_live, self._protocol,
                        self._check_sum, len(self._data))
            )
    
        @property
        def version(self):
            return self._header_version_len >> 4
    
        @property
        def head_len(self):
            return (0xff >> 4) & self._header_version_len
    
        @property
        def flag(self):
            if self._flag is None:
                self._flag = Flag(self._flag_offset[0])
            return self._flag
    
        @property
        def total_len(self):
            return BytesOrder.bytes2int(self._total_len, "big")
    
        @property
        def time_to_live(self):
            return self._time_to_live
    
        @property
        def id(self):
            """IP序号"""
            return BytesOrder.bytes2int(self._id, "big")
    
        @property
        def src(self):
            return [i for i in self._src]
    
        @property
        def dst(self):
            return [i for i in self._dst]
    
        @property
        def head_len_byte(self):
            """头部字节数"""
            return self.head_len << 2
    
        @property
        def data(self):
            """获取传输层协议"""
            ret = None
            # 46~1500 检测是否有填充数据(既数据部分不满足46字节会填充,传递时候要过滤掉这部分数据)
            # tcp自身有分包机制,不用处理分包,其他协议需要处理分包
            data = self._data[:self.total_len - 20]
            if self._protocol == 0x06:
                ret = TCP(data, self)
            elif self._protocol == 0x11:
                ret = UDP(data, self)
            return ret
    

    5.1.tcp.py 传输层(tcp协议)

    tcp协议是一个很复杂的协议,如果你了解透了会对以后设计应用层协议大有帮助的,篇幅有限在这不废话,如稳定性的udp实现,其实就是tcp的另外一个实现

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.util import BytesOrder, ProcData
    
    
    class Flag(object):
        """
       CWR:拥塞窗口减少标志被发送主机设置,用来表明它接收到了设置ECE标志的TCP包。拥塞窗口是被TCP维护
             的一个内部变量,用来管理发送窗口大小。
        ECE:ECN响应标志被用来在TCP3次握手时表明一个TCP端是具备ECN功能的,并且表明接收到的TCP包的IP
             头部的ECN被设置为11。更多信息请参考RFC793。
        URG:紧急标志。紧急标志为"1"表明该位有效。
        ACK:确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的
             确认编号(w+1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。
        PSH:推标志。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理
             Telnet或rlogin等交互模式的连接时,该标志总是置位的。
        RST:复位标志。用于复位相应的TCP连接。
        SYN:同步标志。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端
             检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列
             编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经
             过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。
        FIN:结束标志。
        """
        CWR = 0
        ECE = 0
        URG = 0
        ACK = 0
        PSH = 0
        RST = 0
        SYN = 0
        FIN = 0
    
        def __init__(self, flag):
            # 取反补位(一次1字节的后6位)
            self.CWR = ((~(~(1 << 7))) & flag) >> 7
            self.ECE = ((~(~(1 << 6))) & flag) >> 6
            self.URG = ((~(~(1 << 5))) & flag) >> 5
            self.ACK = ((~(~(1 << 4))) & flag) >> 4
            self.PSH = ((~(~(1 << 3))) & flag) >> 3
            self.RST = ((~(~(1 << 2))) & flag) >> 2
            self.SYN = ((~(~(1 << 1))) & flag) >> 1
            self.FIN = ((~(~1)) & flag)
    
        def __str__(self):
            return "(CWR:%d ECE:%d URG:%d ACK:%d PSH:%d RST:%d SYN:%d FIN:%d)" % (
                self.CWR, self.ECE, self.URG, self.ACK, self.PSH, self.RST, self.SYN, self.FIN)
    
    
    class TCP(ProcData):
        """UDP协议 20B+,暂未处理分段数据 """
        _src = 0
        _dst = 0
        # 发送、确认编号
        _seq_no = 0
        _ack_no = 0
        _header_len_reserved = 0
        _reserved_flag = 0
        _wnd_size = 0
        _check_sum = 0
        # 紧急指针(偏移量)
        _urqt_p = 0
        _option = []
        _flag = None
        _data = []
    
        def __init__(self, data, upper):
            super(TCP, self).__init__(upper)
            self._src = data[:2]
            self._dst = data[2:4]
            self._seq_no = data[4:8]
            self._ack_no = data[8:12]
            # 4+4
            self._header_len_reserved = data[12]
            # 2+6
            self._reserved_flag = data[13]
            self._wnd_size = data[14:16]
            self._check_sum = data[16:18]
            self._urqt_p = data[18:20]
            # 其他可选字段
            if self.header_len > 20:
                self._option = data[20:self.header_len]
            self._data = data[self.header_len:]
    
        def __str__(self):
            return "TCP src(port):%d dst(port):%d seq:%d ack:%d len(header):%d " \
                   "flag:%s win:%d check_sum:%s urqt_p:%d option:%d payload:%d" % (
                       self.src, self.dst, self.seq, self.ack, self.header_len, self.flag, self.wnd_size,
                       self.check_sum, self.urqt_p,
                       len(self._option),
                       len(self._data))
    
        def __len__(self):
            return len(self._data)
    
        @property
        def src(self):
            return BytesOrder.bytes2int(self._src, "big")
    
        @property
        def option(self):
            """分析tcp的可选项字段(分析了常用字段)"""
            size = len(self._option)
            ret = []
            if size > 0:
                option = self._option
                while size > 0:
                    if option[0] == 0x00:
                        ret.append({"END": option[0]})
                        break
                    if option[0] == 0x01:
                        ret.append({"NOP": option[0]})
                        size -= 1
                        option = option[1:]
                    elif option[0] == 0x02:
                        # MSS
                        ret.append({"MSS": {"length": option[1], "value": BytesOrder.bytes2int(option[2:4], "big")}})
                        size -= 4
                        option = option[4:]
                    elif option[0] == 0x03:
                        # 窗口扩大因子
                        ret.append({"WSALE": {"length": option[1], "shift_count": option[2]}})
                        size -= 3
                        option = option[3:]
                    elif option[0] == 0x04:
                        # SACK
                        ret.append({"SACK": {"length": option[1]}})
                        size -= 2
                        option = option[2:]
                    elif option[0] == 0x08:
                        # 时间戳
                        ret.append({"TIMESTAMP": {"length": option[1], "value": BytesOrder.bytes2int(option[2:6], "big"),
                                                  "repl_value": BytesOrder.bytes2int(option[6:10], "big")}})
                        size -= 10
                        option = option[10:]
                    else:
                        break
            else:
                ret = None
            return ret
    
        @property
        def flag(self):
            """获取标志对象"""
            if self._flag is None:
                self._flag = Flag(self._reserved_flag)
            return self._flag
    
        @property
        def flag_desc(self):
            return bin(self._reserved_flag)
    
        @property
        def dst(self):
            return BytesOrder.bytes2int(self._dst, "big")
    
        @property
        def seq(self):
            """获取序列号"""
            return BytesOrder.bytes2int(self._seq_no, "big")
    
        @property
        def ack(self):
            """获取确认号"""
            return BytesOrder.bytes2int(self._ack_no, "big")
    
        @property
        def header_len(self):
            """获取头部长度"""
            return (self._header_len_reserved >> 4) << 2
    
        @property
        def wnd_size(self):
            """获取滑动窗口大小"""
            return BytesOrder.bytes2int(self._wnd_size, "big")
    
        @property
        def check_sum(self):
            """获取校验"""
            return self._check_sum
    
        @property
        def urqt_p(self):
            """获取紧急指针"""
            return BytesOrder.bytes2int(self._urqt_p, "big")
    
        @property
        def data(self):
            """获取原始包(可能包含分段数据,此数据未进行重组)"""
            return self._data
    

    5.1.udp.py 传输层(udp协议)

    udp协议头(首部)占用8字节,记录端口号,头长度以及校验和(非必须)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from pcap.proc.util import BytesOrder, ProcData
    
    
    class UDP(ProcData):
        """UDP 8B"""
        _src = 0
        _dst = 0
        # UDP头部和UDP数据的总长度字节
        _header_len = 0
        _check_sum = 0
        _data = None
    
        def __init__(self, data, upper):
            super(UDP, self).__init__(upper)
            self._src = data[:2]
            self._dst = data[2:4]
            self._header_len = data[4:6]
            self._check_sum = data[6:8]
            self._data = data[8:]
    
        def __str__(self):
            return "UDP src port:%d dst:%d header_len:%d check_sum:%s" % (
                self.src, self.dst, self.header_len, self.check_sum)
    
        @property
        def src(self):
            return BytesOrder.bytes2int(self._src, "big")
    
        @property
        def dst(self):
            return BytesOrder.bytes2int(self._dst, "big")
    
        @property
        def header_len(self):
            return BytesOrder.bytes2int(self._header_len, "big")
    
        @property
        def check_sum(self):
            return self._check_sum
    
        @property
        def data(self):
            return self._data
    

    6.基础类(封装了字节大小端转换、字节缓冲区操作)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    __author__ = "mengdj@outlook.com"
    from io import BytesIO
    
    
    class ProcData(object):
        __upper = 0
    
        def __init__(self, upper=None):
            self.__upper = upper
    
        @property
        def data(self):
            """返回上层数据,未处理分片"""
            pass
    
        @property
        def upper(self):
            return self.__upper
    
    
    class AppProcData(object):
        """此接口由应用层来实现"""
    
        def __init__(self):
            pass
    
        def find(self, data):
            """校验数据并完成初始化,成功返回self,链式调用"""
            pass
    
    
    class BytesOrder(object):
        """大小端排序工具类"""
        order = "big"
    
        @staticmethod
        def bytes2int(data, ord=""):
            if ord == "":
                ord = BytesOrder.order
            return int.from_bytes(data, ord)
    
    
    class BytesBuffer(BytesIO):
        """封装BytesIO,增加重置"""
        # 写入长度缓存
        __length = 0
        # 统计写入次数
        __count = 0
    
        def __len__(self):
            """获取长度,使用切片而不复制数据,同时增加计算缓存"""
            if self.__length == 0:
                self.__length = len(self.getbuffer())
            return self.__length
    
        def clear(self):
            """清理缓存区然后重置索引,seek必须调用"""
            self.truncate(0)
            self.seek(0)
            self.__length = 0
            self.__count = 0
    
        def write(self, *args, **kwargs):
            self.__length = 0
            self.__count += 1
            return super(BytesBuffer, self).write(*args, **kwargs)
    
        def writelines(self, *args, **kwargs):
            self.__length = 0
            self.__count += 1
            return super(BytesBuffer, self).writelines(*args, **kwargs)
    
        def count(self):
            return self.__count
    

    值得注意的是,由于抓取的链路层的数据,尚未进行重组MTU,MSS,因此抓到是可能是分段数据而不是完整的数据,分段操作,对于tcp(mss)由自己完成,其他则右IP协议完成,所以你发一个tcp包大小为1537字节,最终可能拆分成2个包,每个包都会带上tcp协议头,tcp的mss通常为1460字节;而ip分段则只会第一个包带上首部,分包重组需要详细了解协议知识,关于tcp和ip分包重组,请关注本博

    【阿里云】12.12来了!购买云产品即享低至2折,2018最后一波了 https://m.aliyun.com/act/team1212?params=N.4qR9SajEMx

     

     

    展开全文
  • 4.pycharm添加第三方库

    2021-05-04 10:43:06
    网络爬虫的第一步就是根据URL,获取网页的HTML信息。在Python3中,可以使用urllib.request和requests进行网页爬取。 (1)准备所需库 我们需要准备一款名为BeautifulSoup(网页...第三方库安装步骤如下: 选择File-&g

    网络爬虫的第一步就是根据URL,获取网页的HTML信息。在Python3中,可以使用urllib.request和requests进行网页爬取。
    (1)准备所需库

    我们需要准备一款名为BeautifulSoup(网页解析)的开源库,用于对下载的网页进行解析,我们是用的是PyCharm编译环境所以可以直接下载该开源库。

    • urllib库是python内置的,无需我们额外安装,只要安装了Python就可以使用这个库。
    • requests库是第三方库,需要我们自己安装。

    第三方库安装步骤如下:
    选择File->Settings

    在这里插入图片描述
    打开Project:PythonProject下的Project interpreter

    在这里插入图片描述
    点击加号添加新的库

    在这里插入图片描述

    输入bs4选择bs4点击Install Packge进行下载
    在这里插入图片描述

    小知识:requests库的github地址:https://github.com/requests/requests
    步骤如下:
    在cmd中,使用如下指令安装requests:
    pip install requests
    或者:
    easy_install requests


    requests常用方法

    在这里插入图片描述

    官方中文教程地址:
    http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

    展开全文
  • python3安装第三方库是十分方便的,在网络流畅的情况下,输入pip install [库名]。便可以顺利安装第三方库,这是最常用的一种。 方法二:手动下载第三方库,在使用pip安装,这种方式需要手动下载安装包(压缩文件...
  • python文件打包到无网linux环境中首先你需要有一个和要部署的环境相同的机器,但是可以上网,方便下载第三方库我想部署到不能联网centos上那我先...python项目的依赖4、使用pip下载依赖包5、在无网环境下安装第三方库...
  • Python3——网络小说爬虫

    千次阅读 2018-08-08 17:30:09
    爬虫步骤回顾: 根据前两篇文章,我们理解了爬虫的各个过程,简单回顾下: ... Python3中可以通过urllib.request或者requests进行网页爬取... requests库是第三方库,需要我们自己安装;(在上一节中我们是通过PyCh...
  • (1)指标模块可以自己写,也可以直接引用第三方库,例如talib 下载地址 https://pypi.python.org/pypi/TA-Lib (2)回测模块,不是本库的重点,符合就和目前的文华财经,TB等软件没区别了。但可以采用2种方式实现策略的...
  • python-爬虫

    2018-06-07 15:29:00
    简单实例 网络爬虫的第一步就是根据URL,获取网页的HTML信息。在Python3中,可以使用urllib....requests库是第三方库,需要我们自己安装。(requests库强大好用,所以本文使用requests库获取网页的HTML信息。req...
  • (1)指标模块可以自己写,也可以直接引用第三方库,例如talib 下载地址 https://pypi.python.org/pypi/TA-Lib (2)回测模块,不是本库的重点,符合就和目前的文华财经,TB等软件没区别了。但可以采用2种方式实现策略的...
  • python-magic:文件类型检测的第三方库 libmagic 的 Python 接口。 Unipath:用面向对象的方式操作文件和目录。 watchdog:管理文件系统事件的 API 和 shell 工具。 PyFilesystem2:Python 的文件系统抽象层。 ...
  • 从Lambda函数轻松生成自定义指标,而无需自定义批处理代码,阻止网络请求或依靠第三方软件。 通过安装可以支持其他计算环境(EC2,本地,ECS,EKS和其他容器环境)。 将指标链接到高基数上下文 使用嵌入式度量标准...
  • 第三方依赖库安装: pip3 install beautifulsoup4 使用方法: python biqukan.py baiduwenku.py: 百度文库word文章爬取 原理说明:http://blog.csdn.net/c406495762/article/details/72331737 代码不完善,没有...
  • 这时候就需要对功能添加重试代码,这里介绍一个python第三方库:tenacity。 安装方法: pip3 install tenacity 官方详细文档:https://pypi.org/project/retry/ 示例: 1. 最简单的重试(无限重试) from ...
  • scrapy 爬虫框架 scrapy是个能够帮助用户实现专业网络爬虫的爬虫框架,不同于小编之前介绍的...scrapy爬虫框架的安装方法与其它第三方库无区别 #在cmd或anaconda prompt上运行即可 pip install scrapy 命令执行...
  • 关于python爬虫的分析

    2020-12-10 22:08:59
     通过python第三方库(requests、urllib),下载源码,通过xpath、正则匹配数据 <p>3.动态网站  如果采用第2种方法,下载的源码只是简单的html,源码中没有任何数据ÿ...
  • 但是,如果您想尝试基于网络摄像头的实时面部检测,则可能需要安装Python2和OpenCV,但是核心API不需要任何第三方模块或外部依赖项。 主要特点 不需要安装OpenCV或任何第三方模块 处理速度快 无需图像预处理就...
  • 经典监督机器学习c++复现–kmeans聚类 对于机器学习,估计大家现在都耳熟能详了吧,近几...python自然而然也得到了广泛的应用,主要是python对于第三方库来说是太友好了,一个pip命令叫你安装安装,卸载就卸载,...
  • 简单实例

    2019-03-23 16:22:00
    网络爬虫的第一步就是根据URL,获取网页的HTML信息。在Python3中,可以使用urllib....requests库是第三方库,需要我们自己安装。requests库强大好用,所以本文使用requests库获取网页的HTML信息。requests库的gith...
  • 安装第三方依赖包 cd pytorch-book && pip install -r requirements.txt Visdom打不开及其解决方案 新版的visdom已经解决了这个问题,只需要升级即可 pip install --upgrade visdom 之前的解决方案 不再...
  • React学习笔记_状态组件(Stateless Component) 与高阶组件 React学习比较_初识React中的High Order Component es6 javascript对象的扩展运算符 React学习笔记_shoping_cart React学习笔记_tree React...
  • 3.6 第三方软件 73 3.6.1 Orasoft 73 3.6.2 Orac 75 3.6.3 Perl/DBI 76 3.7 小结 76 3.8 常见问答 76 第4章 在Linux上安装 Informix 78 4.1 引言 78 4.2 安装 81 4.2.1 第一部分:软件的获取 和软件的服务器放置 81...
  • 安装Seaborn步骤参考项目部署。 5.3.1 接口设计 绘制地区区域内疫情对比柱状图需要先得到地区(四川)的各地区疫情分类感染人数统计数据(表5-3-1)。 表 5-3-1 绘制地区区域内疫情对比柱状图接口定义 ...
  • 基于Lede OpenWrt,多款HomeLede原创软件及若干第三方软件包(Feed) 结合家庭x86软路由场景需要定制 按照家庭应用场景对固件及软件进行测试(x86),通过后发布 对家庭路由高频功能进行了测试(x86软路由),保证...

空空如也

空空如也

1 2 3
收藏数 42
精华内容 16
关键字:

python无网络安装第三方库

python 订阅