Table of Contents generated with DocToc

用Python实现从命令行进行淘宝搜索

背景

作为马云门前的败家娘们/爷们,在淘宝上搜东西是常做的事。

对于搜索,我们一般的流程是:

  • 打开浏览器
  • 打开淘宝
  • 输入搜索关键词

如果能用python写个脚本简化这个流程,那想必是极好的。

最后想达到的结果是,在命令行输入

python search_taobao.py 关键词1 关键词2 ...

就能直接打开淘宝搜索网页,并搜索关键词

构思

要达到上述效果,我想到的逻辑步骤是:

  1. 读取命令行的参数
  2. 打开浏览器,打开淘宝页面
  3. 搜索关键词

经过google大法之后,了解到
对于步骤1,标准库sysargv变量可以储存python命令后的参数(包括第一个参数,文件名search_taobao.py)

对于步骤2,标准库webbrowseropen方法可以打开指定网页,例如

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成功打开了

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

那么问题可能不是chrome vs. safari,而是默认浏览器 vs. 指定浏览器。

之后花了很长时间去啃webbrowser.py的源代码,虽然只能看懂一点点,但关键的信息get到了

webbrowser源码 上图是源码的一个片段,主要看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)

即要将一个元素加进一个链表时,通过一些条件,选择将元素添加到链表的尾部或头部,这样在之后遍历这个链表时,元素会被最晚或最早使用。

results matching ""

    No results matching ""