如何在tomcat中允许远程deploy

I installed the tomcat 8.5.35 remotely on other machine. I did the following steps to solve this problem:

1. Change $TOMCAT_HOME/conf/server.xml (Same as the course)

<role rolename=”manager-script”/>

<role rolename=”manager-gui”/>

<role rolename=”admin-gui”/>

<user username=”tomcat” password=”tomcat” roles=”manager-script,admin-gui,manager-gui”/>

2. Because the default version come with Catalina directory, I put another file in the $TOMCAT_HOME/conf/Catalina/localhostfolder, named manager.xml, in which the content is:

<?xml version=”1.0″ encoding=”UTF-8″?>

<Context privileged=”true” antiResourceLocking=”false”

docBase=”${catalina.home}/webapps/manager”>

<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”^.*$” />

</Context>

3. Save and restart and profit.

linux在(无root权限,无互联网连接,无pypi源)服务器环境中安装python包

安全性和可用性是反比关系

通过这篇文章,你会学到:

  1. 如何通过非root用户安装python
  2. 如何通过非root用户安装pip
  3. 如何在无互联网的条件下安装python的包
  4. 验证安装成功

1. 如何通过非root用户安装python

  1. 下载源码之后,先进行shasum校验通过。
  2. 解压缩,并执行
    ./configure prefix=/home/username/python
    make install
  3. 然后把路径加到.*rc文件中
    PYTHONPATH=/home/username/python/bin
    export PATH=$PYTHONPATH:$PATH
  4. source .*rc重启,并且通过which python验证是否成功。

参考

2. 如何通过非root用户安装pip

TL;DR

  1. 把pip的wheel文件下载下来。
  2. 执行python pip-9.0.1-py2.py3-none-any.whl/pip install --no-index pip-9.0.1-py2.py3-none-any.whl

Long Version

这个链接中的pfmoore写的答案,注意他提到上面写的这个安装方法没有提供任何warranty。

3. 如何在无互联网的条件下安装python的包

3.1 找到依赖包

应该找一台有互联网的机器,把目前安装paramiko(某个包)所需要的依赖给写下来。通过以下语句:

pip2 download paramiko -d /tmp --no-binary :all:

可以得到以下stdout,然后注意系统提示Successfully downloaded paramiko bcrypt cryptography pynacl pyasn1 cffi six idna asn1crypto enum34 ipaddress pycparser,就是我们需要的包。

Collecting paramiko
  File was already downloaded /private/tmp/paramiko-2.4.0.tar.gz
Collecting bcrypt>=3.1.3 (from paramiko)
  File was already downloaded /private/tmp/bcrypt-3.1.4.tar.gz
Collecting six>=1.4.1 (from bcrypt>=3.1.3->paramiko)
  Downloading six-1.11.0.tar.gz
  Saved /private/tmp/six-1.11.0.tar.gz
......
Collecting idna>=2.1 (from cryptography>=1.5->paramiko)
  Downloading idna-2.6.tar.gz (135kB)
    100% |████████████████████████████████| 143kB 172kB/s 
  Saved /private/tmp/idna-2.6.tar.gz
......
Collecting ipaddress (from cryptography>=1.5->paramiko)
  Downloading ipaddress-1.0.18.tar.gz
  Saved /private/tmp/ipaddress-1.0.18.tar.gz
Collecting pycparser (from cffi>=1.1->bcrypt>=3.1.3->paramiko)
  Downloading pycparser-2.18.tar.gz (245kB)
    100% |████████████████████████████████| 256kB 122kB/s 
  Saved /private/tmp/pycparser-2.18.tar.gz
Successfully downloaded paramiko bcrypt cryptography pynacl pyasn1 cffi six idna asn1crypto enum34 ipaddress pycparser

也可以写成一个shell脚本来下载+列出依赖包

link

#!/bin/sh
# get_pypi_dependencies.sh

PACKAGE=$1
pip download $PACKAGE -d /tmp --no-binary :all: \
| grep Collecting \
| cut -d' ' -f2 \
| grep -v $PACKAGE

执行./get_pypi_dependencies.sh bcrypto,得到:

cffi>=1.1
six>=1.4.1
pycparser

3.2 把这些包的wheel文件下载下来

建议在官网上下载。

  1. 平台版本要选对,windows就选择windows的,linux就是linux的。另外32位和64位要选对。
  2. python2还是python3要选对
  3. 版本要满足最小依赖
  4. cpython和jpython的选择。一般都选择cpython,在安装包上会写成cp27, cp34, cp35, cp36
  5. UCS-2和UCS-4的选择。对于linux版本,可以看到有一个是cp27m版本,一个是cp27mu版本,分别代表了UCS-2和UCS-4.
    • 大部分服务器只能够用UCS-2,用UCS-4安装会报错。
    • UCS-2即UTF-16, 这里的2代表2 bytes,一个byte又是8位,所以总共2^16,可以代表65536个字符。
    • UCS-4即4 bytes per character,2^32, 这个比较耗磁盘空间。
    • 有兴趣可以看看这个讨论

将这些包用SFTP、跳板机等方式传递到离线的服务器上。

然后按照3.1中相反的顺序,通过以下方法安装:

pip install [*.whl]

4. 验证安装成功

执行python,并且import对应的包

5. 其他参考链接

Python的几种安装方式

从日志拿数据(grep, awk, sort, uniq)

解决问题:如何从一份规范化打印的日志中,统计到每一个ID的总个数。

如何统计

我用了don’t starve together游戏服务器中大家的聊天数据,统计出谁说的话最多。(最终业务目标:话说得多的可以考虑给管理员权限。)

grep Say server_chat_log.txt|awk {'print $4'}|sort|uniq -c

  1. 首先grep一把,是为了从众多类型(Say, Join Announcement, Quit Announcement)的日志中通过关键字拿到我想要的日志。语句为:
    • grep Say server_chat_log.txt
    • 也可以用less server_chat_log.txt|grep Say更直观,但是对于大文件,效率不如上面的高。
  2. 然后是分析日志格式,用awk把我想要的field打印出来。这里,开发文档中一般都有日志的格式。另外awk一般以空格作为field separator
    • 我要分析的日志: [16:01:00]: [Say] (KU_qqqqqqqq) 爱烟花的小鱼干: 哇 。可以看到,用户的ID在第4格。
    • 根据awk的格式,用awk '{print $4}'打印出来。
  3. 把所有ID先排序,再统计
    • sort: 排序
    • uniq -c: uniq -c是可以count每一个元素出现的次数。
  4. (Optional)最后把统计结果再排序:
    • sort -n -r: 把统计结果用数字进行排序(-n),然后再倒序排序(-r)。

命令详解

sort

-n: 按照数字排序

-r: 倒序排序

uniq

可以从规范化打印的日志中,找到特定位置的元素,并且统计出相应的数目。需要先使用sort,再使用uniq -c来count所有元素。

Note: ‘uniq’ does not detect repeated lines unless they are adjacent. You may want to sort the input first, or use sort -u without uniq. Also, comparisons honor the rules specified by ‘LC_COLLATE’.

翻译成中文:

在发出 uniq 命令之前,请使用 sort 命令使所有重复行相邻。

日志样例

[15:53:44]: [Say] (KU_xxxxxxxx) 子不语: 小妾。。。
[15:53:54]: [Say] (KU_xxxxxxxx) 子不语: 听着怪怪的。。
DST_Stats|9.331545,6.191408,1.257750,6,8[15:54:40]: [Say] (KU_yyyyyyyy) WaiT: 圣诞树长好就能挂彩灯了
[15:55:18]: [Leave Announcement] 二次元
DST_Stats|7.270835,4.619142,1.153396,5,8[15:55:50]: [Join Announcement] 射命丸
DST_Stats|7.367698,5.289487,0.867764,6,8DST_Stats|7.979237,5.063091,1.189214,6,8[15:57:51]: [Say] (KU_hhhhhhhh) WaiT: 感觉这个树长好要好久头疼
DST_Stats|7.539922,5.255657,0.787640,6,8[15:59:03]: [Say] (KU_hhhhhhhh) WaiT: 你们谁身上还有彩灯
DST_Stats|7.302591,5.121131,0.857226,6,8[15:59:58]: [Say] (KU_hhhhhhhh) WaiT: 姐姐没做避雷针怎么说谁弄
[16:00:18]: [Say] (KU_QQQQQQQQ) Lorzen: 等他上线吧  掉了
DST_Stats|7.112324,5.115301,0.681791,7,8[16:00:46]: [Join Announcement] 1282809699
[16:01:00]: [Say] (KU_qqqqqqqq) 爱烟花的小鱼干: 哇
[16:01:17]: [Say] (KU_QQQQQQQQ) Lorzen: 我都守一天 先让给我吧

ubuntu 16.04的boot区满了,如何删除(缩减版)

Short Version

注意:这个只针对于有经验的认识,你必须清楚你在删什么,不然有重装的风险;如果不清楚,请读Long version

  1. 首先看一下磁盘空间中,/boot分区的空间对不对。我用df -h,看到/boot分区已经100%的使用率。
  2. 然后在/boot分区中,直接删文件。但是注意同类的保持两个不删。
  3. 然后再执行apt-get install -f,安装新的kernel包。
  4. 最后执行apt-get autoremove,删除不用的包。
  5. 最终可以看到/boot分区不再是满的了。
'Filesystem      Size  Used Avail Use% Mounted on
udev            362M     0  362M   0% /dev
tmpfs            77M   13M   64M  17% /run
/dev/sda2        11G  3.0G  7.0G  30% /
tmpfs           381M     0  381M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           381M     0  381M   0% /sys/fs/cgroup
/dev/sda1       361M  151M  192M  44% /boot
tmpfs            77M     0   77M   0% /run/user/1000

参考链接

Long Version

背景

  1. 我想apt-get安装一个包,结果系统一直提醒我”Unmet dependencies. Try ‘apt-get -f install’ with no packages”
'You might want to run 'apt-get -f install' to correct these:
The following packages have unmet dependencies:
 linux-image-extra-4.4.0-92-generic : Depends: linux-image-4.4.0-92-generic but it is not going to be installed
 linux-image-generic : Depends: linux-image-4.4.0-92-generic but it is not going to be installed
                       Recommends: thermald but it is not going to be installed
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

Trouble Shooting

  1. 于是我就按照系统提示,运行apt-get -f install,结果系统还是报错,安装不上,提示以下信息。其中重要的是 No apport report written because the error message indicates a disk full error,貌似是磁盘空间满了
Unpacking linux-image-4.4.0-93-generic (4.4.0-93.116) ...
dpkg: error processing archive /var/cache/apt/archives/linux-image-4.4.0-93-generic_4.4.0-93.116_i386.deb (--unpack):
 cannot copy extracted data for './boot/vmlinuz-4.4.0-93-generic' to '/boot/vmlinuz-4.4.0-93-generic.dpkg-new': failed to write (No space left on device)
No apport report written because the error message indicates a disk full error
  1. 接下来df -h,发现果然有一个分区满了,那就是/boot分区,已经100%了。
root@ubuntu:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            362M     0  362M   0% /dev
tmpfs            77M   12M   65M  16% /run
/dev/sda2        11G  5.1G  4.9G  51% /
tmpfs           381M     0  381M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           381M     0  381M   0% /sys/fs/cgroup
/dev/sda1       361M  357M     0 100% /boot
tmpfs            77M     0   77M   0% /run/user/1000
  1. cd /boot之后,再ls可以得到每个文件的大小,得到以下的信息。大概有个印象是要去删除initrd.img,因为它的盘符最大。不确定哪些可以删除,于是参考了这个stackexchange链接

解决方法

接着上面,解决方法是:

  1. 根据apt-get install -f中的no longer required提示The following packages were automatically installed and are no longer required: ,删掉这个列表中对应的/boot分区的文档。
  2. 又因为initrd.img 开头的文档最大(38M),所以删除这个。另外也可以删除对应版本中的vmlinuz, System.map, abi, config等文档。
  3. 其中,至少要保证两个版本的所有类型文档都还保留着,不然等着重装系统吧。
  4. 然后空间够了,就可以重新通过apt-get install -f来安装了。

如何删除文件的英文原文如下原文在这个stackexchange链接

Freeing Up Space on the /boot File System

The Original Poster has a separate /boot partition, and that is what is full and preventing the apt system from working. It will be necessary for him to free up space there.

If there almost enough space, go to /boot and remove a config file or two:

sudo rm config-3.2.0-19-generic-pae

  1. for example, but using the name of one of the kernel versions you intend to remove anyway. This will free up a little space (about 144K apiece).
  2. If you need more space individually remove old vmlinuz initrd, abi and System.map files until you have enough space (about 22 megs for one of my i386 kernel versions).
  3. Whatever you do, don’t remove them all. You should at least keep the latest two matching versions of each kind of file, for each kind of kernel you use.

断后

最后可以做一个apt-get autoremove做cleanup。我竟然删除了1.9G的文件,看来老版本很耗存储空间呢。

如何在VPS中登陆有reCAPTHCA验证的网站

需求场景:

  1. VPS有稳定的速度,经常可以达到10MB/s,一般作为下载站最好不过了。
  2. 使用传统CLI界面登陆的时候,发现一个问题:没有能够进行reCAPTCHA的按钮,所以登录不了。
  3. 我尝试着自己开电脑下载,但那样太痛苦了,经常下载到一半,网络连接断了,而且也不能够通过简单的拷贝link address的方法,因为有些网站为了保护,生成的下载地址是根据登陆信息+浏览器信息+时间戳动态生成的,如果在另外一个地方下载,自动无效。

方法:

  1. 安装VNC,其中最重要的是安装了图形界面xfce4

2. linux上安装midori

  • modori这个浏览器有JavaScript的功能,可以通过人工进行reCAPTCHA验证
  • 这是一个非常轻量级的浏览器
  • midori信息来源网址

然后下载下来的文件,可以通过scp等方式传回自己的电脑。

苹果WWDC 2016 keynote review

apple pay on mac

提纲:

几个OS:

  1. watchOS
  2. TVOS
  3. OS X—>macOS
  4. iOS

Swift: swift playground(在iPad上学习code)

This fall,new few update

首先为Orlando默哀,may this thing will never happen again.


Watch OS 3

watch OS真想吐槽。所以这章写成了一个angry review。

特性(Kevin介绍)

特性1:acceleration in app launch time.

Yeah!我们的手表应用现在终于可以在正常时间内启动了!!

特性2:我们的手表可以swipe from side和bottom哦。

特性3:message可以用smart reply

特性4:scribble:手表上也可以写英文,中文也支持。

特性5:Winnie(米老鼠的伴侣)表盘

特性6:一个大写的数字表盘

特性7:紧急情况下呼叫911.

Demo

  • iOS的底部dock也移到watchOS平台了。
  • 各种新的face:有专门的运动表盘
  • 还专门演示了scribble支持中文(好吧,中国是最大的市场)

新的app:activity app

Activity sharing: 我们终于可以把自己的运动状态炫耀一下了。

这不是在宣传gym bully么?

Audio messages

新的app:breathe

左三圈右三圈,学习深呼吸。

新的upgrade

对crown和touch gesture的支持


tvOS

 

  • sketch party, minecraft.
  • apple tv remote app:可以用remote来玩游戏哦
  • Siri: 可以通过Siri搜内容,launch youtube。
  • SSO:所有的app都能够只用一个密码,安装的方式简单得多。
  • dark mode
  • replay kit
  • photo kit
  • home kit

OS X —>macOS Sierra

个人最喜欢的部分,毕竟macOS是一个生产工具,生产工具的提升可以给生活带来很好的提升。

  • 来吐槽一下OS X的名字情况,哈哈哈. OS X改名为macOS了
  • 最新的系统:MacOS Sierra。 BYE BYE, EL CAPTAIN

功能

macOS应该是功能最多的,finally, finally。

  1. Auto-unlock: 可以用手表解锁mac了。
  2. Universal Clipboard:iPhone上拷贝的东西(text,video)可以直接粘贴到macbook上。
    • iPad上面放的drawing,也可以直接拷贝粘贴到mac。
    • 还可以通过siri来send message。
  3. mac上的desktop可以同步到手机和另一个desktop。不一定要用cloud了。(这个比较好,不过我基本不把内容放桌面)
  4. 帮您删除不需要的文件:Get rid of files you’ll never use again。
  5. Apple Pay。(为什么apple pay要放在mac上?)
    • 哦,原来是把apple pay放在web上。放心,中国有支付宝。
  6. Tabs everywhere: mac上的任何应用中都可以有Tabs哦。
  7. Picture in Picture: mac上也可以放小屏幕了(只是safari功能,chrome党默哀)。
  8. Siri on mac (Hi, Siri. can you tell me how to beat Alfred?)
    • (Hi, siri. Show me the file I’ve worked last week)
    • 搜索的结果可以pin在notification center。
    • 可以让Siri来快速找音乐放音乐。

 


iOS 10

1. lock screen & home screen experience

  1. raise to wake: iOS也可以像手表一样,举起来就看见了。
  2. 不解锁也可以通过3d-touch回复message了,还可以看到uber的信息。
  3. Control center有一个专门的music center
  4. widget
  5. Email的3d message能力:可以看到谁的邮件一直没回。

2. Siri

  1. Opening up Siri to Developers finally
  2. 可以让siri给wechat发信息,并且第三方可以基于siri的信息开发API。Send a wechat to xxx about 某某事件
  3. VoIP calling.
  4. car play. Safely

3. QuickType

  1. 可以更快extract info。
  2. 支持multilingual typing

4. Photos

Bow to the new AI.

  1. Advanced computer vision: facial recognition on iPhone. 把google的能力搬过来了。(all done locally on device)
  2. Object & scene recognition: 可以自动组成一个相关的相册,draws out the specific photo.
    • people
    • map
    • related
  3. Memory: iPhone根据你拍照,录像信息,自动帮你整理一个相册。(这么屌)
    • 可以选择时长
    • 可以选择不同心情,根据选择的心情选择音乐。

5. Maps

完全没有亮点好不好。Google map用户飘过

  1. seafood searching?
  2. traffic on route google也有啊
  3. 可以将turn的信息写到
  4. Opening maps to developers。
    • 大众点评!大众点评!不是ding-yan-ping
    • 可以开放给滴滴

6. Music

All-new design。然后是一堆blah, blah, blah

Demo:

  • 终于有一个Downloaded music了。
  • Recently Added。
  • Lyrics!! Finally. 其他第三方应用N年前就做了的!!
  • For you
  • Radio

7. News

好像是有new design,没听懂有什么特点。。。

8. Homekit

可以控制camera, doorlocks 顿时想到了小米智能家庭

home app

  1. 定义scene:
  • Good night:关窗帘,关灯,关电视
  • Good morning:开窗帘,开灯
  1. 可以通过iPhone看门口摄像头,开门
  2. Remote access。

9. Phone

  • Voicemail transcript
  • 骚扰电话拦截(specially in China)
  • VoIP可以有来电人信息,包括图片(赶快在Espace里面加,没有图片有个ID也好)

10. Message

总结一下,Message应该是放了很多HTML 5的东西。

  • message有rich link了,Yay,我可以再也不用wechat和whatsapp了。Just kidding
  • 3x bigger emoji
  • 可以把message中的可以改成emoji的词全部改成emoji。
  • 做了滑动解锁消息功能。
  • 对第三方开放。可以发送表情。。。
  • 表情可以放在别人发的图片上。

11.其他

Note collaboration.

Split view on safari on iPad.

12. Privacy

Some privacy bullshit which nobody really cares about as long as you hit “Agree”.

最后,上video介绍iOS 10.

Swift Playground

以后的小学生如何学习coding?play!!

理念还是很先进

  • Playground是免费的

Supervisord不能够启动进程的问题

今天在启动某应用的时候,发现supervisord会报错「spawn error」,开始以为是进程问题,后面直接通过python启动时发现没有问题,所以锁定应该是supervisord的问题,经过查supervisord的配置文件/etc/supervisord.conf,查到配置文件地址在/tmp,所以去/tmp看日志

看报错

root@localhost:/tmp# more ss-manyuser-stderr---supervisor-BLAHBLAH.log 
supervisor: couldn't setuid to 0: Can't drop privilege as nonroot user
supervisor: child process was not spawned
supervisor: couldn't setuid to 0: Can't drop privilege as nonroot user
supervisor: child process was not spawned
supervisor: couldn't setuid to 0: Can't drop privilege as nonroot user
supervisor: child process was not spawned
supervisor: couldn't setuid to 0: Can't drop privilege as nonroot user
supervisor: child process was not spawned

分析

可能是没有权限,查阅google,得到同样的答案。

所以,将配置文件的user改为root

[supervisord] user=root

善后

注意在启动supervisord的时候,需要加上-c /etc/supervisord.conf指定配置文件地址。同样的,如果需要开机启动,/etc/rc.local中也需要加上。

Microservice Structure

 如何解决大流水线不好改造的问题

The Abstract & The source

花了两个小时读完microservice,觉得这个设计思路跟罗辑思维罗胖讲的『U盘人』有类似之处,都是自带信息,随时插拔,自由协作,当然还要容错性高。

这个是原文链接,做软件设计的值得多看看,开阔开阔思路:

http://martinfowler.com/articles/microservices.html

The Good:

With a monolith any changes require a full build and deployment of the entire application. With microservices, however, you only need to redeploy the service(s) you modified.

The Bad:

The downside is that you have to worry about changes to one service breaking its consumers. The traditional integration approach is to try to deal with this problem using versioning, but the preference in the microservice world is to only use versioning as a last resort. We can avoid a lot of versioning by designing services to be as tolerant as possible to changes in their suppliers.

The Specification:

Organize around business capabilities

Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.

— Melvyn Conway, 1967

对比:

Monolithic的团队注重组织分工,各司其职:

Microservice的团队更加注重business capability:

The Example:

The Microservice is the Evolutionary Design, or not?

The Guardian website is a good example of an application that was designed and built as a monolith, but has been evolving in a microservice direction. The monolith still is the core of the website, but they prefer to add new features by building microservices that use the monolith’s API.

在网页中加上第三方搜索(django框架,bing搜索)

搜索,是一个网站基本的能力。在这个例子中,我们添加了搜索功能,其原理是:

  • 注册Bing Search API
  • 调用Bing Search API,得到结果的JSON
  • 将数据存入一个result列表中
  • 展示result

此教程来自http://www.tangowithdjango.com/book17/chapters/bing_search.html,我将他的意思再总结了一下。下面,我们就来分别看这几步:

1. 注册Bing search API

1.1 注册marketplace

首先需要注册一个Microsoft Azure Marketplace的账号。可以通过Hotmail账号注册 (注意语言需要使用英文。用中文的话,微软是不会提供API的)。

1.2 Sign Up应用

然后是在这个应用商店中找到应用,如链接:https://datamarket.azure.com/dataset/bing/search。微软的搜索引擎按照transaction per month来算的,我们就注册一个5000TPS的即可。

注册完成之后,还需要找到API key,最好是新建一个API key,这个key会在后面调用的时候使用。

2. 调用Bing Search API

后面的这几部都是代码实现的。

2.1 根据API文档配置参数

目前我们先创建一个bing_search.py的文件。然后需要参考微软的API文档,看看这个是怎么调用的。

https://datamarket.azure.com/dataset/bing/search#schema可以找到service_root_url,然后这个作为一个root。

然后查阅《Bing Search API Quick Start and Code Samples》文件,上面有列举the examples of your final URI to the Bing Search API:

https://api.datamarket.azure.com/Bing/Search/Web?$format=json&Query=%27Xbox%27

根据这个,我们定义了几个参数,传入到search_url中:

	search_url = "{0}{1}?$format=json&$top={2}&$skip={3}&Query={4}".format(
        root_url,
        source,
        results_per_page,
        offset,
        query
    )

2.2 通过password_manager来管理密码:

	password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    password_mgr.add_password(None, search_url, username, BING_API_KEY)

3. 将数据存入result列表中

3.1 urllib.request.urlopen()的解码处理

这里我们使用的url open得到的response,而url open返回的是一个binary的文件,son又zhi只接受utf-8格式的,所以这里需要将接收到的文件decode为utf-8格式.然后再在json.loads。

	# Convert the bytes to a str. Because "The JSON object must be str, not 'bytes'"
        str_response = response.decode('utf-8')

        # Convert the string response to a Python dictionary object.
        json_response = json.loads(str_response)

3.2 如何将json对应到python列表中

下面第一句的数组是对JSON的标准处理。关于json的知识,可以参考这篇文章link。简单来说,JSON就是一个标准化的数组格式

	for result in json_response['d']['results']:
            results.append({
                'title': result['Title'],
                'link': result['Url'],
                'summary': result['Description']
            })

如果在PHP中,也是通过类似的方法:

foreach($jsonObj->d->results as $value)

3.3 通过命令行的形式验证

在实施网页版本之前,首先通过命令行的形式保证这个API可以Working。

具体请见代码

4. 展示result

需要在Template中添加相应的search.html

需要在views中添加search(request)的view。

需要在urls.py中添加url

最后在base上添加链接。

5. 代码

import json
import urllib.request
import urllib.parse
from rango.keys import BING_API_KEY



def run_query(search_terms):
    # Specify the base
    root_url = 'https://api.datamarket.azure.com/Bing/Search/v1/'
    source = 'Web'

    # Specify how many results we wish to return per page
    results_per_page = 10
    offset = 0

    # Warp quotes around our query terms as required by the Bing API
    query = "'{0}'".format(search_terms)
    query = urllib.request.quote(query)

    # Constructs the latter part of our request's URL
    search_url = "{0}{1}?$format=json&$top={2}&$skip={3}&Query={4}".format(
        root_url,
        source,
        results_per_page,
        offset,
        query
    )

    # Setup authentication with the Bing servers.
    # The username MUST be a blank string, and put in your API key!
    username = ''

    # Create a 'password manager' which handles authentication for us.
    password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    password_mgr.add_password(None, search_url, username, BING_API_KEY)

    # Create our results list which we'll populate
    results = []

    try:
        # Prepare for connecting to Bing's servers.
        handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
        opener = urllib.request.build_opener(handler)
        urllib.request.install_opener(opener)

        # Connect to the server and read the response generated.
        response = urllib.request.urlopen(search_url).read()

        # Convert the bytes to a str. Because "The JSON object must be str, not 'bytes'"
        str_response = response.decode('utf-8')

        # Convert the string response to a Python dictionary object.
        json_response = json.loads(str_response)

        # Loop through each page returned, populating out results list.
        for result in json_response['d']['results']:
            results.append({
                'title': result['Title'],
                'link': result['Url'],
                'summary': result['Description']
            })
    except urllib.request.URLError as e:
        # Catch a URLError exception - something went wrong when connecting
        print("Error when querying the Bing API: "+e)

    return results

def main():
    search_terms = input("Input the word you want to search>> ")
    results = run_query(search_terms)
    print("Rank"+' '+'Title'+50*' '+'URL')
    rank = 0
    for result in results:
        rank += 1
        print(str(rank).ljust(5), end=' ')
        print(result['title'].ljust(50), end=' ')
        print(result['link'])

if __name__ == '__main__':
    main()

Python中不能安装python-docx的问题

python-docx是咱们常用的一个python中处理word文档的库,相对于VB来说,更容易学,也比较适合通过python作为胶水,将其他内容放在word中。然而很多时候安装python-docx会报错,如何解决呢?

0. 前提

必须使用的是windows系统,python-docx在mac os上是不能够工作的。

另外python-docx使用了lxml,而lxml的更新又不是那么快,所以导致了问题。

在命令行中,使用pip install python-docx安装

1. 问题提示

一般来说,大家看到的提示有这么几个:

  1. 提示vcvarsall.bat不存在。
  2. 提示 fatal error C1083: Cannot open include file: ‘libxml/xpath.h’: No such file or directory

2. 问题解决方案

对于上面两个问题,由以下方法解决:

  1. vcvarsall.bat不存在,是因为没有安装visual studio。可以到微软官网下载一个visual studio express并且安装。
  2. 再提示的libxml/xpath.h的错误,通常是因为lxml的安装有问题导致的。所以这里建议分两步安装,先安装lxml的非官方的包:lxml补丁包链接,然后再通过pip install python-docx即可。
    • 注意补丁包的选择,需要选择跟你的python版本对应的版本,例如如果你使用的是32位的python35,就需要选择lxml-3.5.0-cp35-none-win32.whl这个版本
    • whl包的安装:用命令行工具cd到whl目录,再pip install即可