mirror of
https://github.com/netzbegruenung/green-spider.git
synced 2024-05-13 22:16:08 +02:00
Add dryrun target to spider a URL without storing results
This commit is contained in:
parent
d3d3e05a1d
commit
ce8a440d72
15
Makefile
15
Makefile
|
@ -4,7 +4,7 @@ DB_ENTITY := spider-results
|
|||
|
||||
VERSION = $(shell git describe --exact-match --tags 2> /dev/null || git rev-parse HEAD)
|
||||
|
||||
.PHONY: dockerimage spider export
|
||||
.PHONY: dockerimage spider export dryrun test
|
||||
|
||||
# Build docker image
|
||||
dockerimage: VERSION
|
||||
|
@ -18,6 +18,19 @@ jobs:
|
|||
docker compose up manager
|
||||
venv/bin/rq info
|
||||
|
||||
# Spider a single URL and inspect the result
|
||||
dryrun:
|
||||
docker run --rm -ti \
|
||||
-v $(PWD)/volumes/dev-shm:/dev/shm \
|
||||
-v $(PWD)/secrets:/secrets \
|
||||
-v $(PWD)/volumes/chrome-userdir:/opt/chrome-userdir \
|
||||
--shm-size=2g \
|
||||
$(IMAGE) \
|
||||
python3 cli.py \
|
||||
--credentials-path /secrets/datastore-writer.json \
|
||||
--loglevel debug \
|
||||
dryrun ${ARGS}
|
||||
|
||||
# Run the spider.
|
||||
# OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES is a workaround for mac OS.
|
||||
spider:
|
||||
|
|
47
README.md
47
README.md
|
@ -25,53 +25,36 @@ Alle Informationen zum Betrieb befinden sich im Verzeichnis [devops](https://git
|
|||
|
||||
## Entwicklung
|
||||
|
||||
Green Spider ist in Python 3 geschrieben und wird aktuell unter 3.6 getestet und ausgeführt.
|
||||
Green Spider ist in Python geschrieben. Der Code ist darauf ausgelegt, in einem Docker Container ausführbar zu sein. Darüber hinaus _kann_ er möglicherweise in einer lokalen Python-Umgebung funktionieren. Für reproduzierbare Bedingungen beim Ausführen des headless Browsers (chromium, chromedriver) empfielt es sich jedoch, in einer Container-Umgebung zu testen.
|
||||
|
||||
Aufgrund zahlreicher Abhängigkeiten empfiehlt es sich, den Spider Code lokal in Docker
|
||||
auszuführen.
|
||||
Das aktuellste Container Image steht unter `ghcr.io/netzbegruenung/green-spider:latest` zur Verfügung. Alternative Versionen und Tags sind unter [Packages](https://github.com/netzbegruenung/green-spider/pkgs/container/green-spider) auffindbar.
|
||||
|
||||
Das Image wird über den folgenden Befehl erzeugt:
|
||||
Lokal kann das Image mit diesem Befehl gebaut werden:
|
||||
|
||||
```nohighlight
|
||||
make
|
||||
make dockerimage
|
||||
```
|
||||
|
||||
Das dauert beim ersten Ausführen einige Zeit, wiel einige Python-Module das Kompilieren diverser Libraries erfordern.
|
||||
Nach dem ersten erfolgreichen Durchlauf dauert ein neuer Aufruf von `make` nur noch wenige Sekunden.
|
||||
### Unittests ausführen
|
||||
|
||||
### Tests ausführen
|
||||
|
||||
In aller Kürze: `make test`
|
||||
Nach dem Bauen des Container Image (siehe oben) werden die Unit Tests im Container über `make test` ausgeführt.
|
||||
|
||||
### Spider testweise ausführen (Debugging)
|
||||
|
||||
Der Spider kann einzelne URLs verarbeiten, ohne die Ergebnisse in eine Datenbank zu schreiben.
|
||||
Am einfachsten geht das über den `make spider` Befehl, so:
|
||||
Am einfachsten geht das über den `make dryrun` Befehl, so:
|
||||
|
||||
```nohighlight
|
||||
make spider ARGS="--url http://www.example.com/"
|
||||
make dryrun ARGS="http://www.example.com/"
|
||||
```
|
||||
|
||||
Wenn nur eine einzelne Site gespidert werden soll, die Ergebnisse aber in die Datenbank geschrieben werden sollen, kann der Spider so mit `--job` und einem JSON-Object aufgerufen werden (Beispiel):
|
||||
### Warteschlange und Worker
|
||||
|
||||
Für einen kompletten Durchlauf wird die Warteschlange gefüllt und dann abgearbeitet. Das passiert im Betrieb über das Script [devops/run-job.sh](https://github.com/netzbegruenung/green-spider/blob/main/devops/run-job.sh).
|
||||
|
||||
Lokal kann das über die folgenden Befehle getestet werden:
|
||||
|
||||
```nohighlight
|
||||
docker run --rm -ti \
|
||||
-v $(pwd)/volumes/dev-shm:/dev/shm \
|
||||
-v $(pwd)/secrets:/secrets \
|
||||
-v $(pwd)/screenshots:/screenshots \
|
||||
-v $(pwd)/volumes/chrome-userdir:/opt/chrome-userdir \
|
||||
--shm-size=2g \
|
||||
ghcr.io/netzbegruenung/green-spider:latest python3 cli.py \
|
||||
--credentials-path /secrets/datastore-writer.json \
|
||||
--loglevel debug \
|
||||
spider --job '{"url": "https://gruene-porta-westfalica.de/home/", "city": "Porta Westfalica", "country": "DE", "district": "Minden-Lübbecke", "level": "DE:ORTSVERBAND", "state":" Nordrhein-Westfalen", "type": "REGIONAL_CHAPTER"}'
|
||||
```
|
||||
|
||||
Wenn Jobs in der rq Warteschlange vorliegen, kann der Spider auch durch Starten eines rq workers mit diesem Kommando angestoßen werden:
|
||||
|
||||
```shell
|
||||
# Unter mac OS evtl benötigt:
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
|
||||
rq worker --verbose --burst high default low
|
||||
make jobs
|
||||
make spider
|
||||
```
|
||||
|
|
13
cli.py
13
cli.py
|
@ -33,6 +33,10 @@ if __name__ == "__main__":
|
|||
|
||||
# subcommands
|
||||
subparsers = parser.add_subparsers(help='sub-command help', dest='command')
|
||||
|
||||
# 'dryrun' subcommand to spider one URL without writing results back.
|
||||
dryrun_parser = subparsers.add_parser('dryrun', help='Spider an arbitrary URL without storing results. ')
|
||||
dryrun_parser.add_argument('url', help='Spider a URL instead of using jobs from the queue. For testing/debugging only.')
|
||||
|
||||
# manager subcommand
|
||||
manager_parser = subparsers.add_parser('manager', help='Adds spider jobs to the queue. By default, all green-directory URLs are added.')
|
||||
|
@ -63,16 +67,21 @@ if __name__ == "__main__":
|
|||
logging.debug("Called command %s", args.command)
|
||||
|
||||
if args.command == 'manager':
|
||||
|
||||
import manager
|
||||
manager.create_jobs(args.url)
|
||||
|
||||
elif args.command == 'export':
|
||||
|
||||
import export
|
||||
datastore_client = datastore.Client.from_service_account_json(args.credentials_path)
|
||||
export.export_results(datastore_client, args.kind)
|
||||
|
||||
elif args.command == 'dryrun':
|
||||
from spider import spider
|
||||
from export.datetimeencoder import DateTimeEncoder
|
||||
|
||||
result = spider.check_and_rate_site({"url": args.url, "type": "REGIONAL_CHAPTER", "level": "DE:KREISVERBAND", "state": "Unnamed", "district": "Unnamed"})
|
||||
print(json.dumps(result, indent=2, sort_keys=True, ensure_ascii=False, cls=DateTimeEncoder))
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
|
|
@ -11,17 +11,7 @@ from hashlib import md5
|
|||
import json
|
||||
import requests
|
||||
|
||||
|
||||
class DateTimeEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, datetime.date):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, datetime.timedelta):
|
||||
return (datetime.datetime.min + obj).time().isoformat()
|
||||
else:
|
||||
return super(DateTimeEncoder, self).default(obj)
|
||||
from export import datetimeencoder
|
||||
|
||||
def export_results(client, entity_kind):
|
||||
"""
|
||||
|
@ -45,4 +35,4 @@ def export_results(client, entity_kind):
|
|||
|
||||
output_filename = "/json-export/spider_result.json"
|
||||
with open(output_filename, 'w', encoding="utf8") as jsonfile:
|
||||
json.dump(out, jsonfile, indent=2, sort_keys=True, ensure_ascii=False, cls=DateTimeEncoder)
|
||||
json.dump(out, jsonfile, indent=2, sort_keys=True, ensure_ascii=False, cls=datetimeencoder.DateTimeEncoder)
|
||||
|
|
13
export/datetimeencoder.py
Normal file
13
export/datetimeencoder.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import json
|
||||
import datetime
|
||||
|
||||
class DateTimeEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, datetime.date):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, datetime.timedelta):
|
||||
return (datetime.datetime.min + obj).time().isoformat()
|
||||
else:
|
||||
return super(DateTimeEncoder, self).default(obj)
|
Loading…
Reference in a new issue