分类 技术 下的文章

下面是我如何配置 VirtualBox 虚拟机以在我的 Linux 工作站上使用物理的 Windows 操作系统。

 title=

我经常使用 VirtualBox 来创建虚拟机来测试新版本的 Fedora、新的应用程序和很多管理工具,比如 Ansible。我甚至使用 VirtualBox 来测试创建一个 Windows 访客主机。

我从来没有在我的任何一台个人电脑上使用 Windows 作为我的主要操作系统,甚至也没在虚拟机中执行过一些用 Linux 无法完成的冷门任务。不过,我确实为一个需要使用 Windows 下的财务程序的组织做志愿者。这个程序运行在办公室经理的电脑上,使用的是预装的 Windows 10 Pro。

这个财务应用程序并不特别,一个更好的 Linux 程序 可以很容易地取代它,但我发现许多会计和财务主管极不愿意做出改变,所以我还没能说服我们组织中的人迁移。

这一系列的情况,加上最近的安全恐慌,使得我非常希望将运行 Windows 的主机转换为 Fedora,并在该主机上的虚拟机中运行 Windows 和会计程序。

重要的是要明白,我出于多种原因极度不喜欢 Windows。主要原因是,我不愿意为了在新的虚拟机上安装它而再花钱购买一个 Windows 许可证(Windows 10 Pro 大约需要 200 美元)。此外,Windows 10 在新系统上设置时或安装后需要足够的信息,如果微软的数据库被攻破,破解者就可以窃取一个人的身份。任何人都不应该为了注册软件而需要提供自己的姓名、电话号码和出生日期。

开始

这台实体电脑已经在主板上唯一可用的 m.2 插槽中安装了一个 240GB 的 NVMe m.2 的 SSD 存储设备。我决定在主机上安装一个新的 SATA SSD,并将现有的带有 Windows 的 SSD 作为 Windows 虚拟机的存储设备。金士顿在其网站上对各种 SSD 设备、外形尺寸和接口做了很好的概述。

这种方法意味着我不需要重新安装 Windows 或任何现有的应用软件。这也意味着,在这台电脑上工作的办公室经理将使用 Linux 进行所有正常的活动,如电子邮件、访问 Web、使用 LibreOffice 创建文档和电子表格。这种方法增加了主机的安全性。唯一会使用 Windows 虚拟机的时间是运行会计程序。

先备份

在做其他事情之前,我创建了整个 NVMe 存储设备的备份 ISO 镜像。我在 500GB 外置 USB 存储盘上创建了一个分区,在其上创建了一个 ext4 文件系统,然后将该分区挂载到 /mnt。我使用 dd 命令来创建镜像。

我在主机中安装了新的 500GB SATA SSD,并从 临场 live USB 上安装了 Fedora 32 Xfce 偏好版 spin 。在安装后的初次重启时,在 GRUB2 引导菜单上,Linux 和 Windows 操作系统都是可用的。此时,主机可以在 Linux 和 Windows 之间进行双启动。

在网上寻找帮助

现在我需要一些关于创建一个使用物理硬盘或 SSD 作为其存储设备的虚拟机的信息。我很快就在 VirtualBox 文档和互联网上发现了很多关于如何做到这一点的信息。虽然 VirtualBox 文档初步帮助了我,但它并不完整,遗漏了一些关键信息。我在互联网上找到的大多数其他信息也很不完整。

在我们的记者 Joshua Holm 的帮助下,我得以突破这些残缺的信息,并以一个可重复的流程来完成这项工作。

让它发挥作用

这个过程其实相当简单,虽然需要一个玄妙的技巧才能实现。当我准备好这一步的时候,Windows 和 Linux 操作系统已经到位了。

首先,我在 Linux 主机上安装了最新版本的 VirtualBox。VirtualBox 可以从许多发行版的软件仓库中安装,也可以直接从 Oracle VirtualBox 仓库中安装,或者从 VirtualBox 网站上下载所需的包文件并在本地安装。我选择下载 AMD64 版本,它实际上是一个安装程序而不是一个软件包。我使用这个版本来规避一个与这个特定项目无关的问题。

安装过程总是在 /etc/group 中创建一个 vboxusers 组。我把打算运行这个虚拟机的用户添加到 /etc/group 中的 vboxusersdisk 组。将相同的用户添加到 disk 组是很重要的,因为 VirtualBox 是以启动它的用户身份运行的,而且还需要直接访问 /dev/sdx 特殊设备文件才能在这种情况下工作。将用户添加到 disk 组可以提供这种级别的访问权限,否则他们就不会有这种权限。

然后,我创建了一个目录来存储虚拟机,并赋予它 root.vboxusers 的所有权和 775 的权限。我使用 /vms 用作该目录,但可以是任何你想要的目录。默认情况下,VirtualBox 会在创建虚拟机的用户的子目录中创建新的虚拟机。这将使多个用户之间无法共享对虚拟机的访问,从而不会产生巨大的安全漏洞。将虚拟机目录放置在一个可访问的位置,可以共享虚拟机。

我以非 root 用户的身份启动 VirtualBox 管理器。然后,我使用 VirtualBox 的“ 偏好 Preferences => 一般 General ”菜单将“ 默认机器文件夹 Default Machine Folder ”设置为 /vms 目录。

我创建的虚拟机没有虚拟磁盘。“ 类型 Type ” 应该是 Windows,“ 版本 Version ”应该设置为 Windows 10 64-bit。为虚拟机设置一个合理的内存量,但只要虚拟机处于关闭状态,以后可以更改。在安装的“ 硬盘 Hard disk ”页面,我选择了 “ 不要添加虚拟硬盘 Do not add a virtual hard disk ”,点击“ 创建 Create ”。新的虚拟机出现在VirtualBox 管理器窗口中。这个过程也创建了 /vms/Test1 目录。

我使用“ 高级 Advanced ”菜单在一个页面上设置了所有的配置,如图 1 所示。“ 向导模式 Guided Mode ”可以获得相同的信息,但需要更多的点击,以通过一个窗口来进行每个配置项目。它确实提供了更多的帮助内容,但我并不需要。

VirtualBox 对话框:创建新的虚拟机,但不添加硬盘

图 1:创建一个新的虚拟机,但不要添加硬盘。

然后,我需要知道 Linux 给原始 Windows 硬盘分配了哪个设备。在终端会话中以 root 身份使用 lshw 命令来发现 Windows 磁盘的设备分配情况。在本例中,代表整个存储设备的设备是 /dev/sdb

# lshw -short -class disk,volume
H/W path           Device      Class          Description
=========================================================
/0/100/17/0        /dev/sda    disk           500GB CT500MX500SSD1
/0/100/17/0/1                  volume         2047MiB Windows FAT volume
/0/100/17/0/2      /dev/sda2   volume         4GiB EXT4 volume
/0/100/17/0/3      /dev/sda3   volume         459GiB LVM Physical Volume
/0/100/17/1        /dev/cdrom  disk           DVD+-RW DU-8A5LH
/0/100/17/0.0.0    /dev/sdb    disk           256GB TOSHIBA KSG60ZMV
/0/100/17/0.0.0/1  /dev/sdb1   volume         649MiB Windows FAT volume
/0/100/17/0.0.0/2  /dev/sdb2   volume         127MiB reserved partition
/0/100/17/0.0.0/3  /dev/sdb3   volume         236GiB Windows NTFS volume
/0/100/17/0.0.0/4  /dev/sdb4   volume         989MiB Windows NTFS volume
[root@office1 etc]#

VirtualBox 不需要把虚拟存储设备放在 /vms/Test1 目录中,而是需要有一种方法来识别要从其启动的物理硬盘。这种识别是通过创建一个 *.vmdk 文件来实现的,该文件指向将作为虚拟机存储设备的原始物理磁盘。作为非 root 用户,我创建了一个 vmdk 文件,指向整个 Windows 设备 /dev/sdb

$ VBoxManage internalcommands createrawvmdk -filename /vms/Test1/Test1.vmdk -rawdisk /dev/sdb
RAW host disk access VMDK file /vms/Test1/Test1.vmdk created successfully.

然后,我使用 VirtualBox 管理器 “ 文件 File => 虚拟介质管理器 Virtual Media Manager ” 对话框将 vmdk 磁盘添加到可用硬盘中。我点击了“ 添加 Add ”,文件管理对话框中显示了默认的 /vms 位置。我选择了 Test1 目录,然后选择了 Test1.vmdk 文件。然后我点击“ 打开 Open ”,Test1.vmdk 文件就显示在可用硬盘列表中。我选择了它,然后点击“ 关闭 Close ”。

下一步就是将这个 vmdk 磁盘添加到我们的虚拟机的存储设备中。在 “Test1 VM” 的设置菜单中,我选择了 “ 存储 Storage ”,并点击了添加硬盘的图标。这时打开了一个对话框,在一个名为“ 未连接 Not attached ”的列表中显示了 Test1vmdk 虚拟磁盘文件。我选择了这个文件,并点击了“ 选择 Choose ”按钮。这个设备现在显示在连接到 “Test1 VM” 的存储设备列表中。这个虚拟机上唯一的其他存储设备是一个空的 CD/DVD-ROM 驱动器。

我点击了“ 确定 OK ”,完成了将此设备添加到虚拟机中。

在新的虚拟机工作之前,还有一个项目需要配置。使用 VirtualBox 管理器设置对话框中的 “Test1 VM”,我导航到 “ 系统 System => 主板 Motherboard ”页面,并在 “ 启用 EFI Enable EFI ”的方框中打上勾。如果你不这样做,当你试图启动这个虚拟机时,VirtualBox 会产生一个错误,说明它无法找到一个可启动的介质。

现在,虚拟机从原始的 Windows 10 硬盘驱动器启动。然而,我无法登录,因为我在这个系统上没有一个常规账户,而且我也无法获得 Windows 管理员账户的密码。

解锁驱动器

不,本节并不是要破解硬盘的加密,而是要绕过众多 Windows 管理员账户之一的密码,而这些账户是不属于组织中某个人的。

尽管我可以启动 Windows 虚拟机,但我无法登录,因为我在该主机上没有账户,而向人们索要密码是一种可怕的安全漏洞。尽管如此,我还是需要登录这个虚拟机来安装 “VirtualBox Guest Additions”,它可以提供鼠标指针的无缝捕捉和释放,允许我将虚拟机调整到大于 1024x768 的大小,并在未来进行正常的维护。

这是一个完美的用例,Linux 的功能就是更改用户密码。尽管我是访问之前的管理员的账户来启动,但在这种情况下,他不再支持这个系统,我也无法辨别他的密码或他用来生成密码的模式。我就直接清除了上一个系统管理员的密码。

有一个非常不错的开源软件工具,专门用于这个任务。在 Linux 主机上,我安装了 chntpw,它的意思大概是:“更改 NT 的密码”。

# dnf -y install chntpw

我关闭了虚拟机的电源,然后将 /dev/sdb3 分区挂载到 /mnt 上。我确定 /dev/sdb3 是正确的分区,因为它是我在之前执行 lshw 命令的输出中看到的第一个大的 NTFS 分区。一定不要在虚拟机运行时挂载该分区,那样会导致虚拟机存储设备上的数据严重损坏。请注意,在其他主机上分区可能有所不同。

导航到 /mnt/Windows/System32/config 目录。如果当前工作目录(PWD)不在这里,chntpw 实用程序就无法工作。请启动该程序。

# chntpw -i SAM
chntpw version 1.00 140201, (c) Petter N Hagen
Hive <SAM> name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c <lh>
File size 131072 [20000] bytes, containing 11 pages (+ 1 headerpage)
Used for data: 367/44720 blocks/bytes, unused: 14/24560 blocks/bytes.

<>========<> chntpw Main Interactive Menu <>========<>

Loaded hives: <SAM>

  1 - Edit user data and passwords
  2 - List groups
      - - -
  9 - Registry editor, now with full write support!
  q - Quit (you will be asked if there is something to save)


What to do? [1] ->

chntpw 命令使用 TUI(文本用户界面),它提供了一套菜单选项。当选择其中一个主要菜单项时,通常会显示一个次要菜单。按照明确的菜单名称,我首先选择了菜单项 1

What to do? [1] -> 1

===== chntpw Edit User Info & Passwords ====

| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrator                  | ADMIN  | dis/lock |
| 03eb | john                           | ADMIN  | dis/lock |
| 01f7 | DefaultAccount                 |        | dis/lock |
| 01f5 | Guest                          |        | dis/lock |
| 01f8 | WDAGUtilityAccount             |        | dis/lock |

Please enter user number (RID) or 0 to exit: [3e9]

接下来,我选择了我们的管理账户 john,在提示下输入 RID。这将显示用户的信息,并提供额外的菜单项来管理账户。

Please enter user number (RID) or 0 to exit: [3e9] 03eb
================= USER EDIT ====================

RID     : 1003 [03eb]
Username: john
fullname:
comment :
homedir :

00000221 = Users (which has 4 members)
00000220 = Administrators (which has 5 members)

Account bits: 0x0214 =
[ ] Disabled        | [ ] Homedir req.    | [ ] Passwd not req. |
[ ] Temp. duplicate | [X] Normal account  | [ ] NMS account     |
[ ] Domain trust ac | [ ] Wks trust act.  | [ ] Srv trust act   |
[X] Pwd don't expir | [ ] Auto lockout    | [ ] (unknown 0x08)  |
[ ] (unknown 0x10)  | [ ] (unknown 0x20)  | [ ] (unknown 0x40)  |

Failed login count: 0, while max tries is: 0
Total  login count: 47

- - - - User Edit Menu:
 1 - Clear (blank) user password
 2 - Unlock and enable user account [probably locked now]
 3 - Promote user (make user an administrator)
 4 - Add user to a group
 5 - Remove user from a group
 q - Quit editing user, back to user select
Select: [q] > 2

这时,我选择了菜单项 2,“ 解锁并启用用户账户 Unlock and enable user account ”,这样就可以删除密码,使我可以不用密码登录。顺便说一下 —— 这就是自动登录。然后我退出了该程序。在继续之前,一定要先卸载 /mnt

我知道,我知道,但为什么不呢! 我已经绕过了这个硬盘和主机的安全问题,所以一点也不重要。这时,我确实登录了旧的管理账户,并为自己创建了一个新的账户,并设置了安全密码。然后,我以自己的身份登录,并删除了旧的管理账户,这样别人就无法使用了。

网上也有 Windows Administrator 账号的使用说明(上面列表中的 01f4)。如果它不是作为组织管理账户,我可以删除或更改该账户的密码。还要注意的是,这个过程也可以从目标主机上运行临场 USB 来执行。

重新激活 Windows

因此,我现在让 Windows SSD 作为虚拟机在我的 Fedora 主机上运行了。然而,令人沮丧的是,在运行了几个小时后,Windows 显示了一条警告信息,表明我需要“激活 Windows”。

在看了许许多多的死胡同网页之后,我终于放弃了使用现有激活码重新激活的尝试,因为它似乎已经以某种方式被破坏了。最后,当我试图进入其中一个在线虚拟支持聊天会话时,虚拟的“获取帮助”应用程序显示我的 Windows 10 Pro 实例已经被激活。这怎么可能呢?它一直希望我激活它,然而当我尝试时,它说它已经被激活了。

或者不

当我在三天内花了好几个小时做研究和实验时,我决定回到原来的 SSD 启动到 Windows 中,以后再来处理这个问题。但后来 Windows —— 即使从原存储设备启动,也要求重新激活。

在微软支持网站上搜索也无济于事。在不得不与之前一样的自动支持大费周章之后,我拨打了提供的电话号码,却被自动响应系统告知,所有对 Windows 10 Pro 的支持都只能通过互联网提供。到现在,我已经晚了将近一天才让电脑运行起来并安装回办公室。

回到未来

我终于吸了一口气,购买了一份 Windows 10 Home,大约 120 美元,并创建了一个带有虚拟存储设备的虚拟机,将其安装在上面。

我将大量的文档和电子表格文件复制到办公室经理的主目录中。我重新安装了一个我们需要的 Windows 程序,并与办公室经理验证了它可以工作,数据都在那里。

总结

因此,我的目标达到了,实际上晚了一天,花了 120 美元,但使用了一种更标准的方法。我仍在对权限进行一些调整,并恢复 Thunderbird 通讯录;我有一些 CSV 备份,但 *.mab 文件在 Windows 驱动器上包含的信息很少。我甚至用 Linux 的 find 命令来定位原始存储设备上的所有。

我走了很多弯路,每次都要自己重新开始。我遇到了一些与这个项目没有直接关系的问题,但却影响了我的工作。这些问题包括一些有趣的事情,比如把 Windows 分区挂载到我的 Linux 机器的 /mnt 上,得到的信息是该分区已经被 Windows 不正确地关闭(是的,在我的 Linux 主机上),并且它已经修复了不一致的地方。即使是 Windows 通过其所谓的“恢复”模式多次重启后也做不到这一点。

也许你从 chntpw 工具的输出数据中发现了一些线索。出于安全考虑,我删掉了主机上显示的其他一些用户账号,但我从这些信息中看到,所有的用户都是管理员。不用说,我也改了。我仍然对我遇到的糟糕的管理方式感到惊讶,但我想我不应该这样。

最后,我被迫购买了一个许可证,但这个许可证至少比原来的要便宜一些。我知道的一点是,一旦我找到了所有必要的信息,Linux 这一块就能完美地工作。问题是处理 Windows 激活的问题。你们中的一些人可能已经成功地让 Windows 重新激活了。如果是这样,我还是想知道你们是怎么做到的,所以请把你们的经验添加到评论中。

这是我不喜欢 Windows,只在自己的系统上使用 Linux 的又一个原因。这也是我将组织中所有的计算机都转换为 Linux 的原因之一。只是需要时间和说服力。我们只剩下这一个会计程序了,我需要和财务主管一起找到一个适合她的程序。我明白这一点 —— 我喜欢自己的工具,我需要它们以一种最适合我的方式工作。


via: https://opensource.com/article/21/1/virtualbox-windows-linux

作者:David Both 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

exa 是一个 Linux ls 命令的现代替代品。

 title=

我们生活在一个繁忙的世界里,当我们需要查找文件和数据时,使用 ls 命令可以节省时间和精力。但如果不经过大量调整,默认的 ls 输出并不十分舒心。当有一个 exa 替代方案时,为什么要花时间眯着眼睛看黑白文字呢?

exa 是一个常规 ls 命令的现代替代品,它让生活变得更轻松。这个工具是用 Rust 编写的,该语言以并行性和安全性而闻名。

安装 exa

要安装 exa,请运行:

$ dnf install exa

探索 exa 的功能

exa 改进了 ls 文件列表,它提供了更多的功能和更好的默认值。它使用颜色来区分文件类型和元数据。它能识别符号链接、扩展属性和 Git。而且它体积小、速度快,只有一个二进制文件。

跟踪文件

你可以使用 exa 来跟踪某个 Git 仓库中新增的文件。

 title=

树形结构

这是 exa 的基本树形结构。--level 的值决定了列表的深度,这里设置为 2。如果你想列出更多的子目录和文件,请增加 --level 的值。

 title=

这个树包含了每个文件的很多元数据。

 title=

配色方案

默认情况下,exa 根据 内置的配色方案 来标识不同的文件类型。它不仅对文件和目录进行颜色编码,还对 Cargo.tomlCMakeLists.txtGruntfile.coffeeGruntfile.jsMakefile 等多种文件类型进行颜色编码。

扩展文件属性

当你使用 exa 探索 xattrs(扩展的文件属性)时,--extended 会显示所有的 xattrs。

 title=

符号链接

exa 能识别符号链接,也能指出实际的文件。

 title=

递归

当你想递归当前目录下所有目录的列表时,exa 能进行递归。

 title=

总结

我相信 `exa 是最简单、最容易适应的工具之一。它帮助我跟踪了很多 Git 和 Maven 文件。它的颜色编码让我更容易在多个子目录中进行搜索,它还能帮助我了解当前的 xattrs。

你是否已经用 exa 替换了 ls?请在评论中分享你的反馈。


via: https://opensource.com/article/21/3/replace-ls-exa

作者:Sudeshna Sur 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

字典数据结构可以帮助你快速访问信息。

 title=

字典是 Python 编程语言使用的数据结构。一个 Python 字典由多个键值对组成;每个键值对将键映射到其关联的值上。

例如你是一名老师,想把学生姓名与成绩对应起来。你可以使用 Python 字典,将学生姓名映射到他们关联的成绩上。此时,键值对中键是姓名,值是对应的成绩。

如果你想知道某个学生的考试成绩,你可以从字典中访问。这种快捷查询方式可以为你节省解析整个列表找到学生成绩的时间。

本文介绍了如何通过键访问对应的字典值。学习前,请确保你已经安装了 Anaconda 包管理器Jupyter 笔记本

1、在 Jupyter 中打开一个新的笔记本

首先在 Web 浏览器中打开并运行 Jupyter。然后,

  1. 转到左上角的 “File”。
  2. 选择 “New Notebook”,点击 “Python 3”。

 title=

开始时,新建的笔记本是无标题的,你可以将其重命名为任何名称。我为我的笔记本取名为 “OpenSource.com Data Dictionary Tutorial”。

笔记本中标有行号的位置就是你写代码的区域,也是你输入的位置。

在 macOS 上,可以同时按 Shift + Return 键得到输出。在创建新的代码区域前,请确保完成上述动作;否则,你写的任何附加代码可能无法运行。

2、新建一个键值对

在字典中输入你希望访问的键与值。输入前,你需要在字典上下文中定义它们的含义:

empty_dictionary = {}
grades = {
    "Kelsey": 87,
    "Finley": 92
}

one_line = {a: 1, b: 2}

 title=

这段代码让字典将特定键与其各自的值关联起来。字典按名称存储数据,从而可以更快地查询。

3、通过键访问字典值

现在你想查询指定的字典值;在上述例子中,字典值指特定学生的成绩。首先,点击 “Insert” 后选择 “Insert Cell Below”。

 title=

在新单元格中,定义字典中的键与值。

然后,告诉字典打印该值的键,找到需要的值。例如,查询名为 Kelsey 的学生的成绩:

# 访问字典中的数据
grades = {
    "Kelsey": 87,
    "Finley": 92
}

print(grades["Kelsey"])
87

 title=

当你查询 Kelsey 的成绩(也就是你想要查询的值)时,如果你用的是 macOS,只需要同时按 Shift+Return 键。

你会在单元格下方看到 Kelsey 的成绩。

4、更新已有的键

当把一位学生的错误成绩添加到字典时,你会怎么办?可以通过更新字典、存储新值来修正这类错误。

首先,选择你想更新的那个键。在上述例子中,假设你错误地输入了 Finley 的成绩,那么 Finley 就是你需要更新的键。

为了更新 Finley 的成绩,你需要在下方插入新的单元格,然后创建一个新的键值对。同时按 Shift+Return 键打印字典全部信息:

grades["Finley"] = 90
print(grades)

{'Kelsey': 87; "Finley": 90}

 title=

单元格下方输出带有 Finley 更新成绩的字典。

5、添加新键

假设你得到一位新学生的考试成绩。你可以用新键值对将那名学生的姓名与成绩补充到字典中。

插入新的单元格,以键值对形式添加新学生的姓名与成绩。当你完成这些后,同时按 Shift+Return 键打印字典全部信息:

grades["Alex"] = 88
print(grades)

{'Kelsey': 87, 'Finley': 90, 'Alex': 88}

 title=

所有的键值对输出在单元格下方。

使用字典

请记住,键与值可以是任意数据类型,但它们很少是 扩展数据类型 non-primitive types 。此外,字典不能以指定的顺序存储、组织里面的数据。如果你想要数据有序,最好使用 Python 列表,而非字典。

如果你考虑使用字典,首先要确认你的数据结构是否是合适的,例如像电话簿的结构。如果不是,列表、元组、树或者其他数据结构可能是更好的选择。


via: https://opensource.com/article/21/3/dictionary-values-python

作者:Lauren Maffeo 选题:lujun9972 译者:DCOLIVERSUN 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Google API 可以凸显出有关 Google 如何对网站进行分类的线索,以及如何调整内容以改进搜索结果的方法。

 title=

作为一名技术性的搜索引擎优化人员,我一直在寻找以新颖的方式使用数据的方法,以更好地了解 Google 如何对网站进行排名。我最近研究了 Google 的 自然语言 API 能否更好地揭示 Google 是如何分类网站内容的。

尽管有 开源 NLP 工具,但我想探索谷歌的工具,前提是它可能在其他产品中使用同样的技术,比如搜索。本文介绍了 Google 的自然语言 API,并探究了常见的自然语言处理(NLP)任务,以及如何使用它们来为网站内容创建提供信息。

了解数据类型

首先,了解 Google 自然语言 API 返回的数据类型非常重要。

实体

实体 Entities 是可以与物理世界中的某些事物联系在一起的文本短语。 命名实体识别 Named Entity Recognition (NER)是 NLP 的难点,因为工具通常需要查看关键字的完整上下文才能理解其用法。例如, 同形异义字 homographs 拼写相同,但是具有多种含义。句子中的 “lead” 是指一种金属:“铅”(名词),使某人移动:“牵领”(动词),还可能是剧本中的主要角色(也是名词)?Google 有 12 种不同类型的实体,还有第 13 个名为 “UNKNOWN”(未知)的统称类别。一些实体与维基百科的文章相关,这表明 知识图谱 对数据的影响。每个实体都会返回一个显著性分数,即其与所提供文本的整体相关性。

 title=

情感

情感 Sentiment ,即对某事的看法或态度,是在文件和句子层面以及文件中发现的单个实体上进行衡量。情感的 得分 score 范围从 -1.0(消极)到 1.0(积极)。 幅度 magnitude 代表情感的 非归一化 non-normalized 强度;它的范围是 0.0 到无穷大。

 title=

语法

语法 Syntax 解析包含了大多数在较好的库中常见的 NLP 活动,例如 词形演变 lemmatization 词性标记 part-of-speech tagging 依赖树解析 dependency-tree parsing 。NLP 主要处理帮助机器理解文本和关键字之间的关系。语法解析是大多数语言处理或理解任务的基础部分。

 title=

分类

分类 Categories 是将整个给定内容分配给特定行业或主题类别,其 置信度 confidence 得分从 0.0 到 1.0。这些分类似乎与其他 Google 工具使用的受众群体和网站类别相同,如 AdWords。

 title=

提取数据

现在,我将提取一些示例数据进行处理。我使用 Google 的 搜索控制台 API 收集了一些搜索查询及其相应的网址。Google 搜索控制台是一个报告人们使用 Google Search 查找网站页面的术语的工具。这个 开源的 Jupyter 笔记本 可以让你提取有关网站的类似数据。在此示例中,我在 2019 年 1 月 1 日至 6 月 1 日期间生成的一个网站(我没有提及名字)上提取了 Google 搜索控制台数据,并将其限制为至少获得一次点击(而不只是 曝光 impressions )的查询。

该数据集包含 2969 个页面和在 Google Search 的结果中显示了该网站网页的 7144 条查询的信息。下表显示,绝大多数页面获得的点击很少,因为该网站侧重于所谓的长尾(越特殊通常就更长尾)而不是短尾(非常笼统,搜索量更大)搜索查询。

 title=

为了减少数据集的大小并仅获得效果最好的页面,我将数据集限制为在此期间至少获得 20 次曝光的页面。这是精炼数据集的按页点击的柱状图,其中包括 723 个页面:

 title=

在 Python 中使用 Google 自然语言 API 库

要测试 API,在 Python 中创建一个利用 google-cloud-language 库的小脚本。以下代码基于 Python 3.5+。

首先,激活一个新的虚拟环境并安装库。用环境的唯一名称替换 <your-env>

virtualenv <your-env>
source <your-env>/bin/activate
pip install --upgrade google-cloud-language
pip install --upgrade requests

该脚本从 URL 提取 HTML,并将 HTML 提供给自然语言 API。返回一个包含 sentimententitiescategories 的字典,其中这些键的值都是列表。我使用 Jupyter 笔记本运行此代码,因为使用同一内核注释和重试代码更加容易。

# Import needed libraries
import requests
import json

from google.cloud import language
from google.oauth2 import service_account
from google.cloud.language import enums
from google.cloud.language import types

# Build language API client (requires service account key)
client = language.LanguageServiceClient.from_service_account_json('services.json')

# Define functions
def pull_googlenlp(client, url, invalid_types = ['OTHER'], **data):
   
        html = load_text_from_url(url, **data)
   
        if not html:
        return None
   
        document = types.Document(
        content=html,
        type=language.enums.Document.Type.HTML )

        features = {'extract_syntax': True,
                'extract_entities': True,
                'extract_document_sentiment': True,
                'extract_entity_sentiment': True,
                'classify_text': False
                }
   
        response = client.annotate_text(document=document, features=features)
        sentiment = response.document_sentiment
        entities = response.entities
   
        response = client.classify_text(document)
        categories = response.categories
         
        def get_type(type):
        return client.enums.Entity.Type(entity.type).name
   
        result = {}
   
        result['sentiment'] = []    
        result['entities'] = []
        result['categories'] = []

        if sentiment:
        result['sentiment'] = [{ 'magnitude': sentiment.magnitude, 'score':sentiment.score }]
         
        for entity in entities:
        if get_type(entity.type) not in invalid_types:
                result['entities'].append({'name': entity.name, 'type': get_type(entity.type), 'salience': entity.salience, 'wikipedia_url': entity.metadata.get('wikipedia_url', '-')  })
         
        for category in categories:
        result['categories'].append({'name':category.name, 'confidence': category.confidence})
         
         
        return result


def load_text_from_url(url, **data):

        timeout = data.get('timeout', 20)
   
        results = []
   
        try:
         
        print("Extracting text from: {}".format(url))
        response = requests.get(url, timeout=timeout)

        text = response.text
        status = response.status_code

        if status == 200 and len(text) > 0:
                return text
         
        return None
         

        except Exception as e:
        print('Problem with url: {0}.'.format(url))
        return None

要访问该 API,请按照 Google 的 快速入门说明 在 Google 云主控台中创建一个项目,启用该 API 并下载服务帐户密钥。之后,你应该拥有一个类似于以下内容的 JSON 文件:

 title=

命名为 services.json,并上传到项目文件夹。

然后,你可以通过运行以下程序来提取任何 URL(例如 Opensource.com)的 API 数据:

url = "https://opensource.com/article/19/6/how-ssh-running-container"
pull_googlenlp(client,url)

如果设置正确,你将看到以下输出:

 title=

为了使入门更加容易,我创建了一个 Jupyter 笔记本,你可以下载并使用它来测试提取网页的实体、类别和情感。我更喜欢使用 JupyterLab,它是 Jupyter 笔记本的扩展,其中包括文件查看器和其他增强的用户体验功能。如果你不熟悉这些工具,我认为利用 Anaconda 是开始使用 Python 和 Jupyter 的最简单途径。它使安装和设置 Python 以及常用库变得非常容易,尤其是在 Windows 上。

处理数据

使用这些函数,可抓取给定页面的 HTML 并将其传递给自然语言 API,我可以对 723 个 URL 进行一些分析。首先,我将通过查看所有页面中返回的顶级分类的数量来查看与网站相关的分类。

分类

 title=

这似乎是该特定站点的关键主题的相当准确的代表。通过查看一个效果最好的页面进行排名的单个查询,我可以比较同一查询在 Google 搜索结果中的其他排名页面。

  • URL 1 |顶级类别:/法律和政府/与法律相关的(0.5099999904632568)共 1 个类别。
  • 未返回任何类别。
  • URL 3 |顶级类别:/互联网与电信/移动与无线(0.6100000143051147)共 1 个类别。
  • URL 4 |顶级类别:/计算机与电子产品/软件(0.5799999833106995)共有 2 个类别。
  • URL 5 |顶级类别:/互联网与电信/移动与无线/移动应用程序和附件(0.75)共有 1 个类别。
  • 未返回任何类别。
  • URL 7 |顶级类别:/计算机与电子/软件/商业与生产力软件(0.7099999785423279)共 2 个类别。
  • URL 8 |顶级类别:/法律和政府/与法律相关的(0.8999999761581421)共 3 个类别。
  • URL 9 |顶级类别:/参考/一般参考/类型指南和模板(0.6399999856948853)共有 1 个类别。
  • 未返回任何类别。

上方括号中的数字表示 Google 对页面内容与该分类相关的置信度。对于相同分类,第八个结果比第一个结果具有更高的置信度,因此,这似乎不是定义排名相关性的灵丹妙药。此外,分类太宽泛导致无法满足特定搜索主题的需要。

通过排名查看平均置信度,这两个指标之间似乎没有相关性,至少对于此数据集而言如此:

 title=

这两种方法对网站进行规模审查是有意义的,以确保内容类别易于理解,并且样板或销售内容不会使你的页面与你的主要专业知识领域无关。想一想,如果你出售工业用品,但是你的页面返回 “Marketing(销售)” 作为主要分类。似乎没有一个强烈的迹象表明,分类相关性与你的排名有什么关系,至少在页面级别如此。

情感

我不会在情感上花很多时间。在所有从 API 返回情感的页面中,它们分为两个区间:0.1 和 0.2,这几乎是中立的情感。根据直方图,很容易看出情感没有太大价值。对于新闻或舆论网站而言,测量特定页面的情感到中位数排名之间的相关性将是一个更加有趣的指标。

 title=

实体

在我看来,实体是 API 中最有趣的部分。这是在所有页面中按 显著性 salience (或与页面的相关性)选择的顶级实体。请注意,对于相同的术语(销售清单),Google 会推断出不同的类型,可能是错误的。这是由于这些术语出现在内容中的不同上下文中引起的。

 title=

然后,我分别查看了每个实体类型,并一起查看了该实体的显著性与页面的最佳排名位置之间是否存在任何关联。对于每种类型,我匹配了与该类型匹配的顶级实体的显著性(与页面的整体相关性),按显著性排序(降序)。

有些实体类型在所有示例中返回的显著性为零,因此我从下面的图表中省略了这些结果。

 title=

“Consumer Good(消费性商品)” 实体类型具有最高的正相关性, 皮尔森相关度 Pearson correlation 为 0.15854,尽管由于较低编号的排名更好,所以 “Person” 实体的结果最好,相关度为 -0.15483。这是一个非常小的样本集,尤其是对于单个实体类型,我不能对数据做太多的判断。我没有发现任何具有强相关性的值,但是 “Person” 实体最有意义。网站通常都有关于其首席执行官和其他主要雇员的页面,这些页面很可能在这些查询的搜索结果方面做得好。

继续,当从整体上看站点,根据实体名称和实体类型,出现了以下主题。

 title=

我模糊了几个看起来过于具体的结果,以掩盖网站的身份。从主题上讲,名称信息是在你(或竞争对手)的网站上局部查看其核心主题的一种好方法。这样做仅基于示例网站的排名网址,而不是基于所有网站的可能网址(因为 Search Console 数据仅记录 Google 中展示的页面),但是结果会很有趣,尤其是当你使用像 Ahrefs 之类的工具提取一个网站的主要排名 URL,该工具会跟踪许多查询以及这些查询的 Google 搜索结果。

实体数据中另一个有趣的部分是标记为 “CONSUMER\_GOOD” 的实体倾向于 “看起来” 像我在看到 “ 知识结果 Knowledge Results ”的结果,即页面右侧的 Google 搜索结果。

 title=

在我们的数据集中具有三个或三个以上关键字的 “Consumer Good(消费性商品)” 实体名称中,有 5.8% 的知识结果与 Google 对该实体命名的结果相同。这意味着,如果你在 Google 中搜索术语或短语,则右侧的框(例如,上面显示 Linux 的知识结果)将显示在搜索结果页面中。由于 Google 会 “挑选” 代表实体的示例网页,因此这是一个很好的机会,可以在搜索结果中识别出具有唯一特征的机会。同样有趣的是,5.8% 的在 Google 中显示这些知识结果名称中,没有一个实体的维基百科 URL 从自然语言 API 中返回。这很有趣,值得进行额外的分析。这将是非常有用的,特别是对于传统的全球排名跟踪工具(如 Ahrefs)数据库中没有的更深奥的主题。

如前所述,知识结果对于那些希望自己的内容在 Google 中被收录的网站所有者来说是非常重要的,因为它们在桌面搜索中加强高亮显示。假设,它们也很可能与 Google Discover 的知识库主题保持一致,这是一款适用于 Android 和 iOS 的产品,它试图根据用户感兴趣但没有明确搜索的主题为用户浮现内容。

总结

本文介绍了 Google 的自然语言 API,分享了一些代码,并研究了此 API 对网站所有者可能有用的方式。关键要点是:

  • 学习使用 Python 和 Jupyter 笔记本可以为你的数据收集任务打开到一个由令人难以置信的聪明和有才华的人建立的不可思议的 API 和开源项目(如 Pandas 和 NumPy)的世界。
  • Python 允许我为了一个特定目的快速提取和测试有关 API 值的假设。
  • 通过 Google 的分类 API 传递网站页面可能是一项很好的检查,以确保其内容分解成正确的主题分类。对于竞争对手的网站执行此操作还可以提供有关在何处进行调整或创建内容的指导。
  • 对于示例网站,Google 的情感评分似乎并不是一个有趣的指标,但是对于新闻或基于意见的网站,它可能是一个有趣的指标。
  • Google 发现的实体从整体上提供了更细化的网站的主题级别视图,并且像分类一样,在竞争性内容分析中使用将非常有趣。
  • 实体可以帮助定义机会,使你的内容可以与搜索结果或 Google Discover 结果中的 Google 知识块保持一致。我们将 5.8% 的结果设置为更长的(字计数)“Consumer Goods(消费商品)” 实体,显示这些结果,对于某些网站来说,可能有机会更好地优化这些实体的页面显著性分数,从而有更好的机会在 Google 搜索结果或 Google Discovers 建议中抓住这个重要作用的位置。

via: https://opensource.com/article/19/7/python-google-natural-language-api

作者:JR Oakes 选题:lujun9972 译者:stevenzdg988 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

了解在 Firefox 上运行 WebAssembly 的机会和局限性。

 title=

WebAssembly 是一种可移植的执行格式,由于它能够以近乎原生的速度在浏览器中执行应用而引起了人们的极大兴趣。WebAssembly 本质上有一些特殊的属性和局限性。但是,通过将其与其他技术结合,将出现全新的可能性,尤其是与浏览器中的游戏有关的可能性。

本文介绍了在 Firefox 上运行 WebAssembly 的概念、可能性和局限性。

沙盒

WebAssembly 有 严格的安全策略。 WebAssembly 中的程序或功能单元称为模块。每个模块实例都运行在自己的隔离内存空间中。因此,即使同一个网页加载了多个模块,它们也无法访问另一个模块的虚拟地址空间。设计上,WebAssembly 还考虑了内存安全性和控制流完整性,这使得(几乎)确定性的执行成为可能。

Web API

通过 JavaScript Web API 可以访问多种输入和输出设备。根据这个 提案,将来可以不用绕道到 JavaScript 来访问 Web API。C++ 程序员可以在 Emscripten.org 上找到有关访问 Web API 的信息。Rust 程序员可以使用 rustwasm.github.io 中写的 wasm-bindgen 库。

文件输入/输出

因为 WebAssembly 是在沙盒环境中执行的,所以当它在浏览器中执行时,它无法访问主机的文件系统。但是,Emscripten 提供了虚拟文件系统形式的解决方案。

Emscripten 使在编译时将文件预加载到内存文件系统成为可能。然后可以像在普通文件系统上一样从 WebAssembly 应用中读取这些文件。这个 教程 提供了更多信息。

持久化数据

如果你需要在客户端存储持久化数据,那么必须通过 JavaScript Web API 来完成。请参考 Mozilla 开发者网络(MDN)关于 浏览器存储限制和过期标准 的文档,了解不同方法的详细信息。

内存管理

WebAssembly 模块作为 堆栈机 在线性内存上运行。这意味着堆内存分配等概念是没有的。然而,如果你在 C++ 中使用 new 或者在 Rust 中使用 Box::new,你会期望它会进行堆内存分配。将堆内存分配请求转换成 WebAssembly 的方式在很大程度上依赖于工具链。你可以在 Frank Rehberger 关于 WebAssembly 和动态内存 的文章中找到关于不同工具链如何处理堆内存分配的详细分析。

游戏!

WebGL 结合使用时,WebAssembly 的执行速度很高,因此可以在浏览器中运行原生游戏。大型专有游戏引擎 Unity虚幻 4 展示了 WebGL 可以实现的功能。也有使用 WebAssembly 和 WebGL 接口的开源游戏引擎。这里有些例子:

有关 WebAssembly 的更多信息

WebAssembly 是一项很有前途的技术,我相信我们将来会越来越多地看到它。除了在浏览器中执行之外,WebAssembly 还可以用作可移植的执行格式。Wasmer 容器主机使你可以在各种平台上执行 WebAssembly 代码。

如果你需要更多的演示、示例和教程,请看一下这个 WebAssembly 主题集合。Mozilla 的 游戏和示例合集 并非全是 WebAssembly,但仍然值得一看。


via: https://opensource.com/article/21/3/webassembly-firefox

作者:Stephan Avenwedde 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Grafana Tempo 是一个新的开源、大容量分布式跟踪后端。

 title=

Grafana 的 Tempo 是出自 Grafana 实验室的一个简单易用、大规模的、分布式的跟踪后端。Tempo 集成了 GrafanaPrometheus 以及 Loki,并且它只需要对象存储进行操作,因此成本低廉,操作简单。

我从一开始就参与了这个开源项目,所以我将介绍一些关于 Tempo 的基础知识,并说明为什么云原生社区会注意到它。

分布式跟踪

想要收集对应用程序请求的遥测数据是很常见的。但是在现在的服务器中,单个应用通常被分割为多个微服务,可能运行在几个不同的节点上。

分布式跟踪是一种获得关于应用的性能细粒度信息的方式,该应用程序可能由离散的服务组成。当请求到达一个应用时,它提供了该请求的生命周期的统一视图。Tempo 的分布式跟踪可以用于单体应用或微服务应用,它提供 请求范围的信息,使其成为可观察性的第三个支柱(另外两个是度量和日志)。

接下来是一个分布式跟踪系统生成应用程序甘特图的示例。它使用 Jaeger HotROD 的演示应用生成跟踪,并把它们存到 Grafana 云托管的 Tempo 上。这个图展示了按照服务和功能划分的请求处理时间。

 title=

减少索引的大小

在丰富且定义良好的数据模型中,跟踪包含大量信息。通常,跟踪后端有两种交互:使用元数据选择器(如服务名或者持续时间)筛选跟踪,以及筛选后的可视化跟踪。

为了加强搜索,大多数的开源分布式跟踪框架会对跟踪中的许多字段进行索引,包括服务名称、操作名称、标记和持续时间。这会导致索引很大,并迫使你使用 Elasticsearch 或者 Cassandra 这样的数据库。但是,这些很难管理,而且大规模运营成本很高,所以我在 Grafana 实验室的团队开始提出一个更好的解决方案。

在 Grafana 中,我们的待命调试工作流从使用指标报表开始(我们使用 Cortex 来存储我们应用中的指标,它是一个云原生基金会孵化的项目,用于扩展 Prometheus),深入研究这个问题,筛选有问题服务的日志(我们将日志存储在 Loki 中,它就像 Prometheus 一样,只不过 Loki 是存日志的),然后查看跟踪给定的请求。我们意识到,我们过滤时所需的所有索引信息都可以在 Cortex 和 Loki 中找到。但是,我们需要一个强大的集成,以通过这些工具实现跟踪的可发现性,并需要一个很赞的存储,以根据跟踪 ID 进行键值查找。

这就是 Grafana Tempo 项目的开始。通过专注于给定检索跟踪 ID 的跟踪,我们将 Tempo 设计为最小依赖性、大容量、低成本的分布式跟踪后端。

操作简单,性价比高

Tempo 使用对象存储后端,这是它唯一的依赖。它既可以被用于单一的二进制下,也可以用于微服务模式(请参考仓库中的 例子,了解如何轻松上手)。使用对象存储还意味着你可以存储大量的应用程序的痕迹,而无需任何采样。这可以确保你永远不会丢弃那百万分之一的出错或具有较高延迟的请求的跟踪。

与开源工具的强大集成

Grafana 7.3 包括了 Tempo 数据源,这意味着你可以在 Grafana UI 中可视化来自Tempo 的跟踪。而且,Loki 2.0 的新查询特性 使得 Tempo 中的跟踪更简单。为了与 Prometheus 集成,该团队正在添加对 范例 exemplar 的支持,范例是可以添加到时间序列数据中的高基数元数据信息。度量存储后端不会对它们建立索引,但是你可以在 Grafana UI 中检索和显示度量值。尽管范例可以存储各种元数据,但是在这个用例中,存储跟踪 ID 是为了与 Tempo 紧密集成。

这个例子展示了使用带有请求延迟直方图的范例,其中每个范例数据点都链接到 Tempo 中的一个跟踪。

 title=

元数据一致性

作为容器化应用程序运行的应用发出的遥测数据通常具有一些相关的元数据。这可以包括集群 ID、命名空间、吊舱 IP 等。这对于提供基于需求的信息是好的,但如果你能将元数据中包含的信息用于生产性的东西,那就更好了。 例如,你可以使用 Grafana 云代理将跟踪信息导入 Tempo 中,代理利用 Prometheus 服务发现机制轮询 Kubernetes API 以获取元数据信息,并且将这些标记添加到应用程序发出的跨域数据中。由于这些元数据也在 Loki 中也建立了索引,所以通过元数据转换为 Loki 标签选择器,可以很容易地从跟踪跳转到查看给定服务的日志。

下面是一个一致元数据的示例,它可用于Tempo跟踪中查看给定范围的日志。

云原生

Grafana Tempo 可以作为容器化应用,你可以在如 Kubernetes、Mesos 等编排引擎上运行它。根据获取/查询路径上的工作负载,各种服务可以水平伸缩。你还可以使用云原生的对象存储,如谷歌云存储、Amazon S3 或者 Tempo Azure 博客存储。更多的信息,请阅读 Tempo 文档中的 架构部分

试一试 Tempo

如果这对你和我们一样有用,可以 克隆 Tempo 仓库试一试。


via: https://opensource.com/article/21/2/tempo-distributed-tracing

作者:Annanay Agarwal 选题:lujun9972 译者:RiaXu 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出