使用Python/Selenium/最佳工具获取JavaScript生成的图像请求URI?
我有一些来自第三方供应商的JavaScript代码,它会发起一个图片请求。我想弄清楚这个图片请求的URI(网址)。
我可以在浏览器中加载这个页面,然后通过监控“实时HTTP头”或者“Tamper Data”来找出这个图片请求的URI,但我更希望能通过命令行来完成这个过程。
我觉得可能可以用python和qtwebkit来实现,但也许还有更好的方法。
为了更清楚,我可能有这样的(过于简化的代码)。
<script>
suffix = magicNumberFunctionIDontHaveAccessTo();
url = "http://foobar.com/function?parameter=" + suffix
img = document.createElement('img'); img.src=url; document.all.body.appendChild(img);
</script>
然后一旦页面加载完成,我就可以通过嗅探数据包来找出网址。但我不能仅仅通过源代码来找,因为我无法预测magicNumberFunction...()的结果。
任何帮助都会非常感谢!
谢谢。
5 个回答
我会选择很多用Python写的HTTP代理服务器中的任何一个,可能是列表最上面那些最简单的,然后稍微修改一下,让它能记录所有请求的URL(同时也能代理这些请求),比如把这些URL添加到一个文本文件里——我们就叫这个文件'XXX.txt'。
接下来,你只需要一个脚本来:启动你选择的代理服务器;在Firefox(或者其他浏览器)上打开你想要访问的主URL,并把这个代理设置为你的代理(具体怎么做可以参考这个问题),当然其他浏览器也应该能正常工作;等一会儿(比如等代理的XXX.txt文件超过N秒没有被修改);读取XXX.txt,只提取你关心的URL,并把它们记录到你想要的地方;最后关闭代理和Firefox的进程。
我觉得这样做比用qtwebkit、selenium或其他“自动化工具”来实现你的特定需求要快得多,容易得多。
最简单的方法可能是使用像HtmlUnit这样的工具,完全不需要真实的浏览器。通过使用Rhino,它可以执行JavaScript,可能还可以用来提取那个网址。
不过,如果你无法让这个方法工作,可以试试Selenium RC,并使用captureNetworkTraffic命令(这需要在启动Selenium时加上captureNetworkTraffic=true这个选项)。这样会启动Firefox,并配置一个代理,然后你可以把请求信息以JSON/XML/纯文本的形式提取出来。接着,你可以解析这些内容,获取你想要的信息。
还可以试试我公司提供的即时测试工具。如果你想要的数据在我们的结果中(点击查看详情后),你就可以通过Selenium获取到。我知道这些,因为我为我公司BrowserMob编写了Selenium的captureNetworkTraffic API。
最后,我是用Python来实现这个的,使用了Selenium-RC。这个解决方案需要你有selenium-rc的Python文件,并且你需要启动Java服务器(通过命令“java -jar selenium-server.jar”)。
from selenium import selenium
import unittest
import lxml.html
class TestMyDomain(unittest.TestCase):
def setUp(self):
self.selenium = selenium("localhost", \
4444, "*firefox", "http://www.MyDomain.com")
self.selenium.start()
def test_mydomain(self):
htmldoc = open('site-list.html').read()
url_list = [link for (element, attribute,link,pos) in lxml.html.iterlinks(htmldoc)]
for url in url_list:
try:
sel = self.selenium
sel.open(url)
sel.select_window("null")
js_code = '''
myDomainWindow = this.browserbot.getUserWindow();
for(obj in myDomainWindow) {
/* This code grabs the OMNITURE tracking pixel img */
if ((obj.substring(0,4) == 's_i_') && (myDomainWindow[obj].src)) {
var ret = myDomainWindow[obj].src;
}
}
ret;
'''
omniture_url = sel.get_eval(js_code) #parse&process this however you want
except Exception, e:
print 'We ran into an error: %s' % (e,)
self.assertEqual("expectedValue", observedValue)
def tearDown(self):
self.selenium.stop()
if __name__ == "__main__":
unittest.main()