Table of Contents generated with DocToc
用Python实现从命令行进行淘宝搜索
背景
作为马云门前的败家娘们/爷们,在淘宝上搜东西是常做的事。
对于搜索,我们一般的流程是:
- 打开浏览器
- 打开淘宝
- 输入搜索关键词
如果能用python写个脚本简化这个流程,那想必是极好的。
最后想达到的结果是,在命令行输入
python search_taobao.py 关键词1 关键词2 ...
就能直接打开淘宝搜索网页,并搜索关键词
构思
要达到上述效果,我想到的逻辑步骤是:
- 读取命令行的参数
- 打开浏览器,打开淘宝页面
- 搜索关键词
经过google大法之后,了解到
对于步骤1,标准库sys
中
argv
变量可以储存python命令后的参数(包括第一个参数,文件名search_taobao.py)
对于步骤2,标准库webbrowser
中open
方法可以打开指定网页,例如
import webbrowser
webbrowser.open('www.taobao.com')
对于步骤3,可以使用Query String在打开网址时就把关键词post上去。
对于淘宝,相应的做法是输入https://s.taobao.com/search?q={keywords}
,将{keywords}替换成想输入的关键词就行。
实现
综上所思,初步写的解决方案如下
# file name "search_taobao.py"
import sys
import webbrowser
keywords = sys.argv[1:]
url = "https://s.taobao.com/search?q="
for i in keywords:
url += i + "+"
url = url[:-1] #remove the last '+''
webbrowser.open(url)
命令行输入
python search_taobao.py python
成功打开淘宝搜索
尝试输入多个关键词
python search_taobao.py python Django
也搜索成功
问题
虽然使用英文关键词时搜索成功,但在使用中文关键词时出现了bug
例如,搜索关键词书
python search_taobao.py 书
在打开的淘宝页面,搜索的关键词却变成了%C2%A0È
debug
首先这肯定是中文编码的问题,因此尝试在文件开头加一句
# coding=utf-8
测试之后问题依然存在
然后猜测是sys.argv读取中文参数时出现问题
在脚本中加入print语句
# coding=utf-8
import sys
import webbrowser
keywords = sys.argv[1:]
url = "https://s.taobao.com/search?q="
for i in keywords:
print i # Debug
url += i + "+"
url = url[:-1] #remove the last '+''
# webbrowser.open(url)
发现output中的中文显示正常
然后猜测是英文字符串和中文字符串concatenate过程中出现问题
改脚本为
# coding=utf-8
import sys
import webbrowser
keywords = sys.argv[1:]
url = "https://s.taobao.com/search?q="
for i in keywords:
url += i + "+"
print url # Debug
url = url[:-1] #remove the last '+''
# webbrowser.open(url)
测试发现output中文显示正常
最后猜测是webbrowser.open
函数在使用参数含中文时会有bug
直接运行如下脚本
import webbrowser
webbrowser.open("https://s.taobao.com/search?q=书")
结果证实了我的猜测,问题出在webbrowser.open
上
改进
为了解决这个bug,几轮google之后还是没找到解决webbrowser.open
对中文不支持的问题。但在这个过程中,找到了subprocess
库,这个库中call
函数可以让python直接运行命令行命令,另外还查到了命令行的open命令可以直接在浏览器中打开网页。遂把代码改写如下
# coding=utf-8
import sys
import subprocess
keywords = sys.argv[1:]
url = "https://s.taobao.com/search?q="
for i in keywords:
url += i + "+"
url = url[:-1]
subprocess.call(["open", url])
之后测试中文关键词、多关键词都运行成功,算是实现了设想的功能。
ps: Mac下面,可以在命令行多加一句say
的命令,用于命令执行完进行提示。例如
python search_taobao.py 书;say mission complete
执行之后,系统会说mission complete,瞬间成就感爆表。
pps: 后来发现用os.system()调用命令行命令也行 代码可改为
# coding:utf-8
import os
import sys
keywords = sys.argv[1:]
url = "https://s.taobao.com/search?q="
for i in keywords:
url += i + "+"
url = url[:-1]
os.system("open "+url)
update
Sun Oct 18 03:27:54 2015
@LeiyuZhang同学提示我说,win系统下,用webbrowser.open能正确打开带中文字符的网址,这促使我重新去思考我之前的推断是否正确。
接着我就不停地折腾,想试着看看是否在Mac下也能打开webbrowser.open打开带中文字符的网址,或者说是否能检测到这个问题出现的边界条件。
我最初是折腾了unicode、utf-8、gbk等编码,也去看了官方文档,还是没有什么进展。
之后测试是否是浏览器的原因,我机子的默认浏览器是chrome
运行代码
# coding=utf-8
import webbrowser
webbroser.open("http://www.google.com?q=中文搜索")
运行结果如下图所示
接着改用safari
# coding=utf-8
import webbrowser
web = webbrowser.get('safari')
web.open("http://www.google.com?q=中文搜索")
运行之后居然在safari成功打开了
然后我就在思考,问题是不是出在chrome上。 虽然webbroser.get()本身可供选择的参数不包括chrome,但我在网上搜到了一个主动选择在chrome上打开的方法
运行如下命令
# coding=utf-8
import webbrowser
web = webbrowser.get("open -a /Applications/Google\ Chrome.app %s")
web.open("http://www.google.com?q=中文搜索")
发现也能在chrome上正常打开
那么问题可能不是chrome vs. safari,而是默认浏览器 vs. 指定浏览器。
之后花了很长时间去啃webbrowser.py的源代码,虽然只能看懂一点点,但关键的信息get到了
上图是源码的一个片段,主要看open()函数下if else语句,发现python里的webbrowser库在mac下其实是调用AppleScript命令
- 使用默认浏览器时,执行命令为
open location 网址
- 使用其他浏览器时,执行命令为
tell application 浏览器
activate
open location 网址
end
然后开始测试AppleScript,在mac的脚本编辑器里运行
tell application "Google Chrome"
activate
open location "http://www.google.com?q=中文搜索"
end
打开的网址中文显示正确
再运行
open location "http://www.google.com?q=中文搜索"
没有任何反应
网上搜到了一条命令,试着在命令行运行
echo 'open location "http://www.google.com?q=中文搜索"' | osascript
发现随之在chrome上打开的网址中文显示错误,跟之前用webbrowser.open从默认浏览器打开的结果一样!
之后再将safari设置成默认浏览器测试上面那条命令,发现打开的网址还是一样的错误网址。
那么,总算是知道问题出在哪了
初步结论:mac下直接运行open location {带中文字符的网址}
这样的AppleScript会打开错误的网址
现在回过头看,不应该在unicode等编码上花那么多时间去测试,因为
webbrowser.open("http://www.google.com?q=中文搜索")
打开了错误的网址print "http://www.google.com?q=中文搜索"
能显示正确的网址
这就说明问题很大可能出现在webbrowser内部机制,而不在编码上。
ps:源代码确实难啃,但看了之后确实收获很大。 这次印象比较深的是这样一个语句
my_list = []
if condition_a:
my_list.append(some_element)
elif condition_b:
my_list.insert(0, some_elemen)
即要将一个元素加进一个链表时,通过一些条件,选择将元素添加到链表的尾部或头部,这样在之后遍历这个链表时,元素会被最晚或最早使用。