Coder Social home page Coder Social logo

edjopato / website-stalker Goto Github PK

View Code? Open in Web Editor NEW
52.0 5.0 6.0 719 KB

Track changes on websites via git

License: GNU Lesser General Public License v2.1

Dockerfile 0.92% Rust 99.08%
scraper git change-alert change-detection monitoring self-hosted url-monitor web-scraping website-change-detector website-change-monitor

website-stalker's Introduction

Website Stalker

Track changes on websites via git

This tool checks all the websites listed in its config. When a change is detected, the new site is added to a git commit. It can then be inspected via normal git tooling.

Basically it's curl, sed++ and then git commit in a neat package.

See it in action (literally in GitHub Actions).

Install

Usage

GitHub Actions

Check out website-stalker-example which runs within GitHub actions.

Locally

  • First create a new folder / git repository for tracking website changes

    mkdir personal-stalker
    cd personal-stalker
    git init
    website-stalker example-config > website-stalker.yaml
  • Add your favorite website to the configuration file website-stalker.yaml. Also make sure to set the value of from to an email address of yours.

    website-stalker example-config > website-stalker.yaml
    nano website-stalker.yaml
  • Run your newly added website. If you added https://apple.com/newsroom use something like this to test if everything works like you want:

    website-stalker run apple
  • Set up a cronjob / systemd.timer executing the following command occasionally

    website-stalker run --all --commit

Config Example

The config describes a list of sites. Each site has a URL. Additionally, each site can have editors which are used before saving the file. Each editor manipulates the content of the URL.

# This is an example config
# The filename should be `website-stalker.yaml`
# and it should be in the working directory where you run website-stalker.
#
# For example run `website-stalker example-config > website-stalker.yaml`.
# Adapt the config to your needs and set the FROM email address which is used as a request header:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/From
#
# And then do a run via `website-stalker run --all`.
---
from: my-email-address
sites:
  - url: "https://edjopato.de/post/"
    editors:
      - css_select: article
      - css_remove: a
      - html_prettify
      - regex_replace:
          pattern: "(Lesezeit): \\d+ \\w+"
          replace: $1
  - url: "https://edjopato.de/robots.txt"

There is a bigger config in my example repo. The example repo is also used by me to detect changes of interesting sites.

Global Options

Options which are globally configured at the root level of the configuration file website-stalker.yaml.

from

Used as the From header in the web requests. It is a required field.

The idea here is to provide a way for a website host to contact whoever is doing something to their web server. As this tool is self-hosted and can be run as often as the user likes this can annoy website hosts. While this tool is named "stalker" and is made to track websites it is not intended to annoy people.

This tool sets the User-Agent header to website-stalker/<version> https://github.com/EdJoPaTo/website-stalker and the From header to the user configured value. This way both the creator and the user of this tool can be reached in case of problems.

from: my-email-address

Alternatively you can specify FROM via environment variable

export WEBSITE_STALKER_FROM=my-email-address

Per Site Options

Options available per site besides the editors which are explained below.

url

One or multiple URLs can be specified. The simple form is a single URL:

sites:
  - url: "https://edjopato.de/"
  - url: "https://edjopato.de/post/"

It's also possible to specify multiple URL at the same time. This is helpful when multiple sites are sharing the same options (like editors).

sites:
  - url:
      - "https://edjopato.de/"
      - "https://edjopato.de/post/"

accept_invalid_certs

Allows HTTPS connections with self-signed or invalid / expired certificates.

From reqwests documentation:

You should think very carefully before using this method. If invalid certificates are trusted, any certificate for any site will be trusted for use. This includes expired certificates. This introduces significant vulnerabilities, and should only be used as a last resort.

Do you have a need for self-signed certificates or the usage of the system certificate store? Please share about it in Issue #39.

sites:
  - url: "https://edjopato.de/post/"
    accept_invalid_certs: true

http1_only

Only use HTTP/1 for the web request.

Backends might use HTTP/2 fingerprinting which could result in different or unusable output depending on what the backend assumes about the client. HTTP/1 is a simpler protocol which does not allow such kinds of backend optimizations.

sites:
  - url: "https://edjopato.de/post/"
    http1_only: true

ignore_error

Only show warning when the site errors.

This is useful for buggy services which are sometimes just gone or for pages which will exist in the future but are not there yet. Personal example: A bad DNS configuration which lets the website appear nonexistent for some time.

This setting also skips errors from editors.

sites:
  - url: "https://edjopato.de/might-appear-in-the-future"
    ignore_error: true

filename

Overrides the URL based default filename of the site.

Normally the filename is automatically derived from the URL. For the following example it would be something like de-edjopato-api-token-0123456789-action-enjoy-20weather.html. With the filename options it is saved as de-edjopato-api-weather.html instead.

sites:
  - url: "https://edjopato.de/api?token=0123456789&action=enjoy%20weather"
    filename: de-edjopato-api-weather

headers

Add additional HTTP headers to the request to the given site.

This is useful for sites that respond differently based on different headers. Each header Key/Value pair is supplied as YAML String separated with a : followed by a space.

This is the same syntax as HTTP uses which sadly collides with YAML. YAML assumes something with a : is an object. Therefor you have to make sure to quote the headers. Using a YAML object / key/value pair is also not possible as some header keys are allowed multiple times.

sites:
  - url: "https://edjopato.de/"
    headers:
      - "Cache-Control: no-cache"
      - "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0"

Editors

Editors are manipulating the content of a webpage to simplify comparing them later on.

For example: If you are interested in the content of a webpage the <head> with changing stylesheets isn't interesting to you. When keeping it, it will still create diffs which end up being commits. This will create noise you're probably just going to ignore. That's why editors exist.

Think of editors like a pipeline, the next one gets the input of the one before. As some editors are assuming HTML input, they won't work (well) with non HTML input. For example its kinda useless to use html_prettify after html_textify as text won't end up being pretty HTML. For this reason editors like css_select are still producing valid HTML output.

There are probably more tasks out there that might be useful as editors. Feel free to provide an issue for an editor idea or create a Pull Request with a new editor.

css_remove

Tries to remove every instance of matching HTML elements and returns the remaining HTML. Opposite of css_select.

Examples:

editors:
  - css_remove: article
  - css_remove: h1 a
  - css_remove: h1 > a

css_select

Use CSS Selectors to grab every instance of matching HTML elements and returns all of them.

If no matching HTML elements are found, this editor errors.

Examples:

editors:
  - css_select: article
  - css_select: h1 a
  - css_select: h1 > a

html_markdownify

Formats the input HTML as Markdown.

Example:

editors:
  - html_markdownify

html_prettify

Formats the input HTML as pretty HTML.

Example:

editors:
  - html_prettify

html_sanitize

Strip down HTML to its minimal form.

Example:

editors:
  - html_sanitize

html_textify

Only returns text content of HTML elements within the input.

Example:

editors:
  - html_textify

html_url_canonicalize

Parses the input HTML for URLs. URLs are parsed into their canonical, absolute form.

Example:

editors:
  - html_url_canonicalize

json_prettify

Formats the input JSON as pretty JSON.

Example:

editors:
  - json_prettify

regex_replace

Searches the input with a Regex pattern and replaces all occurrences with the given replace phrase. Grouping and replacing with $1 also works.

Examples:

editors:
  # Remove all occurrences of that word
  - regex_replace:
      pattern: "tree"
      replace: ""
  # Remove all numbers
  - regex_replace:
      pattern: "\\d+"
      replace: ""
  # Find all css files and remove the extension
  - regex_replace:
      pattern: "(\\w+)\\.css"
      replace: $1

rss

Creates an RSS 2.0 Feed from the input. An RSS item is generated for every item_selector result. The other selectors can be used to find relevant information of the items. The content is the full result of the item_selector. It can be further edited with every available editor.

Defaults:

  • title: When a <title> exists, it will be used. Otherwise, it's empty.
  • item_selector: article
  • title_selector: h2
  • link_selector: a
  • content_editors can be omitted when empty

Examples:

  # Fully specified example
  - url: "https://edjopato.de/post/"
    editors:
      - rss:
          title: EdJoPaTos Blog
          item_selector: article
          title_selector: h2
          link_selector: a
          content_editors:
            - css_remove: "h2, article > a, div"
            - html_textify

  # Minimal working example
  - url: "https://edjopato.de/post/"
    editors:
      - rss: {}

Alternatives

website-stalker's People

Contributors

dependabot[bot] avatar edjopato avatar kidonng avatar teufelchen1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

website-stalker's Issues

Create issue for the changes with link for the commit

It would be great if we can use the notifier config to create an issue in github action. I am planning to use to detect API change for SDK package, so I can see I have action to do.

If the formatted text can be reached, we can setup Github action to create issue with that description or use Github Action to notify on unsupported platforms as well.

Allow override of 'sites/'

Is your feature request related to a problem? Please describe.

Since #180 it has been possible to override an individual filename, but as far as I can see there is currently no way to override the directory that files get created within: this always defaults to sites/

Describe the solution you'd like

The simplest approach would probably be for a top-level config option to change this for all sites, though it might also make sense to be able to override this for an individual site with a config option at that level.

[Feature request] html to text

I want to watch an html page. Currently, commit shows changes including html tags. I'm not interested in html tags. I'd like an option to filter them out.

Commit per Domain or all

Is your feature request related to a problem? Please describe.

Sometimes I would like to share a commit for a specific domain which changed stuff but another one also changed things which are unrelated.

Describe the solution you'd like

Additionally to --commit there could be --commit-domains and --commit-all. This might work well with #184 too as the domains would be stored in their own folder.

command editor

Is your feature request related to a problem? Please describe.

The editors are not completely perfect. There might be cases missing which might be special to certain websites.

Describe the solution you'd like

Having the option to output the current content to a command and continue to use its outputs might be a powerful way around this.

  • #77 might just be command: jq .something
  • #189 is currently stalled because there is no great way to debug it. Having an output only command in between could be neat here: debug: <filepath> could just output the current state of whatever the input is. #189 also highlights that there might be some additional element required as just a file path would override itself on multiple runs of the same editor. Maybe don't take a file path and just write files with a counter in the name? It's just to help debug after all, not to be committed (maybe error on --commit when a debug editor is there?).

The docs of the command editor could include a hint to submit an issue about it. When its useful it could be added to the editor implementations natively.
Also, it can be searched for instances of this via GitHub search and implement it when I find a good case of this.

Sorting/Ordering is changed, but no change in content

Hey,

first I'm happy that I found your tool, it's very very useful.

I have one special case for a change-tracking. I want to keep track of changes on the site https://antcheck.info/species/Colobopsis_leonardi
There are cards with prices. The cards seem to be generated, so the order of the cards changes with every call. Of course website-stalker does recognize this as a change. Is there a way to re-order/sort the elements so there are only changes detected, when there are really changes? at the moment I use this config

Replace integrated git support by usage of the existing git executable

Is your feature request related to a problem? Please describe.

Currently the git integration is done via libgit2 which can have wrong versions with the system libgit2 version as it isn't pure rust.

Describe the solution you'd like

Replace the current git support with git commands being run in the current folder with the git executable in PATH.

Describe alternatives you've considered

gitoxide might be a neat pure rust implementation.

Additional context

#132

Commit message based on changed site

Is your feature request related to a problem? Please describe.

Commit message headers are not very helpful on seeing what actually changed.

stalked some things ๐Ÿ‘€๐ŸŒ๐Ÿ˜Ž

M https://stisys.haw-hamburg.de/

When only looking on the header only stalked some things ๐Ÿ‘€๐ŸŒ๐Ÿ˜Ž can be read with isnt that helpful

Describe the solution you'd like

If only one site changed the header could contain the actual site. Multiple sites probably still need something generic and a list in the commit message body. Maybe the header could contain the number of sites changed in that case.

A prefix like the ones used in conventional commits might be interesting to differentiate between automatic website-stalker and humans updating for example the config in the same repo. On the other hand the author is already set and easily visible in the commit history like on github or more complex git log --oneline formats. Also see 63aae58 as it was already there in the past.

Things still to be considered: commit headers should be <50 characters. Long urls might be too long. Maybe only include the domain name here and omit protocol / path?

Ideas:

website-stalker: stalked 2 website changes

M https://edjopato.de/
M https://edjopato.de/post/
๐Ÿค–๐Ÿ‘€ 2 website changes

M https://edjopato.de/
M https://edjopato.de/post/
website-stalker: stalked changes on edjopato.de

M https://edjopato.de/post/
stalked changes on https://edjopato.de/post/

M https://edjopato.de/post/
๐Ÿค–๐Ÿ‘€ edjopato.de

M https://edjopato.de/post/
๐Ÿค–๐Ÿ‘€ https://edjopato.de/post/

Overriding filename?

Describe your goal
I have a url that includes a long query string.
The run fails with File name too long (os error 36)

Expected
The easiest option would seem to be allowing a custom filename to be defined for a given url?
E.g. with a new key filename

Thanks for considering it!

Latest version breaks Github Action

Describe the bug
The Github Action started to remove all folders and files from the repo before running fetching the websites.

Versions

Run EdJoPaTo/website-stalker-github-action@v1
  with:
    version: latest
    triple: x86_64-unknown-linux-gnu
  env:
    WEBSITE_STALKER_FROM: ***
Run base=https://api.github.com/repos/EdJoPaTo/website-stalker/releases/
+ base=https://api.github.com/repos/EdJoPaTo/website-stalker/releases/
+ '[' latest == latest ']'
+ base+=latest
+ releases=/tmp/website-stalker-releases.json
+ curl --header 'authorization: ***' --output /tmp/website-stalker-releases.json https://api.github.com/repos/EdJoPaTo/website-stalker/releases/latest
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 [2](https://github.com/WebstormitDev/paddle-billing-client/actions/runs/6093419225/job/16533065513#step:2:2)8968  100 28968    0     0  96594      0 --:--:-- --:--:-- --:--:-- 96882
+ jq . /tmp/website-stalker-releases.json
{
  "url": "https://api.github.com/repos/EdJoPaTo/website-stalker/releases/12001226[3](https://github.com/WebstormitDev/paddle-billing-client/actions/runs/6093419225/job/16533065513#step:2:3)",
  "assets_url": "https://api.github.com/repos/EdJoPaTo/website-stalker/releases/1200122[6](https://github.com/WebstormitDev/paddle-billing-client/actions/runs/6093419225/job/16533065513#step:2:6)3/assets",
  "upload_url": "[https://uploads.github.com/repos/EdJoPaTo/website-stalker/releases/120012263/assets{?name](https://uploads.github.com/repos/EdJoPaTo/website-stalker/releases/120012263/assets%7B?name),label}",
  "html_url": "https://github.com/EdJoPaTo/website-stalker/releases/tag/v0.21.0",
  "id": 120012263,
.....

Expected behavior
Works as before with the same config.

Additional information

Run website-stalker run --all
  website-stalker run --all
  shell: /usr/bin/bash -e {0}
  env:
    WEBSITE_STALKER_FROM: ***
Warning: Remove superfluous "assets/images/coverage.svg"
INFO: Some sites are on the same host. There is a wait time of [5](https://github.com/WebstormitDev/paddle-billing-client/actions/runs/6093419225/job/16533065513#step:5:5) seconds between each request to the same host in order to reduce load on the server.
Warning: Remove superfluous "docker/Dockerfile"
Warning: Remove superfluous "docker/README.md"
Warning: Remove superfluous "paddle_billing_client/__init__.py"
Warning: Remove superfluous "paddle_billing_client/client.py"
Warning: Remove superfluous "paddle_billing_client/endpoints.py"
Warning: Remove superfluous "paddle_billing_client/formatters.py"
Warning: Remove superfluous "paddle_billing_client/models/__init__.py"
Warning: Remove superfluous "paddle_billing_client/models/address.py"
Warning: Remove superfluous "paddle_billing_client/models/adjustment.py"
Warning: Remove superfluous "paddle_billing_client/models/base.py"
Warning: Remove superfluous "paddle_billing_client/models/business.py"
.......

Default extension

Is your feature request related to a problem? Please describe.

Currently extensions of the site files are hardcoded. Changing from html_prettify to html_markdownify results in easily forgetting to change the extension.

Describe the solution you'd like

Some editors export some specific format.
After using rss its xml. After using markdownify its md and so on.
If its unclear txt might be a good default as everything is text based.
Other than that maybe the mime type from the http request could be used to determine the extension.

html_prettify: sort class and style attributes

Is your feature request related to a problem? Please describe.

Changes like this are annoying and don't help:

-<a class="external link">
+<a class="link external">

-<a style="color: white; display: none">
+<a style="display:none;color:white">

Describe the solution you'd like

Sort and apply basic formatting (always one space rather than 3) for class and style.

If the formatting fails (two : in one style element or whatever) just use the unformatted content and don't error about it.

[Feature request] Convert relative links to absolute

Is your feature request related to a problem? Please describe.
I use html_markdownify in my config. Most of the pages I'm watching use relative links making them unclickable.

Describe the solution you'd like
Convert the relative links to absolute so they are clickable.

Describe alternatives you've considered
n/a

Additional context
n/a

Init git repo subcommand

When there is no repo it might be helpful to just create one.

Not sure if this should be done on the run subcommand (when --commit is given) or if this should be behind another subcommand like init-git with the example config.

do not commit anything when config is modified

Is your feature request related to a problem? Please describe.

When the config is modified the commit would create an out of sync situation. The sites folder is not what can be created via config.
The sites folder should always follow the config.

Describe the solution you'd like

If the config is modified a warning is displayed and no commit is done.

Additional context

see also #11

Check robots.txt

Is your feature request related to a problem? Please describe.

bots on the internet should honor the robots.txt (see RFC 9309

Describe the solution you'd like

Checking the robots.txt of every domain being crawled before crawling the actual content.
I think the tool should provide an option to ignore the robots.txt but being annoyed about it on stdout when enabled.

The downside is an additional request to the server on every crawling attempt

Describe alternatives you've considered

Provide an additional subcommand to check the domains in the config for the robots.txt. The user of this tool can run the command to see if they are allowed to do this by the host.
This way the additional requests are only done on demand and the user can decide to remove their crawling attempts.
Maybe integrate this into the check command which checks the config and error when the robots.txt denies a path?

One commit per host

Is your feature request related to a problem? Please describe.

When multiple things happen at the same time it's not as easy to share a link to a commit with only changes of the given domain.

Describe the solution you'd like

Group commits by their host. This will generate multiple commits when there are changes on different domains.

This would simplify the git commit message too as it's always showing the host and not "42 websites changed" then.

Describe alternatives you've considered

File renames would be harder to keep track of. Just commiting everything is way simpler.

Remove `check` sub-command

When using website-stalker i almost never use the check sub-command. Its part of some CI stuff but its mostly pointless there too as its followed directly by the run sub-command anyway.

When I add new sites to the config I just use run with a site filter, and it will error when something is wrong too.

Is there any use of the check sub-command or can it just be removed?

Would a run --dry-run be helpful instead? Personally I think keeping it simple would be the best way so remove it without an alternative.

Use environment variable for `from`

Is your feature request related to a problem? Please describe.
I'll take your repo here as example: https://github.com/EdJoPaTo/website-stalker-example
If someone forks/clones that repo and run it as is, your email address will be visible to those websites. It would look as if it was you who ran it instead of the one who forked/cloned it.

Describe the solution you'd like
from should also be looked up at an environment variable.

What's the purpose of `from:`?

Describe your goal
I just followed the example and put my email address instead.

Expected
I expected my email address but it's not showing up on git logs. This is what I see in the log instead Author: website-stalker/0.12.1 <[email protected]>

Allow grouping of links

Is your feature request related to a problem? Please describe.
I'm following multiple links and I apply the same editors for all of them. Below is an example:

---
from: email@address
sites:
  - url: https://example.com/one
    extension: md
    editors:
      - html_markdownify
  - url: https://example.com/two
    extension: md
    editors:
      - html_markdownify

Describe the solution you'd like
I want it shortened to something like this:

---
from: email@address
sites:
  - urls:
      - https://example.com/one
      - https://example.com/two
    extension: md
    editors:
      - html_markdownify

Describe alternatives you've considered

Additional context

systemd.timer

Add systemd.service and systemd.timer to the project to be used easily (and to be integrated with the AUR package)
Also provide hints to systemctl edit website-stalker.timer on how to edit the time interval.

Should this be a user service? system service? What is the working directory? When the working directory isnt a git repo, should one be created?

Does not run in new repo without commits

Describe the bug

Does not run in new repo without commits.

% website-stalker run --all
ERROR: reference 'refs/heads/main' not found; class=Reference (4); code=UnbornBranch (-9)
Thanks for using website-stalker!

Versions

  • Version of website-stalker: 0.12.0

To Reproduce
Steps to reproduce the behavior:

mkdir folder && cd folder
website-stalker init
website-stalker run --all

Expected behavior

Runs

Self-signed certificate not recognized

Describe the bug
I'm testing website-stalker against my website on my local network. It has a certificate trusted by my device. Running website-stalker gives me an error saying it's an invalid certificate.

Versions

  • Version of website-stalker: 0.13.0
  • Version of rustc: n/a
  • Version of cargo: n/a

To Reproduce
Steps to reproduce the behavior:

  1. Setup test website (e.g. https://server.lan/) with self-signed certificate
  2. Trust certificate on all participating devices system-wide
  3. Use the config below
  4. Run website-stalker run --all --commit
  5. See error below

Expected behavior
The error should not be there. The contents of the webpage should have been committed.

Additional information

$ curl -Is https://server.lan | head -n1
HTTP/2 200

website-stalker.yaml

---
from: [email protected]
sites:
  - url: https://server.lan/
    extension: html
    editors:
      - html_prettify

Error:

$ website-stalker run --all --commit
Begin stalking of 1 sites on 1 domains...
ERROR: https://server.lan/ error sending request for url (https://server.lan/): error trying to connect: invalid certificate: UnknownIssuer
ERROR: All done but some site failed.
Thanks for using website-stalker!

Select parts of a json

Is your feature request related to a problem? Please describe.

Select only parts of the JSON like you can do with jq.

Describe the solution you'd like

An editor like json_select could be nice.

Currently this is not something I need so this is only a tracker of useful resources about it. If someone needs this, feel free to state it here and I will take a closer look.

Additional context

https://crates.io/crates/jsonpath_lib

Detect Redirects and hint better / new urls to reduce traffic

Is your feature request related to a problem? Please describe.

Websites switch domains or rearrange stuff. Sometimes its just edjopato.de/post โ†’ edjopato.de/post/
This redirect happens every time the content is grabbed which results in unneccesary traffic.

Describe the solution you'd like

The website-stalker should print out warnings which url should be improved (add / at the end for example).

Current main can't parse it's own example config

[disclaimer: I'm inexperienced in rust]

The current main can not parse the config generated by the current main when using either init or example-config.

Versions

  • Version of website-stalker: latest main

To Reproduce
Steps to reproduce the behavior:

  1. Freshly clone the repo
  2. cargo build
  3. cargo run example-config > website-stalker.yaml
  4. cargo run check
  5. See error
unknown variant `article`, expected one of `css_remove`, `css_select`, `html_markdownify`, `html_prettify`, `html_sanitize`, `html_textify`, `html_url_canonicalize`, `json_prettify`, `regex_replace`, `rss`

Expected behavior

Successful parsing of the config.

Additional information

Beside this, the real bug might be hidden in config.rs, where the unit tests are inadequate. For example this:

#[test]
fn can_parse_example() {
    let conf_str: String = Config::example_yaml_string();
    let _conf: Config = serde_yaml::from_str(&conf_str).unwrap();
}

would have spotted this issue immediately.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.