爬虫

爬取有道翻译(POST后下载)

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 取消SSL证书检测
import urllib.request
import urllib.parse
import json
import time
while True:
    url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
    data = {}
    data['i'] = input("请输入翻译内容:\n")
    data['doctype'] = 'json'
    data['keyfrom'] = 'fanyi.web'
    data = urllib.parse.urlencode(data).encode('utf-8')

    response = urllib.request.Request(url, data) #POST给网站要翻译的句子
    response.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36') # 伪装访问方式
    response = urllib.request.urlopen(response)
    html = response.read().decode('utf-8')
    target = json.loads(html)
    print(target['translateResult'][0][0]['tgt'])
    time.sleep(2)

BeautifulSoup爬HTML

查找

find_all(self, name=None, attrs={‘ ‘:’ ‘}, recursive=True, text=None, limit=None, **kwargs)

查找所有

self要查找的元素

name目标元素的名称

attrs元素的属性

recursive查找是否在节点子树下展开

支持自己定义函数查找

find(self, name=None, attrs={‘ ‘:’ ‘}, recursive=True, text=None, limit=None, **kwargs)

查找第一个

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import urllib.request
from bs4 import BeautifulSoup

try:
    url = 'https://liting1024.github.io/2020/02/20/Python/'
    response=urllib.request.urlopen(url)
    html=response.read().decode()
    soup=BeautifulSoup(html,'lxml')

    def endsWith(s,t):
        if len(s)>=len(t):
            return s[len(s)-len(t):]==t
        return False
    def myFilter(tag):
        return (tag.name=='a' and tag.has_attr('href') and tag['href']=='/category' and endsWith(tag.text,'ies'))
    # 元素类型为a,有超链接,且超链接为/category,内容以ies结尾

    tag1=soup.find('h1')
    tag2=soup.find_all('a',attrs={'class':'menu-item'})
    tag3=soup.find_all(myFilter)
    print(tag1,'\n',tag2,'\n',tag3)
    for tag in tag2:
        print(tag['href'])
    for tag in tag2:
        print(tag.text)
except Exception as err:
    print(err)

遍历

tag.parent 父类树节点

tag.children 子节点

tag.descendants 所有子孙节点

tag.next_sibling 最近的下一个兄弟节点

tag.previous_sibling 上一个兄弟节点

CSS语法查找

soup.select(tagName, attName=value)

attName 描述
attName^=value 以value开头匹配属性
attName$=value 以value结尾
attName*=value 包含指定值
soup.select("p a[rel='noopener']"))
# 查找p下的具有rel=‘noopenner’属性的a
soup.select("p > a")
# 查找p下的子节点a,不包含孙节点
soup.select("p ~ a")
# 查到p后面同级别的a

爬天气预报

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import urllib.request
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit

try:
    url = 'http://www.weather.com.cn/weather/101080101.shtml'
    headers={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"}
    req=urllib.request.Request(url,headers=headers)
    data=urllib.request.urlopen(req)
    data=data.read()
    dammit=UnicodeDammit(data,['utf-8','gdk'])
    html=dammit.unicode_markup
    # 自动选择解码
    soup=BeautifulSoup(html, 'lxml')
    lis=soup.select("ul[class='t clearfix'] li")
    for li in lis:
        date = li.select('h1')[0].text
        weather = li.select("p[class='wea']")[0].text
        temp1 = li.select("p[class='tem'] i")[0].text
        if li.select("p[class='tem'] span")==[]:
            temp=temp1
            # temp2和temp1相等是无法搜索到temp2
        else:
            temp2=li.select("p[class='tem'] span")[0].text
            temp=temp1+'/'+temp2
        print(date, weather, temp)
except Exception as err:
    print(err)

爬树

深度和广度类

class Stack: # 列表栈,深度
    def __init__(self):
        self.st=[]
    def pop(self):
        return self.st.pop()
    def push(self,obj):
        return self.st.append(obj)
    def isempty(self):
        return len(self.st)==0

class Queue: # 队列,广度
    def __init__(self):
        self.st=[]
    def fetch(self):
        return self.st.pop(0)
    def enter(self,obj):
        return self.st.append(obj)
    def isempty(self):
        return len(self.st)==0

多线程

t = Thread(target=,args=)

target:要执行的函数

args:一个元组或列表

from threading import Thread

t.setDaemon(False)
# 设定为后台线程
t.start()
# 启动线程
t.join()
# 阻塞当前线程,等t执行后继续执行
lock=threading._RLock()
# 设定一个锁
lock.acquire()
# lock获取线程锁,如果另一个线程调用了acquire而没有release则阻塞当前线程等待别的线程释放锁
lock.release()
# 释放锁

多线程爬天气网图片

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
from urllib import parse
import urllib.request
import threading

def imageSpider(start_url):
    global threads
    global count
    try:
        urls=[]
        req=urllib.request.Request(start_url,headers=headers)
        data=urllib.request.urlopen(req)
        data=data.read()
        dammit=UnicodeDammit(data, ["utf-8","gdk"])
        data=dammit.unicode_markup
        soup=BeautifulSoup(data,'lxml')
        images=soup.select('img')
        for image in images:
            src=image['src']
            url=parse.urljoin(start_url, src)
            if url not in urls:
                print(url)
                urls.append(url)
                count=count+1
                T=threading.Thread(target=download,args=(url,count))
                # 多线程运行download函数
                T.setDaemon(False)
                T.start()
                threads.append(T)
    except Exception as err:
        print(err)

def download(url,count):
    if url[len(url)-4]=='.':
        ext=url[len(url)-4:]
    else:
        ext=''
    req=urllib.request.Request(url, headers=headers)
    data=urllib.request.urlopen(req,timeout=100)
    data=data.read()
    fobj=open('image\\'+str(count)+ext,'wb')
    fobj.write(data)
    fobj.close()
    print('downloaded'+str(count)+ext)

start_url='http://www.weather.com.cn/weather1d/101080101.shtml'
headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'}
count=0
threads=[]
imageSpider(start_url)
for t in threads: #多线程等待后结束主程序
    t.join()
print('END')

Scrapy

创建简单爬虫

在虚拟python环境中pip install scrapy

scrapy startproject XXX

生成爬虫名字为itcast,地址为itcast.cn

scrapy genspider itcast itcast.cn

启动爬虫不打印日志

scrapy crawl 爬虫名字 –nolog

在spider文件夹中建立py文件

import scrapy

class MySpider(scrapy.Spider):
    name="mySpider"

    def start_requests(self):
    # 整个函数可以用start_urls = ['https://www.baidu.com']代替
        url='https://www.baidu.com'
        yield scrapy.Request(url=url, callback=self.parse)
        # 访问网页回调callback函数,yield返回数据但可以不结束函数
    def parse(self, response):
        print(response.url)
        data=response.body.decode()
        print(data)

在XXX文件中建立py文件

from scrapy import cmdline

cmdline.execute('scrapy crawl mySpider -s LOG_ENABLED=False'.split())

查找HTML元素

from scrapy.selector import Selector

selector=Selector(text=html)
s=selector.xpath('//title')
# //表示在任何位置,/表示下一级,'//body/book'搜索body下一级的book
# selector.xpath('//book').xpath('/title')
# .xpath('//book').xpath('//title') 对每个book查找title
print(s)

解析为列表

s=selector.xpath(‘//title’).extract()

得到title组成的list,.extract_first()得到第一个元素

获取属性、文本

s=selector.xpath(‘//title/@id’).extract()

获取属性值

s=selector.xpath(“”//title[@id=’chinese’]/text()”).extract()

限定id属性的值筛选

s=selector.xpath(‘//title/text()’).extract()

获取title的文本

用*代表任何

用*代替任何节点,不包括Text、Comment节点

s=selector.xpath(“”//title[@*]”)

任何属性

position下角标

从1开始编号

//body/title[position( )>2] [position( )<5]

取第三到六个title

兄弟节点父节点

s= selector.xpath( //title[ @lang = ‘chinese ]/parent::*”)

查找属性为lang= chinese’的title的父节点

s=sclector.xpathC(“//b[position()= 1]following-sibling::* [position()=1]”)
搜索第一个b节点后面的第一个兄弟节点

“element/ollowing-sibling::*”搜索element后面的同级的所有兄弟节点

“element/preceding-sibling::*“搜索element 前面的同级的所有兄弟节点
“element/preceding-sibling::*[position()=1]”搜索element 前面的同级的第一个兄弟节

其他py文件

items.py储存数据

items中建立用于储存数据的类

class YourprojectItem(scrapy.Item): # 继承scrapy.Item
    # define the fields for your item here like:
    # name = scrapy.Field()
    title=scrapy.Field()

在spiders中的爬虫中应用这个类

from yourProject.items import YourprojectItem

class MySpider(scrapy.Spider):
    name="mySpider"
    start_urls = ['https://www.baidu.com']

    def parse(self, response):
        data=response.body.decode()
        selector=scrapy.Selector(text=data)
        books=selector.xpath("//book")
        for book in books:
            item=YourprojectItem()
            item["title"]=book.xpath("./title/text()").extract_first()
            yield item

pipelines.py数据管道处理类

在settings.py中取消注释

ITEM_PIPELINES = {

​ ‘yourProject.pipelines.YourprojectPipeline’: 300,

}

爬取一次数据,调用一次process_item函数

from itemadapter import ItemAdapter

class YourprojectPipeline(object):
    count = 0
    def process_item(self, item, spider):
        YourprojectPipeline.count+=1
        if YourprojectPipeline.count==1:
            fobj=open("book.txt","wb")
        else:
            fobj=open("book.txt","at")
        print(item["title"])
        fobj.write(item['title'])
        fobj.close()
        return item

爬取当当网图书数据

C++常用函数

cstring类型

比较和计算

strcmp(a,b);

比较返回两个char数组的差异度(-2表示有一个char不同)

strlen(a);

计算string或char数组的长度

size();

lenth();

函数 功能 是为1 否为0
isalpha 判断是否为字母
islower/isupper 小/大写字母
isdigit 数字
isalnum 字母或数字
tolower/toupper 转换为小/大写字母

初始化

memset(s, c, n);

将以开辟内存s的前n个直接初始化为c

n可以用sizeof(s)

复制

memcpy(b, a, n);

以a开头,长度为n的内存,拷贝到b中

strncpy(b,a,n);

以a开头,长度为n的内存,拷贝到b中,并返回b

strcpy(b,a);

从a开始复制给b,遇到NULL ‘/0’结束

strcat(b,a);

把a连接到b后

输入

getline(cin,a,n);

将流中的字符存在a中,

遇到n结束,没有默认为‘/n’

cctype

tolower(); toupper();

改变字母大小写

isalpha(); isdigit(); isprint();

判断是否是字母,数字,可打印字符(非控制字符)

algorithm

min(); max()

返回两个元素中最小(最大)的一个

upper_bound(first, last, n);

查找区间中第一个大于n的位置,返回的是地址

lower_bound(first, last, n);

查找区间中第一个大于等于n的位置,返回的是地址

next_permutation(first, last); prev_permutation();

将数组中的元素全排列

需要将数组进行升序排列,否则只能找出该序列之后的全排列数。

char a[4]={'a','b','c','d'};
    do{
        for(int i=0;i<4;++i)
            cout<<a[i]<<" ";
        cout<<endl;
    }while(next_permutation(a,a+4));

sort(first, last, greater<>());

int a[5]={5,2,4,3,1},b[3]="cba";
sort(a,a+5);//正序排列
sort(a,a+5,greater<>());//逆序排列数字
sort(b,b+3,greater<char>());//逆序排列char

fill(first, last, a);

可将数组的值初始化成a

vector

一个动态申请空间的数组

定义 vector < typename > name;

typename可以是任何基本类型 结构体,STL容器vector,set,queue等。

vector<int> stu;
vector<double> stu;
vector<char> stu;
vector<node> stu;//node是结构体类型
vector<vector<int>> name;
vector<typename> a[arraySize];//申请一个二维数组

初始化

//初始化了10个默认值为0的元素
vector<int> abc(10);
//初始化了10个值为1的元素
vector<int> cde(10,1); 

int a[5] = {1,2,3,4,5};
//通过数组a的地址初始化,注意地址是从0到5(左闭右开区间)
vector<int> b(a, a+5);

vector<int> a(5,1);
//通过a初始化
vector<int> b(a);

//insert初始化方式将同类型的迭代器对应的始末区间(左闭右开区间)内的值插入到vector中
vector<int> a(6,6);
vecot<int> b;
//将a[0]~a[2]插入到b中,b.size()由0变为3
b.insert(b.begin(), a.begin(), a.begin() + 3);
//在b开始位置处插入6个6
b.insert(b.begin(), 6, 6);

vector<int> a(5,1);
int a1[5] = {2,2,2,2,2};
vector<int> b(10);

 /*将a中元素全部拷贝到b开始的位置中,注意拷贝的区间为a.begin() ~ a.end()的左闭右开的区间*/
copy(a.begin(), a.end(), b.begin());

//拷贝区间也可以是数组地址构成的区间
copy(a1, a1+5, b.begin() + 5);

访问

下标访问

从0开始

迭代器

vector::iterator it;//it是一个迭代器变量

常用函数

push_back(a)

在vector最后面添加一个元素a

pop_back(x)

删除vector的尾元素x

size()

clear()

清空vector所有的元素

insert();

insert(it,x);向vector的任意迭代器it初传入一个元素x

a.insert(a.begin()+1, 5);在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
a.insert(a.begin()+1, 3,5);在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
a.insert(a.begin()+1,b+3, b+6);b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8,插入元素后为1,4,5,9,2,3,4,5,9,8

erase()

erase(x); 删除单个元素

erase(a,b); 删除左闭右开区间内[a,b)的元素

copy(a.begin(),a.end(),b.begin()+1);

把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素

find(a.begin(),a.end(),10);

在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

set

一个内部自动升序而且不重复元素的容器

定义

操作 效果
set c 产生一个空的set/multiset,不含任何元素
set c(op) 以op为排序准则,产生一个空的set/multiset

访问

只能通过迭代器

set::iterator it;//typename对应定义set时的类型,auto自动推断定义类型

常用函数

insert(x)

将x插入set容器中,并且自动递增排序和去重

size()

clear()

end()

返回最后一个的迭代器

find(x)

查找值为x的元素,返回它的迭代器

erase()

erase(x); 删除单个元素

erase(a,b); 删除左闭右开区间内[a,b)的元素

multiset

有序可重复的容器

通过重载确定排序规则

struct rec{
    int x,y;
};
struct cmp{
    bool operator()(const rec&a,const rec&b){
        return a.x<b.x||a.x==b.x&&a.y<b.y;
    }
};
multiset<rec,cmp>h;

map

建立key(第一个值)和value(第二个值) 的对应,以key为标准有序

定义

map<int , int> maps;

访问

maps[key] = value; //给key赋值,key有对应的value就覆盖

It->first = 1;

常用函数

insert()

maps.insert(pair<type,type>(1,1)); //maps[1] = 1;

find()

map<type,type>::iterator it = maps.find(x); //auto代替map<type,type>::iterator 自动推断值的类型

长度

maps.empty(); //空返回1

maps.size();

maps.count(x); //返回指定元素出现的次数

逆向迭代器

maps.rbegin(); //返回指向maps尾部的逆向迭代器

maps.rend(); //返回指向maps头部的逆向迭代器

bound

maps.lower_bound(); //返回键值>=给定元素的第一个迭代器

maps.upper_bound(); //返回键值>给定元素的第一个迭代器

遍历

for(map<type,type>::iterator it = maps.begin(); it != maps.end(); it++)

erase()

maps.erase(iterator)

maps.erase(type)

哈希hashtable

unordered_set 不存储重复元素

unordered_map 实现key和value的映射

对比set和unordered_set

map和unordered_set也相同

对比 set unordered_set
有序 有序 无序
实现 BST或RBT Hash Table
插入、删除 log n 平均O(1),最坏O(n)

unordered_map的成员

成员方法 功能
begin() 返回指向容器中第一个键值对的正向迭代器。
end() 返回指向容器中最后一个键值对之后位置的正向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。
empty() 若容器为空,则返回 true;否则 false。
size() 返回当前容器中存有键值对的个数。
max_size() 返回容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[key] 该模板类中重载了 [] 运算符,其功能是可以向访问数组中元素那样,只要给定某个键值对的键 key,就可以获取该键对应的值。注意,如果当前容器中没有以 key 为键的键值对,则其会使用该键向当前容器中插入一个新键值对。
at(key) 返回容器中存储的键 key 对应的值,如果 key 不存在,则会抛出 out_of_range 异常。
find(key) 查找以 key 为键的键值对,如果找到,则返回一个指向该键值对的正向迭代器;反之,则返回一个指向容器中最后一个键值对之后位置的迭代器(如果 end() 方法返回的迭代器)。
count(key) 在容器中查找以 key 键的键值对的个数。
equal_range(key) 返回一个 pair 对象,其包含 2 个迭代器,用于表明当前容器中键为 key 的键值对所在的范围。
emplace() 向容器中添加新键值对,效率比 insert() 方法高。
emplace_hint() 向容器中添加新键值对,效率比 insert() 方法高。
insert() 向容器中添加新键值对。
erase() 删除指定键值对。
clear() 清空容器,即删除容器中存储的所有键值对。
swap() 交换 2 个 unordered_map 容器存储的键值对,前提是必须保证这 2 个容器的类型完全相等。
bucket_count() 返回当前容器底层存储键值对时,使用桶(一个线性链表代表一个桶)的数量。
max_bucket_count() 返回当前系统中,unordered_map 容器底层最多可以使用多少桶。
bucket_size(n) 返回第 n 个桶中存储键值对的数量。
bucket(key) 返回以 key 为键的键值对所在桶的编号。
load_factor() 返回 unordered_map 容器中当前的负载因子。负载因子,指的是的当前容器中存储键值对的数量(size())和使用桶数(bucket_count())的比值,即 load_factor() = size() / bucket_count()。
max_load_factor() 返回或者设置当前 unordered_map 容器的负载因子。
rehash(n) 将当前容器底层使用桶的数量设置为 n。
reserve() 将存储桶的数量(也就是 bucket_count() 方法的返回值)设置为至少容纳count个元(不超过最大负载因子)所需的数量,并重新整理容器。
hash_function() 返回当前容器使用的哈希函数对象。
求最大公约数的多种算法及比较

公约数的性质

gcd(-a,b)=gcd(a,b)
gcd(a,0)=|a|
gcd(a,1)=1
gcd(a,b)=gcd(b, a-b)
gcd(ma,mb)=m * gcd(a,b)

⚠️注:两数必须为正整数

辗转相除法(欧几里得)

时间效率: ⭐️
素数较大时运算耗时

#include <iostream>
using namespace std;
int main() {
    int a, b;
    cin >> a >> b;
    if (a < b) swap(a, b);//保证a大于b
    int t = a % b;
    while (t) {
        a = b;
        b = t;
        t = a % b;
    }
    cout << b;
}

穷举法

时间效率: ⭐️⭐️⭐️

#include <iostream>
using namespace std;
int main() {
    int a, b;
    cin >> a >> b;
    int t = a > b ? b : a;//t为min
    while (t) {
        if (a % t == 0 && b % t == 0)
            break;
        t--;
    }
    cout << t;
}

更相减损术

时间效率: ⭐️⭐️⭐️
两数相差大时运算次数多

#include <iostream>
#include <cmath>
using namespace std;
int main() {
    int a, b;
    cin >> a >> b;
    int l = 0;
    while (a % 2 == 0 && b % 2 == 0) {//都是偶数则除二
        a /= 2;
        b /= 2;
        l++;
    }
    if (a < b) swap(a, b);//保证a大于b
    int t = 1;
    while (t) {
        t = a - b;
        a = b > t ? b : t;//保证a大于b
        b = b > t ? t : b;
        if (a == b)//直到两数相等
            break;
    }
    cout << pow(2, l) * b;
}

Stein算法

时间效率: ⭐️⭐️
对于辗转相除法的改进

//递归
int Stein(int u, int v) {
    if (u == 0) {
        return v;
    }
    if (v == 0) {
        return u;
    }
    if (~u & 1) {
        if (v & 1) {
            return Stein(u >> 1, v);
        }
        else {
            return Stein(u >> 1, v >> 1) << 1;
        }
    }
    if (~v & 1) {
        return gcd2(u, v >> 1);
    }
    if (u > v) {
        return gcd2((u - v) >> 1, v);
    }
    return gcd2((v - u) >> 1, u);
}
//非递归
int Stein(unsigned int x, unsigned int y) {
    int factor = 0;   //计数器
    int temp;

    //大数赋给x,小数赋给y
    if (x < y) {
        temp = x;
        x = y;
        y = temp;
    }
    if (0 == y) {
        return 0;
    }
    while (x != y) {
        if (x & 0x1) {
            if (y & 0x1) {   //x,y都为奇数
                y = (x - y) >> 1;
                x -= y;
            }
            else {    // x为奇数,y为偶数
                y >>= 1;
            }
        }
        else {
            if (y & 0x1) {   // x为偶数,y为奇数
                x >>= 1;
                if (x < y) {
                    temp = x;
                    x = y;
                    y = temp;
                }
            }
            else {   //x,y均为偶数
                x >>= 1;
                y >>= 1;
                ++factor;
            }
        }
    }
    return (x << factor);
}
SwiftUI

ESE 提示可用的修饰

网站资源

点击这个 调色网站

点击这个 图像尺寸变更

点击这个 图标设计:(选择1024x1024像素)

点击这个阿里巴巴图标库

SwiftUI内置控件

布局

HStack(alignment: .leading对齐方式,spacing:10该stack中控件之间的距离) 水平摆放
VStack 竖直摆放
ZStack 叠加摆放
Group 多屏幕展示(多在预览时使用,支持frame)

列表

List(与ForEach用法相同,ForEach放在List里)

数组是继承Identifiable
List(0..<5可放置数组)){ i in
} 列表
如果没有继承Identifiable的话,需要手动写id
List(数组.identified(by:.id)) {}
简单数组就可以用自身作为id
List([1,2,3].identified(by:.self)){}

ScrollView 可滑动的列表,一般放在NavigitionView内

NavigationLink(destination:跳转后的页面){ } 点击可跳转,写在NavigitionView里

//Navigition头部分,修饰写在NavigitionView里面
.navigationBarTitle(Text(""),displayMode:.inline)字体的大小
.navigationBarItems(trailing: Image( ))//可以放另一视图

Form{
Section(header: 小节题目内容){
//小节内的内容
}
Section(header: 小节题目内容){
//小节内的内容
}
}

文字、图片

Text(“”)

TextField(“”, text: $name) //@State private var name = “”

修饰

.keyboardType() 弹出键盘类型
.numberPad和.decimalPad 两种键盘类型

SecureField

Image(system name: “ SF中的图标名称”)

修饰语句:

.font( ) 字体样式
.font(,system(size: )) 自定义字体大小
.frame(width: ,height: ) 尺寸
.foregroundColor(color: ) 颜色
.offset(x: ,y: ) 偏移量(UIScreen.main.bounds.height屏幕的高度)
.toggle( ) 在真假之间转换
.imageScale(.large) 调整图片大小
.aspectRatio(contentMode: .fit) 图片大小自适应屏幕,.fill是占满屏幕
.frame(minWidth: 0,maxWidth: .infinith) 图片最小宽度为0,最大为无穷
.cornerRadius( ) 圆角
.clipShape(Circle()形状) 裁剪
.overlay(Circle().stroke(Color.black, llineWidth: 5)描边的线) 覆盖的图案
.shadow(radius: ) 阴影
.tapAction{
点击后实现的代码,回调函数
} 轻触手势

动画类

单个的动画(俩种同时都有时,单个动画优先展示)

.transitiooon(.move(edge: .trailing)) 从边缘滑出
.rotationEffect 旋转
.rotation3DEffect(Angle(degrees: ), axis: (x: , y: , z: ))3D旋转
.animation(.spring()) 反弹动画
.animation(.basic(duration: 动画时间, curve: .easeInoOut)) 延迟动画

统一的动画

withAnimation(.basic基本动画(duration: 1动画时间)){
这里的值发生改变时,所有包含这个值的视图都加上了动画
}

按钮

Button(action: {
//点击后实现的代码
}) {
//按钮样式
}

EditButton() 启用或禁用列表中项目的编辑模式
Toggle(isOn: $布尔值) {
Text(“ “)
} 开关按钮

提示框

Alert

struct test: View {
    @State private var editing = false
    var body: some View {
        Button(action: {
            self.editing = true
        }){
            Text("show it")
        }
        .alert(isPresented: $editing){
        Alert(title: Text("alert"), message: Text("easy"),  primaryButton: .default(Text("yes") ,action: {
                print("点了yes欧")
                }),  secondaryButton: .destructive(Text("no")))
        }
    }
}

Modal
Popovers

struct test: View {
    @State private var editing = false
    var body: some View {
        Button("show it"){
            self.editing = true
        }.popover(isPresented: self.$editing, arrowEdge: .bottom) {
            Text("hello, this is a new world")
        }
    }
}

Sheet(和Popovers一模一样)

struct test: View {
    @State private var showingSheet = false
    var body: some View {
        Button("Show Sheet") {
            self.showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            Text("6")//也可以写成一个页面
        }
    }
}

ActionSheet

struct test: View {
    @State private var editing = false
    var body: some View {
        Button(action: {
            self.editing = true
        }){
            Text("show it")
        }
        .actionSheet(isPresented: $editing) {
            ActionSheet(title: Text("确定吗?"), message: Text("此操作会。。。"), buttons: [.destructive(Text("确定")), .cancel(Text("撤销"))])
        }
    }
}

选择器

DatePicker(“选择器的标题”,selection: 选择器的值, displayedComponents: ) 时间选择器

displayedComponents用来决定用户应该看到哪种选项:

默认为月-日-星期-小时-分钟
.date 显示年-月-日
.hourAndMinute 显示小时-分钟

Picker(“”,selection: ) 选择器

.pickerStyle(SegmentedPickerStyle( )) 另一种风格的选择器
单个选择滚轮

struct test: View {
    var choice = ["food","medicine","cosmetics"]
    @State private var index = 0
    var body: some View {
        Picker(selection: $index, label: Text("choose")) {
            ForEach (0..<choice.count) { i in
                Text(self.choice[i])
            }
        }
    }
}

多个选择滚轮

struct test: View {

    @State var data: [(String, [String])] = [
        ("One", Array(0...5).map { "\($0)" }),
        ("Two", Array(0...36).map { "\($0)" }),
        ("Three", Array(0...365).map { "\($0)" })
    ]
    @State var selection: [String] = [0, 0, 21].map { "\($0)" }

    var body: some View {
        VStack{
            Text(verbatim: "Selection: \(selection)")
            MultiPicker(data: data, selection: $selection)
            .frame(height: 300)
        }
    }

}
struct MultiPicker: View  {

    typealias Label = String
    typealias Entry = String

    let data: [ (Label, [Entry]) ]
    @Binding var selection: [Entry]

    var body: some View {
        GeometryReader { geometry in
            HStack {
                ForEach(0..<self.data.count) { column in
                    Picker(self.data[column].0, selection: self.$selection[column]) {
                        ForEach(0..<self.data[column].1.count) { row in
                            Text(verbatim: self.data[column].1[row])
                            .tag(self.data[column].1[row])
                        }
                    }
                    .pickerStyle(WheelPickerStyle())
                    .frame(width: geometry.size.width / CGFloat(self.data.count), height: geometry.size.height)
                    .clipped()
                }
            }
        }
    }
}

cornerRadius shadow foregroundColor background frame 都可以修饰选择器
.pickerStyle(SegmentedPickerStyle()) 可以把滚轮换成按钮
按钮也可以是图片

图案形状

Circle 圆形
Edge
Rectangle 好看的小方块
Path
RoundedRectangle

GeometryReader { geometry in
Text(“hello”)
.frame(width: geometry.size.width)
} 计算屏幕大小的容器

其他

属性包装器

未绑定属性就是公用状态
带上private表示只能在本结构体中使用,防止重名导致的崩溃
@State 值改变时,body内的内容重新刷新(双向绑定)
@Binding 将一个视图的属性链接到一些基础的模型数据
@ObservedObject 提取ObservableObject中储存的数据,所有页面共享数据
@Published 每当修改值时都会报告,willset{}可查看报告
@Environment(.Value) var Value 回到主页面
@EnvironmentObject 通过应用程序本身提供给视图,每个视图都可以读取的共享数据
.default 只实例化一次

协议

Identifiable 可以自动生成一个唯一标识符var id = UUID()

有用的View

地图View

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

    func makeUIView(context: Context) -> MKMapView{
        MKMapView()
    }

    func updateUIView(_ uiView: MKMapView,context: Context)   {
        uiView.setRegion(MKCoordinateRegion(
            center: CLLocationCoordinate2D( //经度纬度
                latitude: 39.9087243,
                longitude: 116.3952859
                ),
            span: MKCoordinateSpan(
                latitudeDelta: 0.02,
                longitudeDelta: 0.02)),//地图区域大小(比例尺大小)
        animated: true)
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}

使用第三方库

下载并安装Cocoapods的教程

在APP中打开Podfile文件

在end上一行,写pod ‘第三方库的名字’
点install
库安装慢的教程

可以在Xcode中直接使用了

报错

[!] CocoaPods could not find compatible versions for pod “URLImage”:

解决方法:把.xcworkspace和Podfile.lock文件删除,重新pod install一下

装库的速度慢

给终端挂上梯子,在ssr里找到HTTP代理设置
在终端任意文件夹中输入HTTP的监听地址和监听端口

export https_proxy=http://127.0.0.1:1087
export http_proxy=http://127.0.0.1:1087 
Mac搭建个人Blog

基础部分

hexo创建一个blog

终端的一些命令

注:终端中输入密码时不会显示
1

pwd
//查看此时所在位置
mkdir blog
//创建blog文件夹
cd ..
//返回上一层目录
cd blog
//进入blog文件夹

2

输入sudo hexo init 创建博客

3

如何使用hexo

创建新文章

hexo new post XXX

创建新目录

hexo new page tag

前往blog/source/tag文件夹中更改

---
title: XXX
lyout: tag
date: 2020-02-02 13:07:16
---

创建新标签

hexo new page category

同理把tag改为category即可

about页面

除了不支持Categories和Tags外和写文章的格式一样
一般不需要新建页面,只更改blog/source/about/index.md即可

hexo new page about

推送至github和coding.net

比较github(国外)和coding(腾讯)

github coding.net
域名 自定义 随机生成
加载速度 快一些
方便的clone方式 HTTPS SSH

如何使用hexo

创建新文章

hexo new post XXX

创建新目录

hexo new page tag

前往blog/source/tag文件夹中更改

---
title: XXX
lyout: tag
date: 2020-02-02 13:07:16
---

创建新标签

hexo new page category

同理把tag改为category即可

about页面

除了不支持Categories和Tags外和写文章的格式一样
一般不需要新建页面,只更改blog/source/about/index.md即可

hexo new page about

进阶部分

如何在百度中搜索到自己写的博客内容

必须在这里提交自己的博客链接才能在百度引擎中搜索到的

更换主题

Hexo 中下载主题

git clone https://github.com.....主题地址 themes/主题名字
//将主题下载到themes中

更改theme中的_config.yml

vim _config.yml 进入编辑模式(注意空格)
按 A 开始编辑
按 esc 退出编辑
输入 :wq 保存并退出

4

最后

hexo clean 清除缓存
hexo g 搭建   
hexo d 提交到github

bug

hexo g 失败

TypeError [ERR_INVALID_URL]: Invalid URL: http: //127.0.0.1:1085;export
at onParseError (internal/url.js:243:9)

原因

这个原因呢也很简单,就是hexo升级到4.2后,对于文章内的url自动变成html的A标签的解析引擎有点小bug,这是我在一个github的issue中看到的,issue链接我就不贴出来了,有兴趣的自行用英文关键字进行Google吧。

解决

  • 把http://这个协议头去掉,不过经过测试发现hexo自动生成的链接会有点其它的小bug,大家可以自行测试一下
  • 在http://的冒号后面加个空格
  • 把这个url用两个``给引起来,这种方法我感觉最好

本博客主题为Chic