使用Python与其他程序进行交互

29
我想用Python编写一个程序,可以根据我提供的歌曲名字查找歌词。整个过程应该归结为以下几点。当我运行程序时,希望程序能够执行以下操作:
  • 提示我输入一首歌曲的名称
  • 复制这个名称
  • 打开一个网页浏览器(例如Google Chrome)
  • 将这个名称粘贴到地址栏中,并查找有关这首歌的信息
  • 打开包含歌词的页面
  • 复制歌词
  • 运行一个文本编辑器(例如Microsoft Word)
  • 粘贴歌词
  • 使用歌曲名称保存新的文本文件

当然,我并不要求代码。我只想知道如何使用Python与其他程序进行交互的概念或思路。

更具体地说,我想知道我们如何指出Google Chrome浏览器中的地址栏位置,并告诉python在那里粘贴名称。又或者,我们如何告诉Python如何复制歌词以及将其粘贴到Microsoft Word的工作表中,然后保存它。

我已经阅读了(我还在阅读)几本关于Python的书籍:《Byte of python》、《Learn python the hard way》、《Python for dummies》、《Beginning Game Development with Python and Pygame》。然而,我发现似乎我只学到了如何创建在自身上运行的程序(我无法告诉我的程序执行我想要的与其他已安装在计算机上的程序交互的事情)

我知道我的问题听起来有些傻,但我真的想知道它是如何工作的,我们如何告诉Python识别Google Chrome浏览器的这一部分是地址栏,并且应该将歌曲名粘贴在其中。让Python与另一个程序进行交互的整个想法对我来说非常模糊,我非常想抓住它。

谢谢大家,谁花时间阅读我这么长的问题。

ttriet204


5
请看 http://code.google.com/p/pywinauto/。我已经用它完成了一些不错的自动化。 - g.d.d.c
18
当你应该从“程序员的角度”去思考问题时,你却从“用户的角度”来思考;你不需要打开浏览器、复制文本、打开Word或其他软件,而是需要在Python脚本内执行适当的HTTP请求,解析相关的HTML,提取文本并写入文件。所有这些工具都可以在Python中找到(特别是你会需要用到的urllib2BeautifulSoup模块)。 - Matteo Italia
2
@CameronSparr:当然,但那是一个非常专业化的需求 - 他们需要模拟用户交互; 相反,这里用户需要完成一些工作,他天真地认为要复制人类所做的事情,而实际上有更直接的方式可以从代码中直接实现。 - Matteo Italia
1
可以使用提供 API 的服务,使得操作更加简单,无需进行解析和提取。 - Esailija
4
这个问题的重点是“我需要编写一个能够实现这个功能的程序”,还是“我想利用这个问题作为学习如何与其他应用程序交互的借口”? - abarnert
显示剩余4条评论
5个回答

46
如果你真正想学习如何与其他应用程序交互,那么这可能不是最好的选择。网络浏览器很混乱,时间安排将是不可预测的等等。因此,你承担了一项非常艰巨的任务,如果你按照通常的方式(直接与服务器通信、直接创建文本文件等),而不接触任何其他程序,这将非常容易。
但是,如果你确实想要与其他应用程序交互,有许多不同的方法可供选择,适当的方法取决于你需要处理哪些应用程序。
  • 有些应用程序是设计成可以从外部自动化的。在Windows上,这几乎总是意味着它们有一个COM接口,通常带有一个IDispatch接口,您可以使用pywin32的COM包装器; 在Mac上,则意味着它有一个AppleEvent接口,您可以使用ScriptingBridgeappscript; 在其他平台上,没有通用标准。IE(但可能不包括Chrome)和Word都有这样的接口。

  • 有些应用程序有非GUI界面-无论是您可以使用popen驱动的命令行,还是您可以通过ctypes加载的DLL / SO / DYLIB。或者,理想情况下,其他人已经为您编写了Python绑定。

  • 有些应用程序除了GUI之外什么都没有,没有绕过GUI自动化的方法。您可以在低级别上进行操作,通过在Windows上使用pywin32发送WM_消息,使用Mac上的可访问性API等方式,或者使用像pywinauto这样的库在稍高级别上进行操作,或者可能在非常高的级别上使用selenium或类似工具来自动化特定的应用程序。

因此,您可以使用任何工具来实现此目的,例如selenium用于Chrome和COM自动化用于Word,也可以手动编写所有WM_消息。如果这是学习练习,则需要考虑今天想要学习哪些内容。


让我们从COM自动化开始。使用pywin32,您可以直接访问应用程序的脚本接口,而无需控制用户界面,弄清如何导航菜单和对话框等。这是编写“Word宏”的现代版本——宏可以是外部脚本,而不是在Word内部编写,它们不必使用VB编写,但它们看起来非常相似。您的脚本的最后一部分将类似于:

word = win32com.client.dispatch('Word.Application')
word.Visible = True
doc = word.Documents.Add()
doc.Selection.TypeText(my_string)
doc.SaveAs(r'C:\TestFiles\TestDoc.doc')

如果你看Microsoft Word Scripts,你会看到很多例子。然而,你可能会注意到它们是用VBScript编写的。如果你寻找教程,它们都是为VBScript(或旧版VB)编写的。大多数应用程序的文档也是为VBScript(或VB、.NET甚至低级别的COM)编写的。我所知道的所有关于使用Python进行COM自动化的教程,例如Quick Start to Client Side COM and Python,都是为那些已经了解COM自动化并想知道如何在Python中实现它的人编写的。微软不断更改一切的事实使得搜索变得更加困难——你怎么猜测搜索OLE自动化、ActiveX脚本、Windows Scripting House等是否与学习COM自动化有关呢?因此,我不确定该推荐什么来入门。我可以保证,一旦你学会了所有的废话,这一切看起来都像上面的例子一样简单,但我不知道如何克服最初的障碍。
无论如何,并不是每个应用程序都可以自动化。有时,即使可以自动化,描述 GUI 操作(用户在屏幕上单击的内容)比思考应用程序的对象模型更简单。"选择第三段" 在 GUI 方面很难描述,但 "选择整个文档" 很容易 - 只需按下 control-A 或转到编辑菜单并选择全部。GUI 自动化比 COM 自动化要困难得多,因为您必须向应用程序发送与 Windows 本身发送以表示您的用户操作相同的消息(例如,请参见 "Menu Notifications"),或者更糟糕的是,制作鼠标消息,如“从左上角移动 (32, 4) 像素,单击,向下移动 16 像素,再次单击”来表示“打开文件菜单,然后单击新建”。

幸运的是,有像pywinauto这样的工具将两种类型的GUI自动化封装起来,使其变得更加简单。而像swapy这样的工具可以帮助您确定要发送的命令。如果您不喜欢Python,还有像AutoItActions这样的工具,它们比使用swapypywinauto更容易上手。按照这种方式,您脚本的最后一部分可能会像这样:

word.Activate()
word.MenuSelect('File->New')
word.KeyStrokes(my_string)
word.MenuSelect('File->Save As')
word.Dialogs[-1].FindTextField('Filename').Select()
word.KeyStrokes(r'C:\TestFiles\TestDoc.doc')
word.Dialogs[-1].FindButton('OK').Click()

最后,即使有了所有这些工具,网页浏览器也很难自动化,因为每个网页都有自己的菜单、按钮等,它们不是 Windows 控件,而是 HTML。除非你想一直降到“移动鼠标 12 像素”的级别,否则很难处理这些问题。这就是 selenium 的作用——它以与 pywinauto 处理 Windows GUI 相同的方式脚本化 Web GUI。

嗨Abarnert!非常感谢你。虽然由于我的知识不足,我并不理解你向我解释的大部分内容,但现在我认为我已经掌握了如何让Python与其他程序配合工作的基本思路。我目前正在深入研究你提到的一些术语,比如“GUI”、“DLL/SO/DYLIB”、“Python绑定”、“COM”。我已经在Google和维基百科上尝试过了,但是提供的解释对我来说似乎有点“学术性”。如果可以的话,请给我提供一些关于这些项目的阅读材料。谢谢。 - ttriet204
我会编辑答案并添加更多信息。另外,现在我知道你在使用Windows,我可以更具体地说明。 - abarnert
再次感谢你,Abarnert!你一直陪伴着我!我非常感激你所做的和试图为我分解这个非常模糊的想法成简单的“块”!我从你的回答中学到了很多。你让这个网站成为一个对像我这样的新手非常有用和友好的地方。 - ttriet204

15
以下脚本使用Automa实现你想要的功能(在Word 2010上测试通过):
def find_lyrics():
    print 'Please minimize all other open windows, then enter the song:'
    song = raw_input()
    start("Google Chrome")
    # Disable Google's autocompletion and set the language to English:
    google_address = 'google.com/webhp?complete=0&hl=en'
    write(google_address, into="Address")
    press(ENTER)
    write(song + ' lyrics filetype:txt')
    click("I'm Feeling Lucky")
    press(CTRL + 'a', CTRL + 'c')
    press(ALT + F4)
    start("Microsoft Word")
    press(CTRL + 'v')
    press(CTRL + 's')
    click("Desktop")
    write(song + ' lyrics', into="File name")
    click("Save")
    press(ALT + F4)
    print("\nThe lyrics have been saved in file '%s lyrics' "
          "on your desktop." % song)

要亲自尝试一下,请从下载页面下载Automa.zip并解压到比如说c:\Program Files。你会得到一个名为Automa 1.1.2的文件夹。在该文件夹中运行Automa.exe。将上面的代码复制并通过右键单击控制台窗口粘贴到Automa中。按两次回车键以去除窗口中的最后一个...,回到提示符>>>处。关闭所有其他打开的窗口,然后输入

>>> find_lyrics()

这执行所需的步骤。

Automa是一个Python库:要将其用作此类库,您必须添加该行

from automa.api import *
将您的脚本中的顶部以及来自Automa安装目录的文件library.zip添加到您的环境变量PYTHONPATH中。
如果您有任何其他问题,请告诉我 :-)

嗨,Michael Herrmann。非常感谢。我从未想过有人会花时间为我编写整个代码(我将使用您的代码作为参考来学习,因为我真的很想把我所学到的东西应用到实践中:D)。我相信您的代码将成为我优秀的示例和指南。我现在正在下载 automa,迫不及待地想尝试一下您的工作!非常感谢。我相信我以后还会有更多问题要问。 - ttriet204
首先,这将复制并粘贴所有歌词结果的文本到一个Word文件中,而不仅仅是歌词。这几乎肯定不是你想要的。许多歌词网站都设计成不允许你复制粘贴歌词;即使你很幸运,你也会得到一堆导航、链接等等围绕着歌词的混乱信息。(此外,这将在完成后退出两个应用程序,这可能也不是你想要的,但这更容易修复。) - abarnert
其次,关于这个SO问题的博客文章http://www.getautoma.com/blog/find-song-lyrics-with-automa是非常误导人的。"……其他答案包括……一般的口气'太难了'"?真的吗,展示5行win32com代码在Word中创建一个新文件太难了,但展示7行Automa代码做同样的事情就不难了吗?困难的部分是提取歌词文本——这个答案只是通过没有实际解决它来推迟了这个问题。 - abarnert
关于“试用”@ttriet204:我和同事们商量过了 - 我们认为你想学习新东西很酷,如果你愿意的话,我们很乐意给你提供免费许可证 :-) - Michael Herrmann
哦,实际上,Abarnert对我的回答很有帮助。我写道“虽然我不太理解你说的大部分内容”,这是因为我的编程和计算机理解非常有限,而不是因为他的回答。还有一件事,他确实回答了我的问题,即Python如何与其他程序交互的“概念”。 - ttriet204
显示剩余6条评论

12

以下是Python的实现,基于@Matteo Italia的评论:

你从“用户角度”来解决问题,而应该从“程序员角度”来解决问题。你不需要打开浏览器,复制文本,打开Word或其他东西,你需要在Python脚本内部执行适当的HTTP请求,解析相关的HTML,提取文本并将其写入文件。所有这些工具都可以在Python中使用(特别是您将需要urllib2和BeautifulSoup)。

#!/usr/bin/env python
import codecs
import json
import sys
import urllib
import urllib2

import bs4  # pip install beautifulsoup4

def extract_lyrics(page):
    """Extract lyrics text from given lyrics.wikia.com html page."""
    soup = bs4.BeautifulSoup(page)
    result = []
    for tag in soup.find('div', 'lyricbox'):
        if isinstance(tag, bs4.NavigableString):
            if not isinstance(tag, bs4.element.Comment):
                result.append(tag)
        elif tag.name == 'br':
            result.append('\n')
    return "".join(result)

# get artist, song to search
artist = raw_input("Enter artist:")
song = raw_input("Enter song:")

# make request
query = urllib.urlencode(dict(artist=artist, song=song, fmt="realjson"))
response = urllib2.urlopen("http://lyrics.wikia.com/api.php?" + query)
data = json.load(response)

if data['lyrics'] != 'Not found':
    # print short lyrics
    print(data['lyrics'])
    # get full lyrics
    lyrics = extract_lyrics(urllib2.urlopen(data['url']))
    # save to file
    filename = "[%s] [%s] lyrics.txt" % (data['artist'], data['song'])
    with codecs.open(filename, 'w', encoding='utf-8') as output_file:
        output_file.write(lyrics)
    print("written '%s'" % filename)
else:
    sys.exit('not found')

例子

$ printf "Queen\nWe are the Champions" | python get-lyrics.py 

输出

我已经付出了应得的代价
一次又一次地
我完成了我的惩罚
但没有犯罪
我犯过错误 我做过几个坏决定 我承受了我的沙被踢的份额[...] 写入 '[Queen] [We are the Champions] 歌词.txt'

@J.F. Sebastian,我知道这篇帖子/答案已经很老了,但是我测试了你的代码,它失败了。看起来http://lyrics.wikia.com/api.php上的API格式已经改变了。你能指点我正确的方向或链接,让它再次工作吗?我查看并搜索了那个API网站,有内容/维基API,但没有找到歌词API。 - Michael SM
@MichaelSM:具体的API并不是答案的重点。重点在于Matteo Italia的评论中表达的内容,而代码只是用作简单的说明(以揭示所需的努力)。尽管在发布时代码确实有效。如果lyrics.wikia.com的API被停用,则可以尝试其他类似的服务。 - jfs
@J.F. Sebastian:感谢您的回复。我特别感兴趣的是歌词API。您能推荐一个好的歌词API吗? - Michael SM

5
如果你真的想打开浏览器等,可以看一下selenium。但对于你的目的来说这有点过度了。Selenium是用于模拟按钮点击等测试网站在各种浏览器上的外观的。Mechanize对此不那么过度。
你真正想做的是理解浏览器(或其他任何程序)在幕后的工作方式,即当你单击鼠标或键入键盘或按下保存时,程序在幕后执行了什么操作?你希望你的Python代码执行这些幕后工作。

因此,使用 urlliburllib2requests(或者甚至是 scrapy)请求网页(学习如何组合一个Google搜索的URL或歌词网站的PHP GET请求)。Google还有一个搜索API,你可以利用它来进行Google搜索。

一旦您从页面请求中获得了结果,请使用 xmlbeautifulsouplxlml 等进行解析,并找到包含您所需信息的请求结果部分。

现在,您已经有了歌词,最简单的方法是打开一个文本文件,将歌词倒入其中并写入磁盘。但如果您真的想使用 MS Word,那么请在记事本或 notepad++ 中打开 doc 文件并查看其结构。现在,使用 Python 构建具有类似结构的文档,其中内容将是下载的歌词。
如果此方法失败,您可以查看 pywinauto 或类似工具,以自动将文本粘贴到 MS Word 文档中并单击 保存
引用:Matteo Italia,来自 OP 的 g.d.d.c 评论

文档是二进制格式,用记事本打开没有任何意义。 - Esailija
@Esailija:我的意思是输出可以存储为.txt文件而不是.doc文件。 - inspectorG4dget
嗨InspectorG4dget!非常感谢你的回答。它真的帮了我很多!我已经尝试下载pywinauto并且玩得很开心。最初我选择了你的第一个建议,也就是Selenium。然而,我无法通过你提供的链接下载文件,可能是我的电脑或者我的网络连接出了问题。我一直在尝试下载文件,但是始终无法成功。后来我在互联网上寻找,但是我就是找不到那个链接(或者一个有效的链接!)。如果可以的话,请给我另一个Selenium的链接。非常感谢你的帮助。 - ttriet204
http://seleniumhq.org 是Selenium的主页。那里的说明应该解释如何获取您所需的各种Selenium WebDriver组件(以及哪些是这些组件)。 - abarnert

1
你应该了解一下名为 selenium 的软件包,它可以用于与网络浏览器进行交互。

谢谢!我仍在寻找Selenium下载链接。你能给我提供一下吗? - ttriet204

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接