Мы, как программисты, должны постоянно находиться перед своими компьютерами. Большая часть нашей рабочей жизни проводится в Интернете. Будь то поиск решений по stackoverflow или отставка от коллег, чтение документации и т. Д. Но Интернет всегда отвлекает. В то же время у нас может появиться несколько вкладок Stackoverflow, Instagram, gmail, python docs, YouTube и т. Д. Мы можем этого не почувствовать, но это действительно тратит много времени. Таким образом, становится необходимым отслеживать время просмотра вашего веб-сайта, чтобы вы имели представление о том, насколько продуктивен ваш день.

Я научу вас, как создать скрипт Python, который может отслеживать, какие веб-сайты вы просматриваете и сколько времени вы на них проводите.

Как мы это сделаем?

Этот проект будет состоять из двух компонентов:

  1. Расширение Chrome, которое будет отслеживать текущий веб-сайт, который вы просматриваете.
  2. Флэш-сервер, который будет использовать эти данные для расчета времени, проведенного на определенном веб-сайте.

Расширение chrome будет иметь фоновый скрипт, который будет отслеживать любые изменения в текущей активной вкладке или URL-адресе. Всякий раз, когда происходит какое-либо изменение, он отправляет новый текущий активный URL-адрес на сервер Flask с помощью HTTP-запроса. Тем временем сервер flask рассчитает время, прошедшее с момента предыдущего запроса и нового запроса. Это будет время, потраченное на предыдущий URL.

Сначала мы создадим расширение для Chrome, которое будет отправлять HTTP-запрос на сервер flask, как только активный URL-адрес изменится.

Не волнуйтесь, сделать такое хромированное расширение несложно. Для этого вам просто необходимы базовые знания JavaScript. Я проведу вас по шагам:

Изготовление хромированной пристройки.

Обратите внимание, что нам не нужно создавать интерфейс для нашего расширения, поскольку наше расширение служит только простой цели. Мы просто напишем фоновый скрипт, который будет работать в фоновом режиме браузера, пока расширение активно. Вот файловая структура нашего расширения:

Как показано, наше расширение состоит из 3 файлов:

  • background.js: этот файл будет содержать код, который будет работать в фоновом режиме браузера.
  • icon.png: наш файл значка расширения. Вы можете скачать любой файл значка в формате PNG из Интернета и использовать его.
  • manifest.json: этот файл содержит основные конфигурации, относящиеся к нашему расширению.

Прежде всего, давайте начнем кодировать наш файл background.js.

Работа с этим файлом проста. Просто наблюдайте, когда человек переключается между вкладками или открывает новую вкладку. Как только это произойдет, отправьте HTTP-запрос на сервер с новым текущим URL-адресом в качестве данных. Чтобы определить, когда открывается новая вкладка, Chrome API имеет встроенный слушатель, который вызывается каждый раз.

chrome.tabs.onActivated.addListener(function (activeInfo) {
    chrome.tabs.get(activeInfo.tabId, function (tab) {
        y = tab.url;
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
            }
        };
        xhttp.open("POST", "http://127.0.0.1:5000/send_url");
        xhttp.send("url=" + y);

    });
});

В приведенном выше коде onActivated.addListener() вызывается всякий раз, когда в окне браузера активируется новая вкладка. Внутри этой функции мы можем получить доступ к идентификатору этой вкладки с помощью tabId и URL-адресу с помощью tab.url. Затем мы отправляем HTTP-запрос с XMLHttpRequest() на /send_url конечную точку с URL-адресом в качестве данных.

Теперь нам нужно создать слушателя всякий раз, когда пользователь переключается между вкладками. Мы используем для этого onUpdated.addListener(). Эта функция вызывается при обновлении вкладок.

chrome.tabs.onUpdated.addListener((tabId, change, tab) => {
    if (tab.active && change.url) {

        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
            }
        };
        xhttp.open("POST", "http://127.0.0.1:5000/send_url");
        xhttp.send("url=" + change.url);

    }
});

В onUpdated.addListener() объект change может использоваться для доступа к новому URL-адресу. Мы снова отправляем этот измененный URL-адрес на сервер, используя XMLHttpRequest() .

Теперь мы должны также определять, когда вкладка закрыта, чтобы мы могли обновить ее временную метку и время просмотра в коде сервера. Для этого мы используем комбинацию onUpdated() и onRemoved() слушателей. Это сделано потому, что всякий раз, когда вкладка удаляется, это также считается обновлением в Chrome. Также мы не можем получить доступ к URL-адресу удаленной вкладки из функции onRemoved(), поэтому мы должны использовать его в сочетании с onUpdated().

// define a mapping between tabId and url:
var tabToUrl = {};

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    //store tabId and tab url as key value pair:
    tabToUrl[tabId] = tab.url;
});

chrome.tabs.onRemoved.addListener(function (tabId, removeInfo) {
    //since tab is not available inside onRemoved,
    //we have to use the mapping we created above to get the removed tab url:
    console.log(tabToUrl[tabId]);

    var xhttp2 = new XMLHttpRequest();
    xhttp2.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
        }
    };
    xhttp2.open("POST", "http://127.0.0.1:5000/quit_url");
    xhttp2.send("url=" + tabToUrl[tabId]);

    // Remove information for non-existent tab
    delete tabToUrl[tabId];

});

На этом мы завершили код background.js. Теперь давайте создадим manifest.json и добавим в него следующий код:

{
	"manifest_version": 2,
	"name": "Currenturl",
	"description": "Fetches current tab url.",
	"version": "0.1",
	"author": "Tarun Khare",
	"browser_action": {
		"default_icon": "icon.png",
		"default_title": "Just observing your current url."
	},
	"permissions": ["tabs", "activeTab", "http://127.0.0.1:5000/*", "storage"],
	"background": {
		"scripts": ["background.js"],
		"persistent": false
	}
}

В этом файле мы определяем такие вещи, как имя расширения, версия, файл значка и т. Д. Мы должны предоставить некоторые разрешения для нашего расширения. Итак, в «разрешениях» мы определяем «вкладки», «activeTab», хранилище и URL-адрес сервера, который в моем случае равен 127.0.0.1:5000. В «фоне» мы определяем имя нашего фонового скрипта, то есть «background.js».

Теперь наше расширение chrome готово. Мы можем начать писать наш скрипт на Python. В нашем коде Python сначала мы импортируем необходимые модули фляги и определим некоторые глобальные переменные.

from flask import Flask, jsonify, request
import time

app = Flask(__name__)
url_timestamp = {}
url_viewtime = {}
prev_url = ""

В приведенном выше коде мы будем использовать url_timestamp для хранения последней временной метки unix, когда URL-адрес стал активным. Например, если становится активным google.com, наше расширение отправит запрос на наш сервер с google.com в качестве данных. Как только этот запрос достигнет сервера, мы найдем время Unix в этот конкретный момент и сохраним эту временную метку как значение url_timestamp["google.com"].

Точно так же url_viewtime будет хранить общее время просмотра URL в секундах.

Поскольку URL-адреса часто бывают длинными, давайте создадим функцию, которая будет разделять URL-адреса только на их родительские. Например, https: twitter.com/codeharvestio следует сократить до www.twitter.com.

def url_strip(url):
    if "http://" in url or "https://" in url:
        url = url.replace("https://", '').replace("http://", '') 
            .replace('\"', '')
    if "/" in url:
        url = url.split('/', 1)[0]
    return url

Теперь напишем функцию для конечной точки send_url /. В этой функции всякий раз, когда мы получаем новый URL-адрес от нашего расширения, мы найдем текущую временную метку unix, используя функцию time.time(). По ним мы найдем метку времени предыдущего URL из url_timestamp словаря. Вычитая эти две отметки времени, мы получим время, потраченное на предыдущий URL. Затем мы добавим это время к общему времени просмотра предыдущего URL. Вот код для конечной точки send_url /.

@app.route('/send_url', methods=['POST'])
def send_url():
    resp_json = request.get_data()
    params = resp_json.decode()
    url = params.replace("url=", "")
    print("currently viewing: " + url_strip(url))
    parent_url = url_strip(url)

    global url_timestamp
    global url_viewtime
    global prev_url

    print("initial db prev tab: ", prev_url)
    print("initial db timestamp: ", url_timestamp)
    print("initial db viewtime: ", url_viewtime)

    if parent_url not in url_timestamp.keys():
        url_viewtime[parent_url] = 0

    if prev_url != '':
        time_spent = int(time.time() - url_timestamp[prev_url])
        url_viewtime[prev_url] = url_viewtime[prev_url] + time_spent

    x = int(time.time())
    url_timestamp[parent_url] = x
    prev_url = parent_url
    print("final timestamps: ", url_timestamp)
    print("final viewtimes: ", url_viewtime)

    return jsonify({'message': 'success!'}), 200

Для конечной точки quit_url / нам не нужно писать много кода. Причина в том, что, как только вкладка закрывается в Chrome, это также считается обновлением, поэтому функция onUpdated.addListener() во втором фрагменте кода запускается автоматически. Таким образом, запускаем функцию send_url() в нашем скрипте Python. Это обо всем позаботится. Но мы создадим эту функцию только для печати.

@app.route('/quit_url', methods=['POST'])
def quit_url():
    resp_json = request.get_data()
    print("Url closed: " + resp_json.decode())
    return jsonify({'message': 'quit success!'}), 200

Наконец, добавьте следующую строку, чтобы завершить код сервера:

app.run(host='0.0.0.0', port=5000)

Запустите свой код Python. Затем откройте хром. Нажмите на трехточечный символ в правом верхнем углу, затем «Дополнительные инструменты», затем «Расширения». Включите режим разработчика в правом верхнем углу этой страницы.

Теперь нажмите «Загрузить распакованный», чтобы загрузить расширение. Выберите папку, в которой находятся три ваших файла расширения. (Пожалуйста, не храните файл Python в этой папке, чтобы избежать проблем).

Теперь, как только ваше расширение запустится, вы можете открывать новые вкладки или переключаться между открытыми вкладками. Потратьте на них немного времени. Теперь откройте ваш работающий сервер Python. Вы увидите, как время URL-адреса печатается в консоли Python, как показано ниже.

Когда вы будете переключаться между вкладками или открывать новую вкладку или URL-адрес, обновленные выходные данные будут повторно распечатаны на консоли.

Это оно. Надеюсь, статья вам понравилась. Прокомментируйте в случае сомнений. Также читайте мои статьи на medium и подписывайтесь на меня в twitter. Также ознакомьтесь с другими моими статьями в этом блоге!

Первоначально опубликовано на http://www.codeharvest.io 11 июля 2019 г.