我正在尝试为特定网站编写我的第一个Chrome扩展程序,自动下载网站加载的流。我已经使用chrome.debugger api下载了流,但现在我想使用网站上的数据自动命名流。
首先,让我给你相关的脚本:
manifest.json
---------------------------------------
{
"name": "Downloader script",
"description": "Downloads stuff",
"version": "0.1",
"permissions": [
"debugger",
"downloads"
],
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_title": "Downloader"
},
"manifest_version": 2
}
这是background.js,它显示一个窗口,说明已下载的所有文件。
background.js
--------------------------
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.debugger.attach({tabId:tab.id}, version,
onAttach.bind(null, tab.id));
});
var version = "1.0";
function onAttach(tabId) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
chrome.windows.create(
{url: "headers.html?" + tabId, type: "popup", width: 400, height: 600});
}
以下是(非常简单的)headers.html:
<html>
<head>
<style>
body {
font-family: monospace;
word-wrap: break-word;
}
#container {
white-space: pre;
}
.request {
border-top: 1px solid black;
margin-bottom: 10px;
}
</style>
<script src="headers.js"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
现在来了困难的部分,header.js
var tabId = parseInt(window.location.search.substring(1));
window.addEventListener("load", function() {
chrome.debugger.sendCommand({tabId:tabId}, "Network.enable");
chrome.debugger.onEvent.addListener(onEvent);
});
window.addEventListener("unload", function() {
chrome.debugger.detach({tabId:tabId});
});
var requests = {};
function onEvent(debuggeeId, message, params) {
if (tabId != debuggeeId.tabId)
return;
if (message == "Network.requestWillBeSent") {
var requestDiv = requests[params.requestId];
if (!requestDiv && params.redirectResponse) {
var requestDiv = document.createElement("div");
requestDiv.className = "request";
requests[params.requestId] = requestDiv;
downloadSong(params.requestId, params.redirectResponse);
}
document.getElementById("container").appendChild(requestDiv);
}
}
function downloadSong(requestId, response) {
var requestDiv = requests[requestId];
var newSong = document.createElement("div");
newSong.textContent = "New song is being downloaded...";
var songLink = document.createElement('a');
var songLinkText = document.createTextNode("Direct link to song");
songLink.appendChild(songLinkText);
songLink.title = "Right click -> save as...";
songLink.href = response.headers.location;
if (songLink.href.indexOf("//audio") > -1) {
requestDiv.appendChild(newSong);
requestDiv.appendChild(songLink);
chrome.downloads.download({url: response.headers.location},function(id){});
}
}
现在我从中获取流的网站具有以下结构:
<div id="trackInfo" class="unselectable">
<div class="contents" style="display: block;">
<div class="info">
<div class="trackData">
<div><a href="http://www.linktowebsite" class="songTitle" address="true">This is the song title i want to grab</a></div>
<div><i class="byText">by</i> <a href="http://www.artistlink" class="artistSummary" address="true">Artist name i want to grab</a>
</div>
<div><i class="onText">on</i> <a class="albumTitle" address="true" href="http://www.albumlink" style="">Album title i want to grab</a></div>
</div>
</div>
</div>
</div>
我的问题是:如何从页面中获取元素数据(我相信它被称为DOM)并将其与chrome.downloads api一起使用?由于headers.js文件(我认为)不与网页本身联系,只是网络部分。
PS:我第一次在这里发帖,我的帖子也会受到建设性的批评。
答案 0 :(得分:0)
我有一种感觉,你在这里使用榴弹炮狩猎松鼠,使用"debugger"
拦截网络请求并将DOM注入页面。
为了拦截网络请求,有一个专用的API,chrome.webRequest
。
您可以将监听器附加到chrome.webRequest.onBeforeRequest
,您将获得与chrome.debugger.onEvent
收听者中使用的信息相同的信息。
为了注入您的DIV并从DOM读取数据,您(仅)需要content script。
以下代码假设您还将使用jQuery(没有理由不这样做,用它来操作DOM更容易)。它只是骨架代码。
您可以指定内容脚本以始终加载音乐服务,并使用chrome.runtime.onMessage
收听来自背景的消息:
chrome.runtime.onMessage.addListener(function(message) {
if(message.songUrl){
var newSong = $('<div>').text(New song is being downloaded...);
/* fill the <div> and append it to the page */
}
});
当您的后台检测到音乐流下载时,它会在请求事件中显示tabId
,并且可以向所需的标签发送消息:
chrome.webRequest.onBeforeRequest.addListener(
function(details){
if (details.url.indexOf("//audio") > -1) {
chrome.tabs.sendMessage(tabId, {songUrl: details.url});
}
return {}; // Do not modify the request
},
/* filter details */
);
至于提取歌曲细节,jQuery是你的朋友。你需要提出一个选择器来选择你需要的元素:
// Inside content script
var songName = $("#trackInfo .songTitle").text();
// etc.