0%

Angular 9 is available, new release switches applications to the Ivy compiler and runtime by default (Feb, 2020)

模板编译

「模版编译」的工作一般是将使用「声明式语言」描述的「模版」转化为「命令式语言」定义的逻辑代码。鉴于这里的主体是 JavaScript,可以理解为「文本」->「函数」的转换。

Angular 模板编译演变

v2 版本中,Angular 采用了和 Svelte 几乎相同的「编译到指令操作」策略,主要区别是对「视图操作」使用的是基于 Renderer 的抽象指令。这种编译方式确实带来了卓越的性能,但由此带来的明显不便之一是生成代码的大小,在 Trotyl Yu:如何评价 angular 2 中的 AoT?中有给出「模版编译」产物的示例,由于太过占用屏幕空间,不在此处贴出。

v4 版本中,Angular 引入了 View Engine 的概念,建立了公共的运行时部分以减少「编译产物」的大小,而「视图定义」部分也不再使用「编译到指令函数」的策略,而是「编译到工厂函数,类似于(详细代码可以参见 【MMR-A】全新的 View Engine 模式):

1
2
3
4
5
6
7
8
9
10
11
function View_MyComponent() {
return viewDef([
elementDef(1, 'div', [['id', 'foo']]),
elementDef(1, 'p', []),
textDef(['Hello ']),
], (check, view) => {
var comp = view.component;
const currVal_0 = inlineInterpolate('Hello, ', comp.name);
check(view, currVal_0);
});
}

注册响应式表单模块

该模块定义了响应式表单涉及到的组件等类型或构造方法
类定义在@angular/forms包中,会在组件中引用,那么为什么要注册模块?

1
2
3
4
5
6
7
8
9
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }

FormControl

响应式控件类,每个实例对应页面表单中的一个控件,在template中使用formControl=”name”绑定,在FormGroup中使用formControlName=”name”绑定。
edit.component.ts:

1
name = new FormControl('QQstone')

edit.component.html
1
2
<input type="text" [formControl]="name">
<p>{{name.value}}</p>

FormGroup

用于管理一组响应式控件,一个表单可以标记为一个Group,也可以分为多个Group(QQs尚为实践过)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form #f="ngForm" *ngIf="assetForm" (ngSubmit)="save()" nz-form [formGroup]="assetForm">
<nz-form-label nzSpan="4" nzRequired>Asset Name</nz-form-label>
<nz-form-control nzSpan="8">
<input nz-input formControlName="asset_name" name="name" maxlength="30" placeholder="Name" required />
</nz-form-control>
<nz-form-label nzSpan="4" nzRequired>Status</nz-form-label>
<nz-form-control nzSpan="8">
<nz-select formControlName="status" name="status" nzPlaceHolder="Status"
nzAllowClear required>
<nz-option *ngFor="let item of enum.asset_status" [nzLabel]="item.text" [nzValue]="item.code">
</nz-option>
</nz-select>
</nz-form-control>

</form>

FormBuilder

使用FormBuilder构造FormGroup,每个组件对应一个Array,Array第一个属性是控件初始value,其后是校验器,若存在多个校验器,则该属性为Array
注入 private fb: FormBuilder

1
2
3
4
profileForm = this.fb.group({
name:['', Validators.required],
status:['30']
})

前提 服务号

注册服务号

  • 企业名称
  • 营业执照注册号
  • 验证方式

爬虫(Web Crawler)

郑重声明:本文仅限于编程学习,用于非法目的及造成侵权后果的行为,老子概不负责

http请求

私以为,爬虫程序就是以程序执行代替人工操作,在一定范围的网络资源中找自己要的东西。当人做这项枯燥的工作时,无非输入网址—打开网页—用肉眼识别—下载这样子,下面基本上就是用python模拟这个过程。

1
2
3
4
5
6
7
8
9
10
import requests
import re
response = requests.get('https://qqstone.github.io/qqsnote/2019/10/28/MySQL/')
print(response.text)
if response.text.find('主键'):
print('find it!')
keyUnicode = str('主键'.encode('unicode_escape')).replace('\\\\','\\')[2:14]
print('\S*'+keyUnicode+'\S*')
matchObj = re.findall('\S*'+keyUnicode+'\S*',response.text)
print(matchObj)

反“反爬设置”

有时请求一个网页时,发现无论通过Get或Post以及其他请求方式,都会出现403错误。这种现象多数是由于服务器拒绝了访问,因为这些网页为了防止恶意采集信息,所用的反爬虫设置。

此时可以通过模拟浏览器的header信息来进行访问。

1
2
3
4
5
6
import requests
import re
url='https://www.acfun.cn/a/ac12293064'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'}
response = requests.get(url,headers=headers)
print(response.text)

上述只是针对user agent检测的手段,通常网站管理员采取的反爬虫基本手段还有封锁IP,检测请求间隔,封锁cookie等,针对这些手段需要采取相应的措施如使用代理,使用sleep模拟点击控制间隔,禁用cookie等

超时处理

使用代理

解析html树

Scrapy框架

依赖:

1
2
3
4
5
pip install Twisted
# windows平台用下面这个
pip install Twisted[windows_platform]

pip install Scrapy

参考 Scrapy文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import scrapy
import re


class QuotesSpider1(scrapy.Spider):
name = "quotes1"
keyword = ""
pages = 75

def start_requests(self):
url = 'https://xxxxxxx.xxx.html'
yield scrapy.Request(url=url, callback=self.parse)
for i in range(2, self.pages):
surl = url.replace('.html', '-'+str(i)+'.html')
yield scrapy.Request(url=surl, callback=self.parse_key_word)

def parse(self, response):
regexp = r'\d{2}'
video_list_tags = response.css('h3::attr(title)')
for vt in video_list_tags:
#if vt.extract().find(self.keyword) >= 0:
match_array = re.findall(regexp, vt.extract())

if len(match_array):
self.log(vt.extract())
filename = 'output.log'
with open(filename, 'a', encoding='utf-8') as f:
f.write(vt.extract()+'-->'+response.url+"\n")

def parse_key_word(self, response):
video_list_tags = response.css('h3::attr(title)')
for vt in video_list_tags:
if vt.extract().find(self.keyword) >= 0:
self.log(vt.extract())
filename = 'output.log'
with open(filename, 'a', encoding='utf-8') as f:
f.write(vt.extract() + '-->' + response.url + "\n")


执行scrapy实例
1
scrapy crawl quotes1

概念

参考:Android 上网概述

使用3g/4g/5g网络的移动设备,通过ppp协议与蜂窝网络的基站建立通信

基带和蜂窝网络
ppp协议是链路层协议

协议结构
Linux对PPP数据链路的建立过程进行抽象,实现了pppd拨号应用程序,专门用于管理PPP数据链路的建立与关闭,见下图。

pppd是一个后台服务进程(daemon),实现了所有鉴权、压缩/解压和加密/解密等扩展功能的控制协议,负责把要发送的数据包传递给PPP协议处理模块,设置PPP协议的参数,用来建立/关闭连接。

Android设备网络访问架构

链路建立的大致过程:
链路建立

( Raspberry Pi Model B Plus Rev1.2 )

setup

官方指引:Setting up your Raspberry Pi

常见异常:HDMI无响应

修改/boot/config.txt

1
2
3
4
5
6
7
hdmi_force_hotplug=1
config_hdmi_boost=4
hdmi_group=2
hdmi_mode=9
hdmi_drive=2
hdmi_ignore_edid=0xa5000080
disable_overscan=1

设置默认命令行启动

1
sudo raspi-config

Boot Options -> Desktop / CLI -> Console
开启ssh server
ssh笔记

GPIO

USB摄像头

Using a standard USB webcam
实践发现,手上的UVC Camera一旦停止调用就会跳出(中断)

搭建直播流服务

4g上网

实践时 电脑USB接口向树莓派供电 插上网卡就电压不足(Under-voltage detected)

lsusb命令识别出” ID 05c6:6000 Qualcomm,Inc.Siemens SG75 “

安装ppp包

内网穿透

ipv6

关于使用ubuntu发行版和centos发行版的倾向(存目)

简单的ubuntu

镜像

实践日期:2019-12-29 ubuntu-18.04.3-live-server-amd64.iso

安装和分区(存目)

安装ssl

配置网卡

不知道怎么就安装了cloud image

参考Configure Ubuntu Server 18.04 to use a static IP address

在线安装Applications

配置apache

启用端口 /etc/apache2/ports.conf

配置/etc/sites-availiable/yoursite.conf
栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<VirtualHost *:90>
ServerName www.example.com

DirectoryIndex index.html
DocumentRoot /home/qqs/Workspace/csc_simulate/
<Directory /home/qqs/Workspace/csc_simulate>
Require all granted
</Directory>
Alias /viewer /home/qqs/Workspace/cs_meshviewer/build
<Directory /home/qqs/Workspace/cs_meshviewer/build>
Require all granted
</Directory>

<Location /viewer>
DirectoryIndex index.html
</Location>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

ProxyPreserveHost On
ProxyPass /download http://10.196.98.58:3000/download
ProxyPassReverse /download http://10.196.98.58:3000/download
</VirtualHost>

注意 并不是唯一的,应根据需要定义路径的访问控制,Difference between Directory and Location
启用和禁用site
1
2
a2ensite yoursite.conf
a2dissite yoursite.conf

启用和禁用模块

1
2
3
4
5
6
7
8
// 关于反向代理
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod lbmethod_byrequests
// 关于虚拟路径
a2enmod alias
// 禁用:a2dismod

启用、停用和重启服务
1
systemctl start|stop|reload apache2

Issue 403 You don’t have permission to access this resource.

令人发狂的CentOS(Selinux)

镜像

实践日期:2019-12-29 CentOS-8-x86_64-1905-dvd1.iso

网卡设置

1
2
3
4
5
6
ip add
nmcli device show
nmcli device status
nmcli connection down enp0s3
nmcli connection up enp0s3
nmcli c reload

静态IP

/etc/sysconfig/network-scripts/ifcfg-enp0s3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none # 默认是dhcp,根据dhcp分配 改为none或static
NAME=enp0s3
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=enp0s3
UUID=0b813e18-6008-485c-ba8c-d19e259a847a
DEVICE=enp0s3
ONBOOT=yes # 开机启用该配置
IPADDR=10.196.98.99
GATEWAY=10.196.98.1
NETMASK=255.255.254.0
DNS1=10.192.0.100
PREFIX=24

防火墙

1
2
3
4
5
systemctl stop firewalld.service #关闭
systemctl start firewalld.service #启动

firewall-cmd --zone=public --permanent --add-port 22/tcp #开启端口
systemctl restart firewalld.service #重启

关闭selinux

1
2
sestatus // 查看状态
setenforce 0 // 临时关闭

禁用selinux

编辑/etc/selinux/config, set SELINUX=disabled。