Pārlūkot izejas kodu

moved from old git repo

Johann Woelper 6 gadi atpakaļ
vecāks
revīzija
6d514c503d
8 mainītis faili ar 417 papildinājumiem un 0 dzēšanām
  1. 20 0
      Pipfile
  2. 91 0
      Pipfile.lock
  3. 60 0
      app.js
  4. 64 0
      db.json
  5. BIN
      icon.png
  6. 83 0
      index.html
  7. 10 0
      urls.json
  8. 89 0
      watcher.py

+ 20 - 0
Pipfile

@@ -0,0 +1,20 @@
+[[source]]
+
+url = "https://pypi.python.org/simple"
+verify_ssl = true
+name = "pypi"
+
+
+[dev-packages]
+
+
+
+[packages]
+
+requests = "*"
+lxml = "*"
+
+
+[requires]
+
+python_version = "2.7"

+ 91 - 0
Pipfile.lock

@@ -0,0 +1,91 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "b7153a94dd2391ac3c5b5304d8afddbb82f852e398f9f1eeb48a75469f2eb2e9"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "2.7"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.python.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "certifi": {
+            "hashes": [
+                "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+                "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+            ],
+            "version": "==2018.1.18"
+        },
+        "chardet": {
+            "hashes": [
+                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+            ],
+            "version": "==3.0.4"
+        },
+        "idna": {
+            "hashes": [
+                "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
+                "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
+            ],
+            "version": "==2.6"
+        },
+        "lxml": {
+            "hashes": [
+                "sha256:01c45df6d90497c20aa2a07789a41941f9a1029faa30bf725fc7f6d515b1afe9",
+                "sha256:0c9fef4f8d444e337df96c54544aeb85b7215b2ed7483bb6c35de97ac99f1bcd",
+                "sha256:0e3cd94c95d30ba9ca3cff40e9b2a14e1a10a4fd8131105b86c6b61648f57e4b",
+                "sha256:0e7996e9b46b4d8b4ac1c329a00e2d10edcd8380b95d2a676fccabf4c1dd0512",
+                "sha256:1858b1933d483ec5727549d3fe166eeb54229fbd6a9d3d7ea26d2c8a28048058",
+                "sha256:1b164bba1320b14905dcff77da10d5ce9c411ac4acc4fb4ed9a2a4d10fae38c9",
+                "sha256:1b46f37927fa6cd1f3fe34b54f1a23bd5bea1d905657289e08e1297069a1a597",
+                "sha256:231047b05907315ae9a9b6925751f9fd2c479cf7b100fff62485a25e382ca0d4",
+                "sha256:28f0c6652c1b130f1e576b60532f84b19379485eb8da6185c29bd8c9c9bc97bf",
+                "sha256:34d49d0f72dd82b9530322c48b70ac78cca0911275da741c3b1d2f3603c5f295",
+                "sha256:3682a17fbf72d56d7e46db2e80ca23850b79c28cfe75dcd9b82f58808f730909",
+                "sha256:3cf2830b9a6ad7f6e965fa53a768d4d2372a7856f20ffa6ce43d2fe9c0d34b19",
+                "sha256:5b653c9379ce29ce271fbe1010c5396670f018e78b643e21beefbb3dc6d291de",
+                "sha256:65a272821d5d8194358d6b46f3ca727fa56a6b63981606eac737c86d27309cdd",
+                "sha256:691f2cd97cf026c611df1ea5055755eec7f878f2d4f4330dc8686583de6fc5fd",
+                "sha256:6b6379495d3baacf7ed755ac68547c8dff6ce5d37bf370f0b7678888dc1283f9",
+                "sha256:75322a531504d4f383264391d89993a42e286da8821ddc5ac315e57305cb84f0",
+                "sha256:7f457cbda964257f443bac861d3a36732dcba8183149e7818ee2fb7c86901b94",
+                "sha256:7ff1fc76d8804e0f870c343a72007ff587090c218b0f92d8ee784ac2b6eaf5b9",
+                "sha256:8523fbde9c2216f3f2b950cb01ebe52e785eaa8a07ffeb456dd3576ca1b4fb9b",
+                "sha256:8f37627f16e026523fca326f1b5c9a43534862fede6c3e99c2ba6a776d75c1ab",
+                "sha256:a7182ea298cc3555ea56ffbb0748fe0d5e0d81451e2bc16d7f4645cd01b1ca70",
+                "sha256:abbd2fb4a5a04c11b5e04eb146659a0cf67bb237dd3d7ca3b9994d3a9f826e55",
+                "sha256:accc9f6b77bed0a6f267b4fae120f6008a951193d548cdbe9b61fc98a08b1cf8",
+                "sha256:bd88c8ce0d1504fdfd96a35911dd4f3edfb2e560d7cfdb5a3d09aa571ae5fbae",
+                "sha256:c557ad647facb3c0027a9d0af58853f905e85a0a2f04dcb73f8e665272fcdc3a",
+                "sha256:defabb7fbb99f9f7b3e0b24b286a46855caef4776495211b066e9e6592d12b04",
+                "sha256:e2629cdbcad82b83922a3488937632a4983ecc0fed3e5cfbf430d069382eeb9b"
+            ],
+            "index": "pypi",
+            "version": "==4.2.1"
+        },
+        "requests": {
+            "hashes": [
+                "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+                "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+            ],
+            "index": "pypi",
+            "version": "==2.18.4"
+        },
+        "urllib3": {
+            "hashes": [
+                "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+                "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+            ],
+            "version": "==1.22"
+        }
+    },
+    "develop": {}
+}

+ 60 - 0
app.js

@@ -0,0 +1,60 @@
+Number.prototype.currency = function() { return '$' + this.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') };
+
+
+function log() {
+    console.log('LOG >>>', arguments);
+}
+
+function get_items() {
+    var xhr = new XMLHttpRequest();
+    xhr.onload = function() {
+        var data = {};
+        try {
+            data = JSON.parse(xhr.responseText);
+        } catch(e){
+            log('could not parse JSON');
+        }
+        app.items = data;
+    };
+    xhr.open('GET', 'db.json', true);
+    try {
+        xhr.send();
+    } catch(e) {
+        log('err', e);
+    }
+}
+
+var app = new Vue({
+    el: '#app',
+    data: {
+        title: "egunner",
+        items: {},
+        debug: false
+    },
+
+    mounted: function () {
+        // hide splash
+        var splash = document.getElementById("splash");
+        splash.style.display = "none";
+        
+        // unhide main container after mount
+        this.$el.style.display = "block";
+    },
+    computed: {
+    },
+    
+    methods: {
+    },
+    
+    watch: {
+    },
+    
+});
+
+
+get_items();
+
+window.setInterval(function(){
+    console.log('refresh');
+    get_items();
+}, 5000);

+ 64 - 0
db.json

@@ -0,0 +1,64 @@
+{
+    "Last update": {
+        "url": null, 
+        "price": null, 
+        "thumb": null, 
+        "desc": "2019-02-11 09:00:02.289679"
+    }, 
+    "Schaft f\u00fcr Ruger Gunsite Scout Rifle": {
+        "url": "http://egun.de/market/item.php?id=7337107", 
+        "remaining": "26 Tage", 
+        "price": 69.0, 
+        "thumb": "http://www.egun.de/market/images/picture.gif", 
+        "desc": "Schaft f\u00fcr Ruger Gunsite Scout Rifle"
+    }, 
+    "Mossberg MVP Patrol .223Rem. 16\" Lauf 10 RD Mag.Neuwaffe": {
+        "url": "http://egun.de/market/item.php?id=7312600", 
+        "remaining": "12 Tage", 
+        "price": 819.0, 
+        "thumb": "http://www.egun.de/market/images/picture.gif", 
+        "desc": "Mossberg MVP Patrol .223Rem. 16\" Lauf 10 RD Mag.Neuwaffe"
+    }, 
+    "Accuracy International Chassis System (AICS-AX 2.0) FDE Remington 700 SA .308 Repetierb\u00fcchsen": {
+        "url": "http://egun.de/market/item.php?id=7020521", 
+        "remaining": "14 Tage", 
+        "price": 1448.0, 
+        "thumb": "http://www.egun.de/market/images/picture.gif", 
+        "desc": "Accuracy International Chassis System (AICS-AX 2.0) FDE Remington 700 SA .308 Repetierb\u00fcchsen"
+    }, 
+    "Rep.B\u00fcchse .223Rem Mossberg MVP Patrol TAN 16,25\" Lauf/ MFD/ M\u00fcndungsgewinde 1/2-28/ AR-15 Magazin": {
+        "url": "http://egun.de/market/item.php?id=7234684", 
+        "remaining": "20 Tage", 
+        "price": 979.0, 
+        "thumb": "http://egun.de/market/cache/aucimg/64x64/1.7234684.1225321523.jpg", 
+        "desc": "Rep.B\u00fcchse .223Rem Mossberg MVP Patrol TAN 16,25\" Lauf/ MFD/ M\u00fcndungsgewinde 1/2-28/ AR-15 Magazin"
+    }, 
+    "Remington 700 AAC-SD Repetierb\u00fcchse 308 win": {
+        "url": "http://egun.de/market/item.php?id=7228926", 
+        "remaining": "5 Tage", 
+        "price": 699.0, 
+        "thumb": "http://www.egun.de/market/images/picture.gif", 
+        "desc": "Remington 700 AAC-SD Repetierb\u00fcchse 308 win"
+    }, 
+    "Rep.B\u00fcchse .308Win Ruger Gunsite Scout 16,1\" Lauf/ M\u00fcndungsfeuerd\u00e4mpfer (5/8-24)/ Schichtholzschaft": {
+        "url": "http://egun.de/market/item.php?id=6935206", 
+        "remaining": "3 Tage", 
+        "price": 1399.0, 
+        "thumb": "http://egun.de/market/cache/aucimg/64x64/1.6935206.608219153.jpg", 
+        "desc": "Rep.B\u00fcchse .308Win Ruger Gunsite Scout 16,1\" Lauf/ M\u00fcndungsfeuerd\u00e4mpfer (5/8-24)/ Schichtholzschaft"
+    }, 
+    "Remington 700 AAC-SD mit 16,5\" Lauf .300 Blackout und Hausken JD184 Schalld\u00e4mpfer": {
+        "url": "http://egun.de/market/item.php?id=7166449", 
+        "remaining": "13 Tage", 
+        "price": 1799.0, 
+        "thumb": "http://egun.de/market/cache/aucimg/64x64/5.7166449.1389141865.jpg", 
+        "desc": "Remington 700 AAC-SD mit 16,5\" Lauf .300 Blackout und Hausken JD184 Schalld\u00e4mpfer"
+    }, 
+    "Mossberg MVP Patrol .308win 16\" Lauf 10 RD Mag.Neuwaffe": {
+        "url": "http://egun.de/market/item.php?id=7312591", 
+        "remaining": "12 Tage", 
+        "price": 819.0, 
+        "thumb": "http://www.egun.de/market/images/picture.gif", 
+        "desc": "Mossberg MVP Patrol .308win 16\" Lauf 10 RD Mag.Neuwaffe"
+    }
+}

BIN
icon.png


+ 83 - 0
index.html

@@ -0,0 +1,83 @@
+<!doctype html>
+<head>
+  <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+  <meta content="utf-8" http-equiv="encoding">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta name="mobile-web-app-capable" content="yes">
+  <meta name="theme-color" content="#dddddd">
+  <link rel="icon" sizes="128x128" href="icon.png">
+  
+  <style>
+    * {
+      margin: 0;
+      padding: 0;
+    }
+    #splash {
+      background-color: rgb(61, 61, 61);
+      color: rgb(207, 207, 207);
+      padding: 10%;
+      margin: 0%;
+      font-size: 4em;
+      font-weight: bolder;
+      padding-bottom: 200%;
+      height: 100%;
+      font-family: Arial, Helvetica, sans-serif;
+    }
+  </style>
+</head>
+
+
+<body>
+  <div id="splash">
+    loading
+  </div>
+  
+  
+  <div id="app" style="display: none">
+    <nav>
+      <!-- <img class="brand" src="icon-white.png"> -->
+      <div class="logo">{{title}}</div>
+      <template v-for="item in items" v-if="item.price == null">
+        <div style="font-size:0.6em; margin-left:70%;">
+          Updated: {{item.desc}}
+        </div>    
+      </template>
+      
+    </nav>
+    
+    
+    <div class="content">
+      
+      
+      <template v-for="item in items" v-if="item.price != null">
+        <div class="panel">
+          <div class="grid-auto">
+            <div >
+              <img :src="item.thumb" style="vertical-align:middle;">
+            </div>
+            <div><a :href="item.url">{{item.desc}}</a></div>
+            <div>
+              <div class="badge">{{item.price}} EUR</div>
+            </div>
+            <div>Noch {{item.remaining}}</div>
+          </div>
+        </div>
+      </template>
+      
+      
+      <!-- {{articles}} -->
+      
+    </div> 
+  </div>
+</body>
+
+
+<script defer src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.min.js"></script>
+<link rel="stylesheet" href="https://rawgit.com/woelper/lilac/master/lilac.min.css">
+<script defer src="app.js"></script>
+
+<style>
+  :root {
+    --main-color: #2e442f;
+  }
+</style>

+ 10 - 0
urls.json

@@ -0,0 +1,10 @@
+[
+    "http://www.egun.de/market/list_items.php?mode=qry&query=m1a&plusdescr=off&wheremode=and&ewb=1&status=&minprice=&maxprice=1900&type=0&nick=&country_id=&zip=&int=0&order=ends&asdes=asc",
+    "http://www.egun.de/market/list_items.php?mode=qry&plusdescr=off&wheremode=and&query=remington+aac&quick=1",
+    "http://www.egun.de/market/list_items.php?mode=qry&query=ruger+scout&plusdescr=off&wheremode=and&ewb=1&status=&minprice=&maxprice=&type=0&nick=&country_id=&zip=&int=0&order=ends&asdes=asc",
+    "http://www.egun.de/market/list_items.php?mode=qry&query=aics&plusdescr=off&wheremode=and&ewb=&status=&minprice=200&maxprice=&type=0&nick=&country_id=&zip=&int=0&order=ends&asdes=asc",
+    "http://www.egun.de/market/list_items.php?mode=qry&plusdescr=off&wheremode=and&query=mossberg+patrol&quick=1",
+    "http://www.egun.de/market/list_items.php?mode=qry&query=smith+wesson+r8&plusdescr=off&wheremode=and&ewb=1&status=&minprice=&maxprice=&type=0&nick=&country_id=&zip=&int=0&order=ends&asdes=asc",
+    "http://www.egun.de/market/list_items.php?mode=qry&query=m305&plusdescr=off&wheremode=and&ewb=1&status=&minprice=&maxprice=&type=0&nick=&country_id=&zip=&int=0&order=ends&asdes=asc",
+    "http://www.egun.de/market/list_items.php?mode=qry&plusdescr=off&wheremode=and&maxprice=2000&query=m14+luxdef&quick=1"
+]

+ 89 - 0
watcher.py

@@ -0,0 +1,89 @@
+import requests
+import os
+import json
+from lxml import html, etree
+import datetime
+
+# TODO output price, url image
+
+class Retriever(object):
+    def __init__(self):
+        self.urls = []
+        self.urlfile = os.path.join(os.path.dirname(__file__), 'urls.json')
+        self.dbfile = os.path.join(os.path.dirname(__file__), 'db.json')
+        self.item_kw = 'item.php?'
+        self.base_url = 'http://egun.de/market/'
+        self.json_out = {}
+        self.load_urls()
+        self.scrape()
+        self.dump()
+
+    def load_urls(self):
+        with open(self.urlfile) as f:
+            self.urls = json.load(f)
+
+    def dump(self):
+        with open(self.dbfile, 'w') as f:
+            json.dump(self.json_out, f, indent=4)
+
+
+
+    def scrape(self):
+
+        self.json_out['Last update'] = {'thumb': None, 'desc': str(datetime.datetime.now()), 'price': None, 'url': None}
+        
+        for url in self.urls:
+
+
+            r = requests.get(url)
+            tree = html.fromstring(r.content)
+
+            for element in tree:
+                for e in element.iter():
+                    if e.tag == 'tr' and 'bgcolor' in e.attrib:
+                        if e.attrib['bgcolor'] == '#FFFFFF' or e.attrib['bgcolor'] == '#EBEBEB':
+                            # we are now in a category
+                            
+                            _thumb = 'http://www.egun.de/market/images/picture.gif'
+                            _desc = ''
+                            _url = ''
+                            _price = 0
+
+                            # get thumb
+                            for thumb in e.iter('img'):
+                                if thumb.attrib['alt'] == 'Thumbnail':
+                                    _thumb = self.base_url + thumb.attrib['src']
+                            
+
+                            # get link
+                            for link in e.iter('a'):
+                                _url = self.base_url + link.attrib['href']
+                                for t in link.iter():
+                                    if t.text is not None:
+                                        _desc = t.text
+                                            
+                            # get price
+                            for cell in e.iter('td'):
+                                if cell.text is not None:
+                                    if 'EUR' in cell.text:
+                                        try:
+                                            p = ''.join(cell.text.split('EUR')[0].split())
+                                            # clean currency
+                                            p = p.replace('.','')
+                                            p = p.replace(',','.')
+                                            p = float(p)
+                                            _price = p
+                                        except:
+                                            pass
+
+                            cells = []
+                            for cell in e.iter('td'):
+                                if cell.text is not None and cell.text != '':
+                                    cells.append(cell.text)
+          
+
+                            self.json_out[_desc] = {'thumb': _thumb, 'desc': _desc, 'price': _price, 'url': _url, 'remaining': cells[-1]}
+
+
+
+r = Retriever()