bs4 对象的种类

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment .

Tag 标签

Tag对象与XMLHTML原生文本中的tag相同:

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>

Tag有很多方法和属性,现在介绍一下tag中最重要的属性: name和attributes

Name 标签名

每个tag都有自己的名字,通过 .name 来获取:

tag.name
# u'b'

如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档:

tag.name = "blockquote"
tag
# <blockquote class="boldest">Extremely bold</blockquote>

也就是说name属性是可修改的。

Attributes 属性

一个tag可能有很多个属性. tag <b class="boldest"> 有一个 “class” 的属性,值为 “boldest” . tag的属性的操作方法与字典相同:

tag['class']
# u'boldest'

把Tag当作一个字典,我们可以通过键名获取属性值

也可以直接”点”取属性, 比如: .attrs :

tag.attrs
# {u'class': u'boldest'}

tag的属性可以被添加,删除或修改. 再说一次, tag的属性操作方法与字典一样

tag['class'] = 'verybold'
tag['id'] = 1
tag
# <blockquote class="verybold" id="1">Extremely bold</blockquote>

del tag['class']
del tag['id']
tag
# <blockquote>Extremely bold</blockquote>

tag['class']
# KeyError: 'class'
print(tag.get('class'))
# None

多值属性

HTML 4定义了一系列可以包含多个值的属性.在HTML5中移除了一些,却增加更多.最常见的多值的属性是 class (一个tag可以有多个CSS的class). 还有一些属性 rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中多值属性的返回类型是list:

css_soup = BeautifulSoup('<p class="body strikeout"></p>')
css_soup.p['class']
# ["body", "strikeout"]

css_soup = BeautifulSoup('<p class="body"></p>')
css_soup.p['class']
# ["body"]

如果某个属性看起来好像有多个值,但在任何版本的HTML定义中都没有被定义为多值属性,那么Beautiful Soup会将这个属性作为字符串返回

id_soup = BeautifulSoup('<p id="my id"></p>')
id_soup.p['id']
# 'my id'

将tag转换成字符串时,多值属性会合并为一个值

rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>')
rel_soup.a['rel']
# ['index']
rel_soup.a['rel'] = ['index', 'contents']
print(rel_soup.p)
# <p>Back to the <a rel="index contents">homepage</a></p>

如果转换的文档是XML格式,那么tag中不包含多值属性

xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
xml_soup.p['class']
# u'body strikeout'

NavigableString 可遍历的字符串

字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串:

tag.string
# u'Extremely bold'
type(tag.string)
# <class 'bs4.element.NavigableString'>

一个 NavigableString 字符串与Python中的Unicode字符串相同,并且还支持包含在 遍历文档树 和 搜索文档树 中的一些特性. 通过 unicode() 方法可以直接将 NavigableString 对象转换成Unicode字符串:

unicode_string = unicode(tag.string)
unicode_string
# u'Extremely bold'
type(unicode_string)
# <type 'unicode'>

tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法:

tag.string.replace_with("No longer bold")
tag
# <blockquote>No longer bold</blockquote>

BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象

因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name

soup.name
# u'[document]'

Comment 注释及特殊字符串

Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分:

markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)
# <class 'bs4.element.Comment'>

Comment 对象是一个特殊类型的 NavigableString 对象:

comment
# u'Hey, buddy. Want to buy a used parser'

但是当它出现在HTML文档中时, Comment 对象会使用特殊的格式输出:

print(soup.b.prettify())
# <b>
#  <!--Hey, buddy. Want to buy a used parser?-->
# </b>

Beautiful Soup中定义的其它类型都可能会出现在XML的文档中: CData , ProcessingInstruction , Declaration , Doctype .与 Comment 对象类似,这些类都是 NavigableString子类,只是添加了一些额外的方法的字符串独享.下面是用CDATA来替代注释的例子:

from bs4 import CData
cdata = CData("A CDATA block")
comment.replace_with(cdata)

print(soup.b.prettify())
# <b>
#  <![CDATA[A CDATA block]]>
# </b>

6-1:nmcli命令配置网络服务

使用nmcli命令配置网络

1.创建新连接配置

(1)创建新连接配置default,IP通过DHCP自动获取

file

(2)删除连接

file

(3)创建新的连接配置test2,指定静态IP,不自动连接

file

2.查看/etc/sysconfig/network-scripts/目录

file

3.启用test2连接配置

file

4.查看是否生效

file

5.修改连接设置

(1)修改test2为自动启动

file

(2)修改DNS为192.168.10.1

file

(3)添加DNS 114.114.114.114

file

(4)看下是否成功

file

(5)删除DNS

file

(6)修改IP地址和默认网关

file

(7)还可以添加多个IP

file

node 区分 ES6 和 commonjs

学习 JavaScript 语言,你会发现它有两种格式的模块。

一种是 ES6 模块,简称 ESM;另一种是 Node.js 专用的 CommonJS 模块,简称 CJS。这两种模块不兼容。

很多人使用 Node.js,只会用require()加载模块,遇到 ES6 模块就不知道该怎么办。本文就来谈谈,ES6 模块在 Node.js 里面怎么使用。

一、使用nodejs自带的功能支持es6语法

1、两种模块的差异

ES6 模块和 CommonJS 模块有很大的差异。

语法上面,CommonJS 模块使用require()加载和module.exports输出,ES6 模块使用import和export。

用法上面,require()同步加载,后面的代码必须等待这个命令执行完,才会执行。import命令则是异步加载,或者更准确地说,ES6 模块有一个独立的静态解析阶段,依赖关系的分析是在那个阶段完成的,最底层的模块第一个执行。

2、Node.js 的区分

Node.js 要求 ES6 模块采用.mjs后缀文件名。也就是说,只要脚本文件里面使用import或者export命令,那么就必须采用.mjs后缀名。Node.js 遇到.mjs文件,就认为它是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定"use strict"。

如果不希望将后缀名改成.mjs,可以在项目的package.json文件中,指定type字段为module

{
   "type": "module"
}

一旦设置了以后,该目录里面的 JS 脚本,就被解释用 ES6 模块。

# 解释成 ES6 模块
$ node my-app.js

如果这时还要使用 CommonJS 模块,那么需要将 CommonJS 脚本的后缀名都改成.cjs

总结为一句话:.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。

注意,ES6 模块与 CommonJS 模块尽量不要混用require命令不能加载.mjs文件,会报错,只有import命令才可以加载.mjs文件。反过来,.mjs文件里面也不能使用require命令,必须使用import

3、CommonJS 模块加载 ES6 模块

CommonJSrequire()命令不能加载 ES6 模块,会报错,只能使用import()这个方法加载。

(async () => {
  await import('./my-app.mjs');
})();

上面代码可以在 CommonJS 模块中运行。

require()不支持 ES6 模块的一个原因是,它是同步加载,而 ES6 模块内部可以使用顶层await命令,导致无法被同步加载。

4、ES6 模块加载 CommonJS 模块

ES6 模块的import命令可以加载 CommonJS 模块,但是只能整体加载,不能只加载单一的输出项。

// 正确
import packageMain from 'commonjs-package';
// 报错
import { method } from 'commonjs-package';

这是因为 ES6 模块需要支持静态代码分析,而 CommonJS 模块的输出接口是module.exports,是一个对象,无法被静态分析,所以只能整体加载。

加载单一的输出项,可以写成下面这样。

import packageMain from 'commonjs-package';
const { method } = packageMain;

5、同时支持两种格式的模块

一个模块同时要支持 CommonJS 和 ES6 两种格式,也很容易。

如果原始模块是 ES6 格式,那么需要给出一个整体输出接口,比如export default obj,使得 CommonJS 可以用import()进行加载。

如果原始模块是 CommonJS 格式,那么可以加一个包装层。

import cjsModule from '../index.js';
export const foo = cjsModule.foo; 

上面代码先整体输入 CommonJS 模块,然后再根据需要输出具名接口。

你可以把这个文件的后缀名改为.mjs,或者将它放在一个子目录,再在这个子目录里面放一个单独的package.json文件,指明{ type: "module" }

另一种做法是在package.json文件的exports字段,指明两种格式模块各自的加载入口。

"exports":{ 
    "require": "./index.js",
    "import": "./esm/wrapper.js" 
}

上面代码指定require()import,加载该模块会自动切换到不一样的入口文件

二、使用babel

1.首先, 安装依赖

npm install 
    @babel/core@7.1.6 
    babel-core@^6.26.3 
    babel-plugin-transform-es2015-modules-commonjs@6.26.2 
    babel-polyfill@6.26.0 
    babel-preset-env@1.7.0 
    babel-preset-latest-node@2.0.2 
    babel-register@6.26.0 -D

2.在项目的根目录中添加 .babelrc 在该文件中粘贴以下内容

{
    "presets": ["env"],
    "plugins": ["transform-es2015-modules-commonjs"]
}

3.创建入口文件 index.js 并粘贴以下内容

require('babel-register');
const babel = require('@babel/core');
const babelPresetLatestNode = require('babel-preset-latest-node');

babel.transform('code();', {
  presets: [[babelPresetLatestNode, {
    target: 'current',
  }]],
});

require('babel-polyfill');
require('./src');

4. 创建 src 目录, 并添加 index.js 文件,

​ 在index.js 文件中写ES6 或者nodejs 就可以了

配置xfs文件系统磁盘配额(quota)

(1)新建大小为100M、文件系统为xfs的主分区/dev/sdb3,并新建挂载点/disk3。

(2)编辑配置文件fstab,在/disk3目录项下加“uquota”参数。

(3)再重启系统后使用mount命令查看,即可发现/disk3目录已经支持quota磁盘配额技术了。

(4)接下来创建一个用于检查quota磁盘容量配额效果的用户user1,并针对/disk3目录增加其他人的写权限,保证用户能够正常写入数据。

(5)使用xfs_quota命令设置磁盘配额:

具体的限额控制包括:硬盘使用量的软限制和硬限制分别为3MB和6MB;创建文件数量的软限制和硬限制分别为3个和6个。

(6)测试磁盘配额设置是否成功:

尝试切换到这个普通用户,然后分别尝试创建一个大小为5MB和8MB的文件。可以发现,在创建8MB的文件时受到了系统限制;并生成磁盘配额报告。

(7)使用edquota命令修改磁盘配额,并再测试:

把用户user1的硬盘使用量的硬限额从6MB提升到10MB,创建文件数量的硬限制也从6个提升到8个。

第一题:
file

第二题:
file

第三题:
file

第四题:
file

第五题:
file

第六题:
file

file

第七题:
edquota -u user1
file

file

file

基本磁盘管理

1.创建/dev/sdb1和/dev/sdb5,/dev/sdb6

(一)磁盘分区

● 在虚拟机关机状态下,添加一块大小为8G的SCSI的新硬盘/dev/sdb。

● 使用fdisk命令创建大小为1000MB的/dev/sdb1主分区。

● 使用fdisk命令创建大小为3000MB的/dev/sdb2扩展分区。

● 使用fdisk命令创建创建大小为1000MB的/dev/sdb5逻辑分区。

● 使用fdisk命令创建创建大小为1000MB的/dev/sdb6逻辑分区。

● 输入w,把设置写入硬盘分区表,退出fdisk并重新启动系统。

reboot 重启

(二)磁盘格式化

● 用mkfs命令在上述刚刚创建的分区上创建ext4文件系统、xfs文件系统和vfat文件系统。

● 用fsck命令检查上面创建的文件系统。

挂载.挂载/dev/sdb1和/dev/sdb5、/dev/sdb6

● 利用mkdir命令,在/mnt目录下建立挂载点,mountpoint1和mountpoint2、mountpoint3。

● 把上述新创建的ext4分区挂载到/mnt/mountpoint1上。

● 把上述新创建的vfat分区挂载到/mnt/mountpoint2上。

● 把上述新创建的xfs分区挂载到/mnt/mountpoint3上。

● 利用df命令加某个选项(自己思考)列出挂载到系统上的分区,查看挂载是否成功。

思考:已经挂载好的硬盘还能不能继续创建新的分区呢?

● 利用umount命令卸载上面的分区。

mount /dev/sd 之后按下的是两次Tab而不是回车

复习

1. Linux最早是由计算机爱好者( B )开发的。

A Richard Petersen
B Linus Torvalds
C Rob Pick
D Linux Sarwar

2.Linux的根分区系统类型可以设置成( C )。

A FATl6
B FAT32
C ext4
D NTFS

3. Linux中有多个查看文件的命令,如果希望在查看文件内容过程中用光标可以上下移动来查看文件内容,则符合要求的那一个命令是( C )。

A cat
B more
C less
D head

4.查看系统当中所有进程的命令是( D )。

A ps all
B ps aix
C ps auf
D ps aux

5.如果忘记了ls命令的用法,可以采用( C )命令获得帮助。

A ?ls
B help ls
C man ls
D get ls

6.请选出创建用户ID是200,组ID是1000、用户主目录为/home/user01的正确命令。( C )

A useradd -u:200 -g:1000 -h:/home/user01 user01
B useradd -u=200 -g=1000 -h=/home/user01 user01
C useradd -u 200 -g 1000 -d /home/user01 user01
D useradd -u 200 -g 1000 -h /home/user01 user01

7.在使用了shadow口令的系统中,/etc/passwd和/etc/shadow两个文件的权限正确的是( C )

A -rw-r—–,-r——-
B -rw-r–r–,-r-r-r–r-
C -rw-r–r–,-r——-
D -rw-r–rw-,-r—–r-

8.如果umask设置为022,缺省的创建的文件的权限为( D )

A —-w–w-
B –rwxr-xr-x
C r-xr-x—
D rw-r—r–

二.多选题(共1题,5.8分)

1. 如何使用ls命令查看/dev目录的详细信息?(注意:只查看/dev目录,不是目录里面的内容)( CD )

A ls /dev
B ls /dev -l
C ls /dev -ld
D ll /dev -d

三.填空题(共4题,23.2分)

1.在Linux系统中命令区分大小写。在命令行中,可以使用Tab键来自动补齐命令。

2.Linux的所有设备均表示在/dev目录中的一个文件,并分别用hd 和sd打头表示这两种硬盘。

3.Linux默认的系统管理员账号是root

4.计算机现在主流的操作系统有UNIX 、WINDOWS 、MAC OS 和 LINUX(字母大写)。

四.简答题(共2题,11.6分)

1.思考题:如果文件file1在/etc目录下,file2在/dev目录下,现需要将这两个文件合并覆盖到/mnt目录下,并命名为file3,请问如何操作?(file1、file2已经创建好,只考虑合并操作即可)
file

2.usermod命令。

(1)利用usermod命令实现锁定用户admin。
(2)passwd -S 查看admin账户锁定情况。
(3)利用usermod命令实现解锁用户admin。
(4)passwd -S 查看admin账户锁定情况。
file

.其它(共2题,13.0分)

1、diff命令

(1)使用cd命令切换到root用户的家目录。
(2)使用pwd命令显示当前目录。
(3)使用cp命令复制文件anaconda-ks.cfg为文件a1。
(4)删除文件a1第一行。
(5)使用diff命令对比文件anaconda-ks.cfg和文a1 。

file
2、ln命令

(1)利用cp命令复制系统文件/etc/profile到当前目录下名为profile。
(2)给文件profile创建一个软链接lnsprofile和一个硬链接lnhprofile。
(3)长格式显示文件profile、lnsprofile和lnhprofile的详细信息。注意比较3个文件链接数的不同。
(4)删除文件profile,用长格式显示文件lnsprofile和lnhprofile的详细信息,比较文件lnhprofile的链接数的变化。
(5)用less命令查看文件lnsprofile的内容,看看有什么结果。
(6)用less命令查看文件lnhprofile的内容,看看有什么结果。
file

使用useradd、passwd、chage命令

使用useradd命令来新建用户账号:

(1)新建用户user1,UID为1010,GID为1010,用户的主目录为/home/user1,用户的shell为/bin/bash,用户的密码为123456。

(2)查看/etc/passwd文件的最后一行,了解用户账户各属性。

(3)查看/etc/shadow文件的最后一行,了解用户账户各属性。

(4)切换用户,使用新用户user1登录系统。

(5)切换回root用户使用passwd命令设置用户user1的密码。

(6)查看/etc/shadow文件的变化

useradd命令的其他选项2:

(1)新建用户user2,并不要创建用户主目录。

(2)passwd命令设置用户user2的密码。

(3)查看/etc/passwd文件的最后一行,了解用户账户各属性。

(4)切换用户登录系统。

passwd -d选项:

(1)使用useradd命令创建用户user3,并用passwd命令设置密码为空口令。

(2)使用tail命令查看/etc/shadow文件的最后一行,注意观察密码字段。

(3)切换用户user3登录。

利用chage命令设置密码过期、密码失效,并进行验证:

(1)创建用户user4,并利用passwd命令设置密码。

(2)利用chage -d 修改密码最后一次修改时间为2020-9-18。

(3)利用chage命令设置密码最短口令存活期3天、最长存活期30天;口令到期前3天提醒用户。

(4)利用chage -l查看密码时间策略。

(5)窗口模式切换用户(不要用su),验证密码过期但未失效会出现怎样情况?(本小题直接回答,不需要截图)

输入当前UNIX密码
为user4更改STRESS密码
输入user4的密码两次,修改密码之后就可以正常登录了

搭建个人网盘

下载 phpstudy

官网下载

file

一路 next 即可

创建网站

file

如果是在服务器上,勾选 生产环境
如果是在本地,勾选 同步hosts

下载 kod

官网下载

file

将下载的压缩包解压到kod.demo.com文件夹下

file

最终的复制结果
file

打开填写的域名

如果打不开,检查如下配置
file
在里面添加一行
file
最终效果图
file

按要求配置好数据库

file

python 列表

追加

list.append(obj)

在列表末尾添加新的对象

统计

list.count(obj)

统计某个元素在列表中出现的次数

合并

list.index(obj)

从列表中找出某个值第一个匹配项的索引位置

插入

list.insert(index, obj)

将对象插入列表

弹出

list.pop([index=-1])

移除列表中的一个元素(默认最后一个元素),并且返回该元素的值

移除

list.remove(obj)

移除列表中某个值的第一个匹配项

反转

list.reverse()

反向列表中元素

排序

list.sort(cmp=None, key=None, reverse=False)

对原列表进行排序