#599 特殊号码

2021-07-28

*#06# 移动设备识别码

弹出一个框,title 是 “移动设备识别码”:

MEID :14 位数字
IMEI1: 15 位数字
IMEI2: 15 位数字
  • MEID, Mobile Equipment Identifier, 移动设备识别码

    移动设备识别码是一个全球唯一的识别 CDMA2000 移动台设备的号码。该号码的格式由 3GPP2 report S.R0048 定义,不过可以看作一个使用十六进制数字的IMEI。

  • IMEI, International Mobile Equipment Identity, 国际移动设备识别码

    通常所说的手机 “串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证。序列号共有15位数字,前6位(TAC)是型号核准号码,代表手机类型。接着2位(FAC)是最后装配号,代表产地。后6位(SNR)是串号,代表生产顺序号。最后1位(SP)一般为0,是检验码,备用。国际移动设备识别码一般贴于机身背面与外包装上,同时也存在于手机存储器中,通过输入 *#06# 即可查询。

*#*#4636#*#* 小米手机测试信息

三个子菜单:

  • 手机信息1
  • 手机信息2
  • WLAN infomation

#598 Python 源码学习 05: strbytes

2021-07-28

有了 int 的一点点经验,先找:

SETBUILTIN("bytearray",             &PyByteArray_Type);
SETBUILTIN("bytes",                 &PyBytes_Type);
SETBUILTIN("str",                   &PyUnicode_Type);

INIT_TYPE(&PyByteArray_Type, "bytearray");
INIT_TYPE(&PyBytes_Type, "str");
INIT_TYPE(&PyUnicode_Type, "str");

PS: 而且还可以通过 bytes 类型的 __doc__ 内容在 cpython 源码中搜索。
PS: 这里有一个奇怪的地方,就是 INIT_TYPE 的时候,把 PyBytes_Type 给了 str

PyBytes_Type

Objects/bytesobject.c

PyTypeObject PyBytes_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "bytes",
    PyBytesObject_SIZE,
    sizeof(char),
    0,                                          /* tp_dealloc */
    0,                                          /* tp_vectorcall_offset */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_as_async */
    (reprfunc)bytes_repr,                       /* tp_repr */
    &bytes_as_number,                           /* tp_as_number */
    &bytes_as_sequence,                         /* tp_as_sequence */
    &bytes_as_mapping,                          /* tp_as_mapping */
    (hashfunc)bytes_hash,                       /* tp_hash */
    0,                                          /* tp_call */
    bytes_str,                                  /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    &bytes_as_buffer,                           /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
        Py_TPFLAGS_BYTES_SUBCLASS,              /* tp_flags */
    bytes_doc,                                  /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    (richcmpfunc)bytes_richcompare,             /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    bytes_iter,                                 /* tp_iter */
    0,                                          /* tp_iternext */
    bytes_methods,                              /* tp_methods */
    0,                                          /* tp_members */
    0,                                          /* tp_getset */
    &PyBaseObject_Type,                         /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    bytes_new,                                  /* tp_new */
    PyObject_Del,                               /* tp_free */
};
typedef struct {
    PyObject_VAR_HEAD
    Py_hash_t ob_shash;
    char ob_sval[1];

    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     */
} PyBytesObject;

我不知道这个 PyBytesObject 是个啥。
回头找 int 相关信息,果然找到 typedef struct _longobject PyLongObject;
就在网上搜索,结果找到 python 官网(Bytes Objects)有相关信息:

PyBytesObject

This subtype of PyObject represents a Python bytes object.

PyTypeObject PyBytes_Type

This instance of PyTypeObject represents the Python bytes type; it is the same object as bytes in the Python layer.

PyUnicode_Type

Objects/unicodeobject.c

PyTypeObject PyUnicode_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "str",                        /* tp_name */
    sizeof(PyUnicodeObject),      /* tp_basicsize */
    0,                            /* tp_itemsize */
    /* Slots */
    (destructor)unicode_dealloc,  /* tp_dealloc */
    0,                            /* tp_vectorcall_offset */
    0,                            /* tp_getattr */
    0,                            /* tp_setattr */
    0,                            /* tp_as_async */
    unicode_repr,                 /* tp_repr */
    &unicode_as_number,           /* tp_as_number */
    &unicode_as_sequence,         /* tp_as_sequence */
    &unicode_as_mapping,          /* tp_as_mapping */
    (hashfunc) unicode_hash,      /* tp_hash*/
    0,                            /* tp_call*/
    (reprfunc) unicode_str,       /* tp_str */
    PyObject_GenericGetAttr,      /* tp_getattro */
    0,                            /* tp_setattro */
    0,                            /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
    Py_TPFLAGS_UNICODE_SUBCLASS,   /* tp_flags */
    unicode_doc,                  /* tp_doc */
    0,                            /* tp_traverse */
    0,                            /* tp_clear */
    PyUnicode_RichCompare,        /* tp_richcompare */
    0,                            /* tp_weaklistoffset */
    unicode_iter,                 /* tp_iter */
    0,                            /* tp_iternext */
    unicode_methods,              /* tp_methods */
    0,                            /* tp_members */
    0,                            /* tp_getset */
    &PyBaseObject_Type,           /* tp_base */
    0,                            /* tp_dict */
    0,                            /* tp_descr_get */
    0,                            /* tp_descr_set */
    0,                            /* tp_dictoffset */
    0,                            /* tp_init */
    0,                            /* tp_alloc */
    unicode_new,                  /* tp_new */
    PyObject_Del,                 /* tp_free */
};

字符串格式化

我想找 % 格式化,{} 格式化,以及最新的 fstring 的实现方式,但是代码的复杂性,让我在预计的时间之内无法完成,只好到此打住。

可能得从 parse.cast.c 语法树开始,再到 parse_string.c

// Objects/unicodeobject.c
// PyMethodDef unicode_methods 中的几行:
{"format", (PyCFunction)(void(*)(void)) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
{"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__},
UNICODE___FORMAT___METHODDEF

// Objects/clinic/unicodeobject.c.h
#define UNICODE___FORMAT___METHODDEF    \
    {"__format__", (PyCFunction)unicode___format__, METH_O, unicode___format____doc__},

static PyObject *
unicode___format__(PyObject *self, PyObject *arg)
{
    PyObject *return_value = NULL;
    PyObject *format_spec;

    if (!PyUnicode_Check(arg)) {
        _PyArg_BadArgument("__format__", "argument", "str", arg);
        goto exit;
    }
    if (PyUnicode_READY(arg) == -1) {
        goto exit;
    }
    format_spec = arg;
    return_value = unicode___format___impl(self, format_spec);

exit:
    return return_value;
}
static PyObject *
do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
{
    SubString input;

    /* PEP 3101 says only 2 levels, so that
       "{0:{1}}".format('abc', 's')            # works
       "{0:{1:{2}}}".format('abc', 's', '')    # fails
    */
    int recursion_depth = 2;

    AutoNumber auto_number;

    if (PyUnicode_READY(self) == -1)
        return NULL;

    AutoNumber_Init(&auto_number);
    SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
    return build_string(&input, args, kwargs, recursion_depth, &auto_number);
}

static PyObject *
do_string_format_map(PyObject *self, PyObject *obj)
{
    return do_string_format(self, NULL, obj);
}

没啥头绪,放弃。

#596 HTML5 Boilerplate

2021-07-26

可以保证跨浏览器兼容性的一套 HTML 模板,我决定将其应用在本站。

HTML5 Boilerplate is an HTML, CSS and JavaScript template (or boilerplate) for creating HTML5 websites with cross-browser compatibility.

#595 广告拦截器太过分了

2021-07-23

《科技爱好者周刊》第 167 期中,阮一峰十分愤慨的说广告拦截器太过分了。

因为他接到读者反馈,有篇文章中间的两段上下语义似乎不能接上,是否有写内容遗漏。然后检查之后发现是被广告拦截器拦截了。

阮一峰从使用非常广泛的规则集 EasyList (AdBlock 默认开启订阅,每 4 小时更新一次) 发现了很多针对他的规则,并从中摘抄了几句特别狠的:

! 拦截脚本 checker.js
ruanyifeng.com/blog/checker.js

! 隐藏指向 t.cn 的链接
ruanyifeng.com##a[href^="http://t.cn/"]

! 隐藏含有"培训"的段落
ruanyifeng.com##p:-abp-contains(培训)

# 曾经出现过,禁用所有 JS 代码:
ruanyifeng.com^$csp=script-src 'none'

我才知道,广告拦截可以做到这么精准的匹配,真心服!
阮一峰检测到用户开启广告拦截之后,就会不显示所有内容,取而代之的是这个提示:

您使用了广告拦截器,导致本站内容无法显示。
请将 www.ruanyifeng.com 加入白名单,解除广告屏蔽后,刷新页面。谢谢。

其他:

  1. 其实除了浏览器的广告拦截插件之外,HTTP 网关/代理、路由器也可以通过预设规则拦截广告。
  2. 我用过的广告拦截插件:AdBlock (getadblock.com),AdBlockPlus (adblockplus.org),uBlockOrigin (gorhill/uBlock)
  3. AdBlock (下载量 296278) 和 AdBlockPlus (下载量 174432) 的渊源:最早是有一个 Adblock 项目,由于 Adblock 停止更新,一位开发者启动了 AdblockPlus 项目,再后来又有公司基于 AdblockPlus 项目创建 AdBlock。

  4. uBlock (下载量 1658) 和 uBlock Origin (下载量 24666) 的渊源:uBlock 的创始人将项目转移给别人维护之后,好像对后来接收捐款的分配不满,自己又开了一个分支 uBlock Origin。

#594 BIMI

2021-07-22

看到新闻,谷歌正式开始在 Gmail 中启用 BIMI,显示经过验证的图标。
BIMI 全名 Brand Indicators for Message Identification,可能是邮件品牌标识的意思,作用就是在邮件中显示一个图标,用来标识邮件是否是品牌邮件。
当然这个 BIMI 就需要邮件能够通过一些手段的检测,比如 SPF, DKIM, DMARC,来保证其可靠性。

#593 使用 utterances 开源评论框

2021-07-22

本站的评论框(Disqus)不知道为啥死活打不开(net::ERR_SSL_PROTOCOL_ERROR),不知道是被某种特殊力量给控制住了,还是别的什么原因。
不想折腾它了,直接切到 utterances 算了。
我本来想,反正也没有人评论,无所谓啦。但时间一长,总在心里挂念这件事,万一有个热心读者想要评论呢!

utterances 是一款依托 GitHub Issue 的开源评论框,所有评论数据都在 GitHub 上。
然后这个仓库是我的,数据当然完全掌握在自己手上,用的放心。

我写博客好些年了,评论框换过好多次,总是垮,最后换 Disque 就是图稳定,但还是不让人省心,这回换到 GitHub 上来了,应该绝对不会有问题了吧!

第一步:安装

utterances app,应该是允许它访问我的某个仓库,读写 Issue。

第二步:<script> 标签

从官网点几个选择框,然后就可以复制出来,粘贴到需要显示评论框的地方(会在那个后面插入一个 iframe)。

<script
  src="https://utteranc.es/client.js"
  repo="markjour/markjour.com"
  issue-term="pathname"
  theme="github-light"
  crossorigin="anonymous"
  async
></script>

不完美的地方:框子太窄

好在是根据最外围的 div 控制的,直接加一行:

div.utterances {
  max-width: none !important;
}

补充

wget https://utteranc.es/client.js -O static/utteranc/client.js
wget https://utteranc.es/client.js.map -O static/utteranc/client.js.map

#592 排列与组合

2021-07-22

吐槽:现在网上各种讲解,不要太贴心。
要是我读书那会儿有这么多资源,我能上清华(手动狗头)。

#591 使用 nohup 的一个小问题

2021-07-22
function fq () {
    # ...
    nohup qv2ray &>> /tmp/qv2ray.log &
    # ...
}

每次关闭终端,qv2 就一起崩溃了。

然后我改成:

nohup sh -c "qv2ray &>> /tmp/qv2ray.log &"

就好了。

分析:可能是后面日志和改后台运行的部分被 nohup 拿走的缘故吧。

#590 转载:如何将 Numpy 加速 700 倍?用 CuPy 呀

2021-07-21

作为 Python 语言的一个扩展程序库,Numpy 支持大量的维度数组与矩阵运算,为 Python 社区带来了很多帮助。借助于 Numpy,数据科学家、机器学习实践者和统计学家能够以一种简单高效的方式处理大量的矩阵数据。那么 Numpy 速度还能提升吗?本文介绍了如何利用 CuPy 库来加速 Numpy 运算速度。
就其自身来说,Numpy 的速度已经较 Python 有了很大的提升。当你发现 Python 代码运行较慢,尤其出现大量的 for-loops 循环时,通常可以将数据处理移入 Numpy 并实现其向量化最高速度处理。
但有一点,上述 Numpy 加速只是在 CPU 上实现的。由于消费级 CPU 通常只有 8 个核心或更少,所以并行处理数量以及可以实现的加速是有限的。
这就催生了新的加速工具——CuPy 库。