使用python的requests包执行网络请求非常方便,可以便利地设置headers、cookies以及请求数据。根据多年使用requests包的经验,以及最近给一个客户的写的代码,下面总结出该包的最佳实践方式。

整体的结构

def read_header_file(header_path):
    # 加载代码

if __name__ == '__main__':
    s = requests.Session()
    read_header_file(header_path)
    # 执行请求,无论是get或者post,则无需再设置headers和cookies
    s.get('<url>')

headers以及cookies的获取

如果使用chrome浏览器,则按F12键后可以调出浏览器的开发工具,然后按照下图所示的方式可以获取到请求的headers和cookies,将其保存为一个文件。

headers和cookies获取的示意图

如果对于cookies的要求细节比较多,那么可以在chrome浏览器中安装EditThisCookie插件,然后按照如下图的方式获取Json格式的cookies。

使用EditThisCookie获取Json格式的cookies

加载headers和cookies

import pandas as pd

def read_header_file(header_path):
    df = pd.read_csv(header_path, skiprows=1, skipfooter=1,
                     header=None, engine="python", sep=r"\s*'\s*", usecols=[1])
    for _, r in df.iterrows():
        v = r.values[0]
        if 'cookie' in v.lower():
            jc = v.split(': ', 1)
            for kv in jc[1].split(';'):
                s.cookies.update(dict([kv.split('=', 1)]))
        else:
            s.headers.update(dict([v.split(': ', 1)]))

其中header_path变量指的就是之前保存的bash格式的请求文件。

pandas中的read_csv函数非常强大,可以非常方便将一些没有结构化的数据转换成结构化数据。dict函数可以将类似[[a, b]]转换成字典。或者结合for...in...语句,将更多偶数的列表转换成字典。

# INPUT: a = [1, 2, 3, 4]
[dict([a[i:i+2]]) for i in range(0, len(a), 2)]
# OUTPUT: [{1: 2}, {3: 4}]

有时候我们下载到一些PDF格式的书籍,虽然包含了页面目录,但不是书签形式的,阅读起来不是很方便。那么如何根据书籍的页面目录,快速创建书签目录呢。本篇博文是基于python库pdfbookmarker的一个处理方案。其地址参见:https://github.com/RussellLuo/pdfbookmarker

将目录转换成TXT格式的目录文件

如果是扫描版本的PDF文件,建议使用金山PDF阅读器自带的扫描件识别功能,先将目录部分转换成可以选择的PDF格式(OCR功能)。然后再利用Adobe PDF阅读器的列选择功能,将PDF页面目录拷贝到TXT格式的目录文件中。拷贝方法为:首先按Shift + ALT键,待鼠标指针变化成选择框的时候,再行复制。目前还不知道金山PDF阅读器的列选择功能怎么使,但是Adobe PDF阅读器的这个功能非常不错,尤其是对于双栏目录,不使用列选择功能复制后就会混合在一起。

使用正则格式化目录文件

TXT文件复制制作完成之后,可能还存在很多的问题。例如有些目录因为文字部分太长,就会出现串行。

  • 串行问题
Chapter 6 REACTION EQUILIBRIUM IN IDEAL GAS MIXTURES 174
6.1 Chemical Potentials in an Ideal Gas Mixture 175
6.2 Ideal-Gas Reaction Equilibrium 177
6.3 Temperature Dependence
of the Equilibrium Constant 182
6.4 Ideal-Gas Equilibrium Calculations 186
6.5 Simultaneous Equilibria 191

例如上面的目录,6.3节的目录出现了串行。可以使用如下的正则解决(下面的正则替换均需在Visual Studio Code软件中使用,因为不同的编辑器支持的正则方言不一样)。

# 查找正则
(?<!\d)\n
# 替换部分,输入一个空格就成

如果因为文档的字迹不清楚,导致拷贝后的效果不好,那么可能需要手工校对。字迹清楚的一般不会有其他问题。

将目录格式化成python脚本需要的格式

++"TEXT TITLE"|N

其中+的数量代表level的级别,N代表页码的数字。由于每本书籍的目录格式是不一样的,编写具有鲁棒性的脚本比较困难。我们还是可以使用正则进行针对性的格式化。以上述的目录为例。

  • 给每一行目录增加+"符号(level=1的目录)
# 查找正则
^
# 替换
+"

这样,章一级(level=1)的基本就处理完成了,那么针对节一级(level=2)的还需要替换。

  • 格式化节一级的目录(level=2的目录)
# 查找正则,如果前边的数字包含点,代表为节一级,当然下边的写法比较随意
"(\d*?[.])
# 替换
+"$1
  • Level等于3部分的目录格式化
# 查找正则
"((\d*?[.]){2})
# 替换正则
+"$1
  • 页面数字部分的格式化
# 查找正则
\s*?(\d+)(?=\n)
# 替换
"|$1

这里可能需要经常性的使用正则中的零宽度断言,如有不熟悉或者遗忘,可以参见:https://www.cnblogs.com/macq/p/6597366.html

处理页面目录位置偏移

做完上面的步骤,目录的格式已经处理完毕。但是对于大部分的书籍,其页面目录中对应的数字和实际的PDF页面位置存在一个偏移,由于正则替换功能没有数字计算的功能,因此只能使用脚本了。这里使用Powershell脚本。

param (
    [Parameter(Mandatory)]
    [string]$Path,

    [int]$Gain = 5
)

$OutPath = "{0}-p.ini" -f $Path.Substring(0, $Path.LastIndexOf("."))

Get-Content $Path | % {
    $lr = $_.Split("|")
    "{0}|{1}" -f @($lr[0], ([int]$lr[1] + $Gain))
} | Out-File $OutPath

假设powershell脚本的名字为cp.ps1,那么调用的方式为:

.\cp.ps1 -Path content.txt -Gain 18

其中Gain参数对应偏移的量。对于有些比较变态的书籍,每一个章节的偏移量都不一样,这个时候就需要对脚本进行一些修改了。

小结:对于%循环中的输出,如果出现变量赋值,代表该变量不会传递给下一个命令,否则就会传递。

如果vscode安装了Replace Selection插件,那么不必使用powershell脚本也可以实现页面数字的增加和修改。步骤如下:(1)使用正则表达式$选择所有的结尾,然后在结尾处插入+offset,其中offset为需要增加的数字;(2)使用CTRL+SHIFT+<-增加选择范围,直到覆盖原来的数字;(3)使用插件中Replace with Evaluated Javascript Result命令执行eval功能。更加详细的步骤,可以查看一下视频。

添加书签目录

假设书签的文件名为c.txt,PDF文件的名称为c.pdf则调用的方法为:

pdfbm c.pdf c.txt [c-p.pdf]

其中输出文件的名称是可选的,如果不设置,其名称为原名称加上-new后缀。

以上就是PDF文件的书签目录制作流程,看起来还是比较复杂的,流程有点多,但是如果每一步比较熟,还是很快的。尤其对于那种几百页上千页的PDF文件,这种方式比手工制作目录肯定方便不少。

jekyll搭配markdown写作是一件非常方便的事情,可以直接在本地写完,然后使用git进行版本控制。然而,鉴于当前恶劣的网络环境,寻找一个稳定的、能用的jekyll平台变得非常困难。github由于是国外公司,ghpages经常无法正常访问,而国内的一些git平台,虽然速度通常快很多,但是条款经常变化。例如,我曾经使用了一阵子gitee,但是后面这个网站只能Pro版的用户定制域名,甚至在后面因为需要清理站点,几个月无法提交pages服务。而coding.net网站,也是开始好好的,后面就和腾讯云合作,jekyll的运行环境变得不定,特别容易发生提交出错。

那么,如果自己有服务器,且是Windows服务器的情况下,如何安装jekyll环境呢(Ps,最近腾讯云有那个轻量级应用服务器,60元就可以玩一年,所以买了一个做测试。)。

jekyll环境的安装

gem install jekyll
gem install jekyll-paginate
gem install jekyll-minimal

安装完成之后,运行jekyll server即可生成服务。不过,后面为了放在后台运行,可以使用powershell脚本的Start-Process命令。

编写应对hook的脚本

类似github、gitee等软件平台,提供push等事件的hook。即如果我们将编写的post提交到网站上,将触发一个hook事件,调用一个我们提供的网址。这个时候,我们可以使用powershell编写一个简单的http服务器,当接收到hook的请求,脚本就将网站中的repo更新到本地,从而达到更新网站的目的。很多网站都会提供密码验证服务,避免收到攻击。

对于http服务器的创建,可以使用python脚本,只需要非常简单的的几行就可以。不过需要安装python解析器。如果实在较新的windows系统中,还可以基于powershell脚本使用System.Net.HttpListener去实现。需要注意通常的hook必须是实现了POST请求类型,如果没有,可能导致超时错误。

$http = New-Object System.Net.HttpListener

由于使用git更新repo内容,尤其是提交的东西较多或者网络不好时,是一个较为耗时的过程,容易导致hook调用发生time out错误。此时,可以使用ps中的Start-Job功能,将这个耗时的动作放在背景线程中去执行,例如:

Start-Job -ScriptBlock{
    Push-Location -Path "location of your git repo"
    git pull
    Pop-Location
}

注明Start-Job执行的背景线程,依赖于主线程。如果主线程关闭,背景线程也将会关闭,此与Start-Process不同。

后台运行

  • 运行jekyll
Start-Process powershell -WindowStyle Hidden -ArgumentList "jekyll server"

后台的进程实际有Ruby执行。

  • 运行HttpListener脚本
Start-Process powershell -WindowStyle Hidden -ArgumentList "powershell_script_filepath"
  • 运行nginx(前端服务器)
Start-Process nginx -WindowStyle Hidden

exe程序可以独立运行,不需要借助于powershell。在nginx的配置文件中,将powershell的HttpLisener和ruby的jekyll脚本设置为后端代理,nginx作为前端处理流量。这样可以实现多个域名对应多个服务器了。

错误解决

安装完成之后,可能发现标题带有中文的页面无法访问,这个时候可以参考一下网页解决: https://guosongyu.github.io/2020/01/jekyll%E4%BD%BF%E7%94%A8%E4%B8%AD%E6%96%87%E8%B7%AF%E5%BE%84,主要是Ruby处理中文字符出现的编码问题,将编码设置为utf-8即可。

论文写作过程中,通过涉及投稿、修改、改投等各种环节,正好tex文件是文本格式的,那么git就成为了不二之选的版本控制工具。对于一般的latex文档写作,vscode结合LaTeX Workshop插件,足以应付。但是,如果我们需要生成当前版本和上一个commit之间的,包含修改内容、位置信息的PDF文件,就需要进行额外的设置了。这里我们以vscode为载体,讲解如何实现这一过程。

软件准备

工欲善其事必先利其器,vscode结合以下插件,非常有帮助。

  • LaTeX Workshop (插件)
  • LaTeX language support (插件)
  • LaTeX Utilities (插件)
  • LTex - English support (插件)
  • Template Generator
  • LaTeX Snippets

其中LaTeX Workshop是基本。LaTeX Utilities可以提供字数统计的功能。Template Generator可以提供模板的功能。写作过程中,如果有模板功能,那么一些重复的、繁琐的设置就可以统一解决了。LaTeX Snippets可以在模板的基础上,为一些代码较多的环境提供帮助,比如figuretable等等。

软件设置

软件设置部分就是最耗时耗力的地方了。好在,设置一次之后,就不用再次设置。默认你使用的git进行版本控制。假设当前文件的相对路径为${relativeFile},全名为${fileBaseName},不包含后缀的为${fileBaseNameWithoutExtension},其父路径为${relativeDir}。一般来说,得到校对格式的PDF需要经过以下步骤:

  • 获得上一个commit的文件的tex代码,在git里边可以使用^head代表上一个commit(另外一种表示head~x代表倒数第x次commit)。可以使用如下代码实现该功能:
git show ^head:${relativeFile} > tmp.tex

然而,由于${relativeFile}在windows中使用的路径分割符号为\,但是git是无法识别这个的。解决的办法为,将路径传导一个自定义的bat文件中,在其中将路径的分隔符进行替换,然后再执行操作。一个示例的文件如下:

@echo off

@REM modify source path
set source=%1
set uSource=%source:\=/%

@REM modify dest path
set dest=%2
set uDest=%dest:\=/%

git show ^head:%uSource% > %uDest%
  • 将上一个版本的tex文件和当前版本的tex进行校对,使用latexdiff工具。
latexdiff tmp.tex ${relativeFile} > tmpdiff.tex
  • 编译校对后的tex文件,生成pdf文件。这里我们使用latexmk工具。
latexmk --xelatex -interaction=nonstopmode ${relativeDir}\\tmpdiff.tex
xdvipdfmx ${relativeDir}\\tmpdiff
  • 清理残余的文件,如果是在windows下,直接使用del命令
del /s *.aux *.bbl...

将这四个命令,分别使用vscode的task功能变成4个task,然后再新建一个task,依次运行即可。

"dependsOrder": "sequence",
"dependsOn": [
    "Export Previous LaTeX Version",
    "Create LaTeX Diff File",
    "Compfile Diff File with LatexMK",
    "Clean Compiled Files"
],

需要额外注意dependsOrder项,这个必须设置,否则依赖项的执行变成并行和随机的了,将产生错误。

文件预览

文件预览可以使用系统默认的软件打开,使用如下命令:

explorer `${relativeFile}`

也可以使用vscode进行打开,例如:

code `${relativeFile}`

但是这些打开方式均有一个缺点,就是如果我更新了PDF文件,无法自动更新。其实,如果我们将PDF文件使用右侧打开的功能之后,只要不关闭,那么下次重新编译tex文件,PDF的内容会自动更新到tab中,这样还解决了反复开关PDF软件的繁琐问题。

额外的经验

如何安装bst文件。如果我们自定义了一些bst文件,需要按照并全局使用,可以先搜索其他bst文件所在的文件,我的在C:\texlive\2019\texmf-dist\bibtex\bst。那么创建一个自定义的文件夹,然后将bst文件拷贝到这个自定义的文件夹中,最后使用mktexlsr命令安装。

latexmk结合xelatex选项,默认可以识别是否需要增加编译次数,产生文献引用的内容。然而,如果tex的文件名是中文的时候,将导致无法找到bbl文件的错误,使得引用部分无法变成成功。

首先得说,该文章目前只是根据网友的回答所得的一个初步的初步结论,有可能非常不可靠,需要再详细阅读专业的书籍、文献以及实验来进一步论证。

在实验过程中,需要将AuNR@Ag包覆一层$\ce{Cu2O}$,但是奇怪的是,经常出现$\ce{Cu2O}$包覆成功了,而Ag层却被刻蚀掉了。这个现象尤其是使用AA作为还原剂的时候,基本都会发生,从而形成一种棺材结构($\ce{AuNR@void@Cu2O}$)。

如果使用新配置的$\ce{NH3OHCl}$去还原,也会产生类似的结构,不过好一点的事情是$\ce{Cu2O}$的壳层通常是完备的。但是根据实验发现,如果$\ce{NH3OHCl}$放置的时间久一些之后,似乎其还原性变弱了,导致形成的结构颜色从蓝色变成了紫色,也就是中间的Ag层被刻蚀的几率边小了。

对于制备$\ce{AuNR@Ag@Cu2O}$结构,文献中通常使用水合肼来还原,不过这种危险的化学物品现在不容易购买,因此实验中没有使用。

小木虫网友在探讨盐酸羟胺在碱性环境下的还原性时,表明盐酸羟胺在碱性条件下,其还原性弱于在酸性条件下,同时其还原性弱于AA1。这是否表明,为了降低$\ce{NH3OHCl}$的还原性,可以通过加入更多的NaOH来调控实现呢?

在探讨水合肼与盐酸羟胺的还原性时,有网友表示,盐酸羟胺的还原性比水合肼要强2

因此,是不是为了实现制备中间Ag不被刻蚀的$\ce{AuNR@Ag@Cu2O}$纳米结构,最佳的实验是使用还原性比较弱的水合肼,其次是盐酸羟胺。如果使用盐酸羟胺,则最好在强碱性情况下。如果需要制备$\ce{AuNR@void@Cu2O}$结构,最好使用AA作为还原剂,不过$\ce{Cu2O}$的壳层不够封闭。因此可以使用新配置的$\ce{NH3OHCl}$结构,而NaOH加入量不要太多。

参考