我一直觉得 fortune 挺好玩的,最近刚好在学习 python,就试着用 python 写了一个小东西用来从 baidu 中抓取格言,写成 fortune 文件。fortune 文件可以从这里下载:proverbs
1、要让 fortune 能够使用该 fortune 文件,还需要先用 strfile 来产生一个索引文件 proverbs.dat
strfile proverbs
"proverbs.dat" created
There were 760 strings
Longest string: 313 bytes
Shortest string: 28 bytes
2、要将该 fortune 文件安装到 fortune 数据库中,只需要将将 fortune 文件和生成的索引文件一起拷贝到 fortune 存储数据文件的目录中就行了
sudo cp proverbs proverbs.dat /usr/share/fortune
注意:fortune 数据存放目录在不同 linux 发行版上可能不同,具体是在哪,请执行 man fortune 查看
3、如果你不想污染原始的 fortune 数据库,或者没有 root 权限,fortune 也可以用命令行参数直接指定读取的文件:
fortune proverbs
为了搜索格言,我先尝试在 baidu 上搜索了一下格言,结果发现 baidu 除了显示出相关网页链接之外,还显示了一个小窗口里面列出了大量的格言:
点击其中的 1、2、3 页,发现访问的 URL 分别是
https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?from_mid=1&format=json&ie=utf-8&oe=utf-8&subtitle=格言&query=格言&rn=8&pn=0&resource_id=6844&cb=jQuery110208193217330929087_1488263284684&_=1488263284688
https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?from_mid=1&format=json&ie=utf-8&oe=utf-8&subtitle=格言&query=格言&rn=8&pn=8&resource_id=6844&cb=jQuery110208193217330929087_1488263284684&_=1488263284686
https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?from_mid=1&format=json&ie=utf-8&oe=utf-8&subtitle=格言&query=格言&rn=8&pn=16&resource_id=6844&cb=jQuery110208193217330929087_1488263284684&_=1488263284687
URL 中的 %E6%A0%BC%E8%A8%80 就是格言的转义结果。
通过对比这些访问的URL不难推测出其中的参数 rn 应该是每次返回的格言条数,pn 应该指定从第几条格言开始显示。
后面参数 _ 的值虽然在不断的改变,好在经过实验发现这个参数不传递也不会影响结果,事实上,你还能够把 cb 参数也一起省略掉。
另外,经过实验发现 rn 的最大值只能是 50,超过50的值返回的结果依然只有50条格言。
分析出接口地址,再从 JSON 结果中抓取相应的值就很容易了:
def request_proverb(start,number):
'''从百度那获取格言信息,START为起始条数,NUMBER为获取格言条数,不能超过50'''
url = "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php"
params = {"from_mid":1,
"format":"json",
"ie":"utf-8",
"oe":"utf-8",
"subtitle":"格言",
"query":"格言",
"rn":number,
"pn":start,
"resource_id" : 6844}
response = requests.get(url,params=params)
response = json.loads(response.text)
status = response.get('status')
if status != "0":
raise Exception()
data = response.get('data')[0]
resNum = data.get('resNum')
proverbs = data.get('disp_data')
return proverbs
其中,每个格言信息都是一个如下所示的字典:
{'StdStg': 6844, 'StdStl': 8, '_update_time': '1475048807',
'loc': 'http://www.baidu.com/geyan/c880b7476531e5cbf050dce6da74578c',
'lastmod': '2014-06-26', 'changefreq': 'always', 'priority': '1.0',
'type': '格言', 'brief0': '真理,真谛', 'term0': '欧文', 'term': '欧文',
'ename': '真理惟一可靠的标准就是永远自相符合。', 'stat0': '真理', 'statctl': 'stat0',
'statlst': '类别', 'author': '欧文', 'pv': '59', 'SiteId': 2003651,
'_version': 5, '_select_time': 1475048794}
不过我们只需要其中的 ename 和 author 这两个信息。
fortune 文件格式蛮简单的,只需要用 只包含%的行 将各格言内容分开就行了。
每条格言,我希望显示成 格言的内容 后面跟一个横杠,再跟上 作者 这样。
真理惟一可靠的标准就是永远自相符合。
-欧文
%
土地是以它的肥沃和收获而被估价的;才能也是土地,不过它生产的不是粮食,而是真理。
如果只能滋生瞑想和幻想的话,即使再大的才能也只是砂地或盐池,那上面连小草也长不出来的。
-别林斯基
使用字符串的 format 方法可以很容易的控制生成的格言格式
def proverb_to_fortune_item(proverb):
author = proverb.get('author','')
ename = proverb.get('ename','')
return "{ename}\n\t-{author}\n".format(ename=ename,author=author)
最后再用 "%\n" 作为分隔符将每条格言拼接起来就完成了
def proverbs_to_fortune_file(proverbs,fortune_file):
with open(fortune_file,mode="a") as f:
fortune_items = [proverb_to_fortune_item(proverb) for proverb in proverbs]
f.write('%\n'.join(fortune_items))
