Coding的痕迹

一位互联网奔跑者的网上日记

0%

在 Postgresql-13 中使用 Python3

前期爬取了网上的一些文章,并存储到 PostgreSQL 中。但是当时用以提取发布日期的方法不太好,提取成功率很低。幸好观察存储的 URL,似乎其中包含了发布日期。格式大概是:

1
2
3
'/2020/0909/random_numbers/page.htm'
# 或
'/_t147/2020/0909/random_numbers/page.htm'

便想到在 PostgreSQL 中调用 Python 实现日期提取。

安装 plpython3u 扩展

环境:

  • PostgreSQL 13.2
  • Python 3.8.5

PostgreSQL 的扩展性很好。曾经在 《PostgreSQL 服务端编程》中了解过这种对不同语言插件的扩展性,今天便来试一试。我的 pg 是运行在 Debian 上的,可以使用 apt 命令安装:

1
apt install postgresql-plpython3-13 postgresql-plpython3-13-dbgsym

网上的资料多是 Redhat 那一类系统的,可能因为 PostgreSQL 官方在下载页给出了 rpm 包。我是使用 apt search 搜索的:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@KiteAgentEnv:~# apt search postgresql-plpython
Sorting... Done
Full Text Search... Done

(省略)

postgresql-plpython3-13/focal-pgdg,now 13.2-1.pgdg20.04+1 amd64 [installed]
PL/Python 3 procedural language for PostgreSQL 13

postgresql-plpython3-13-dbgsym/focal-pgdg,now 13.2-1.pgdg20.04+1 amd64 [installed]
debug symbols for postgresql-plpython3-13

root@KiteAgentEnv:~#

如果没有配置 PostgreSQL 的 apt 源,需要事先设置一下,设置方法见 官方 Wiki我的上一篇博客

一般来说不需要重启服务器,就可以在可用扩展列表中看到了:

1
SELECT name FROM pg_available_extensions;

然后执行以在当前数据库中启用扩展:

1
CREATE EXTENSION plpython3u;

编写函数

简单地编写函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE OR REPLACE FUNCTION try_parse_date(path text)
RETURNS text
AS $$
import re

r = re.search(r'/(20[012]\d/\d{4})/', path)
if r:
date_str = r.group(1)
year = date_str[:4]
month = date_str[-4:-2]
day = date_str[-2:]

return f'{year}-{month}-{day}'

$$ LANGUAGE plpython3u;

然后执行:

1
SELECT try_parse_date('/2020/0909/c12570a187683/page.htm')::date;

瞅着可以,拿去试试——对于约 12 万条文章,用时 5 m 22 s 605 ms。执行过程中CPU占用在单核且 10% 左右,但是对于用时来说这个效率有点低。可能的原因是每次都加载了 re 模块,并且正则表达式较普通的字符串处理更慢。不过,对于这样的小任务来说,用时足够短了。

参考资料

  1. 第 45 章 PL/Python - Python 过程语言, PostgreSQL 官方文档
  2. PostgreSQL: how to install plpythonu extension, StackOverflow