add specific follow of translation pages
This commit is contained in:
parent
7a7704bc01
commit
bd3d14e9f8
11 changed files with 48190 additions and 268240 deletions
File diff suppressed because it is too large
Load diff
|
@ -920,11 +920,22 @@ class WikiController extends AbstractController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load specific pages from outdated_pages.json
|
||||||
|
$specificPages = [];
|
||||||
|
$outdatedPagesFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/outdated_pages.json';
|
||||||
|
if (file_exists($outdatedPagesFile)) {
|
||||||
|
$outdatedPagesData = json_decode(file_get_contents($outdatedPagesFile), true);
|
||||||
|
if (isset($outdatedPagesData['specific_pages']) && is_array($outdatedPagesData['specific_pages'])) {
|
||||||
|
$specificPages = $outdatedPagesData['specific_pages'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $this->render('admin/wiki.html.twig', [
|
return $this->render('admin/wiki.html.twig', [
|
||||||
'wiki_pages' => $wikiPages,
|
'wiki_pages' => $wikiPages,
|
||||||
'missing_translations' => $missingTranslations,
|
'missing_translations' => $missingTranslations,
|
||||||
'page_differences' => $pageDifferences,
|
'page_differences' => $pageDifferences,
|
||||||
'pages_unavailable_in_english' => $pagesUnavailableInEnglish,
|
'pages_unavailable_in_english' => $pagesUnavailableInEnglish,
|
||||||
|
'specific_pages' => $specificPages,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<img src="{{ languages['en'].description_img_url }}" alt="image" style="height: 2rem;">
|
<img src="{{ languages['en'].description_img_url }}" alt="image"
|
||||||
|
style="height: 2rem;">
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -152,11 +153,11 @@
|
||||||
class="btn btn-sm btn-outline-info" title="Version anglaise">
|
class="btn btn-sm btn-outline-info" title="Version anglaise">
|
||||||
<i class="bi bi-flag-fill"></i> EN
|
<i class="bi bi-flag-fill"></i> EN
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ path('app_admin_wiki_create_french', {'key': key}) }}"
|
{# <a href="{{ path('app_admin_wiki_create_french', {'key': key}) }}" #}
|
||||||
class="btn btn-sm btn-outline-primary"
|
{# class="btn btn-sm btn-outline-primary" #}
|
||||||
title="Créer une traduction française">
|
{# title="Créer une traduction française"> #}
|
||||||
<i class="bi bi-translate"></i> créer FR
|
{# <i class="bi bi-translate"></i> créer FR #}
|
||||||
</a>
|
{# </a> #}
|
||||||
{# <a href="{{ path('app_admin_wiki_compare', {'key': key}) }}" #}
|
{# <a href="{{ path('app_admin_wiki_compare', {'key': key}) }}" #}
|
||||||
{# class="btn btn-sm btn-outline-secondary" #}
|
{# class="btn btn-sm btn-outline-secondary" #}
|
||||||
{# title="Voir les détails et créer la page française"> #}
|
{# title="Voir les détails et créer la page française"> #}
|
||||||
|
@ -173,6 +174,86 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if specific_pages is defined and specific_pages|length > 0 %}
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header bg-primary text-white">
|
||||||
|
<h2>Pages spécifiques ({{ specific_pages|length }})</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>Ces pages wiki sont des pages spécifiques qui ont été sélectionnées pour une comparaison particulière.</p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead class="thead-dark">
|
||||||
|
<tr>
|
||||||
|
<th>Titre</th>
|
||||||
|
<th>Raison</th>
|
||||||
|
<th>Score de décrépitude</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for page in specific_pages %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
{% if page.en_page.description_img_url is defined and page.en_page.description_img_url %}
|
||||||
|
<div class="me-3">
|
||||||
|
<img src="{{ page.en_page.description_img_url }}" alt="{{ page.key }}"
|
||||||
|
style="max-width: 80px; max-height: 60px; object-fit: contain;">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
<strong>{{ page.key }}</strong>
|
||||||
|
<span class="badge bg-primary">Spécifique</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ page.reason }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if page.staleness_score is defined %}
|
||||||
|
<div class="progress" style="height: 20px;">
|
||||||
|
{% set score_class = page.staleness_score > 70 ? 'bg-danger' : (page.staleness_score > 40 ? 'bg-warning' : 'bg-success') %}
|
||||||
|
<div class="progress-bar {{ score_class }}" role="progressbar"
|
||||||
|
style="width: {{ page.staleness_score }}%;"
|
||||||
|
aria-valuenow="{{ page.staleness_score }}"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax="100">
|
||||||
|
{{ page.staleness_score }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">Non disponible</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<a href="{{ page.en_page.url }}" target="_blank"
|
||||||
|
class="btn btn-sm btn-outline-primary" title="Version anglaise">
|
||||||
|
<i class="bi bi-translate"></i> EN
|
||||||
|
</a>
|
||||||
|
{% if page.fr_page %}
|
||||||
|
<a href="{{ page.fr_page.url }}" target="_blank"
|
||||||
|
class="btn btn-sm btn-outline-info" title="Version française">
|
||||||
|
<i class="bi bi-translate"></i> FR
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<a href="{{ path('app_admin_wiki_compare', {'key': page.key}) }}"
|
||||||
|
class="btn btn-sm btn-outline-secondary" title="Comparer les versions">
|
||||||
|
<i class="bi bi-arrows-angle-expand"></i> Comparer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if pages_unavailable_in_english|length > 0 %}
|
{% if pages_unavailable_in_english|length > 0 %}
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header bg-info text-dark">
|
<div class="card-header bg-info text-dark">
|
||||||
|
|
|
@ -59,10 +59,21 @@
|
||||||
|
|
||||||
<h1>Comparaison Wiki OpenStreetMap - {{ key }}
|
<h1>Comparaison Wiki OpenStreetMap - {{ key }}
|
||||||
|
|
||||||
<a href="https://wiki.openstreetmap.org/FR:Key:{{ key }}">fr</a>
|
{% if en_page.is_specific_page is defined and en_page.is_specific_page %}
|
||||||
<a href="https://wiki.openstreetmap.org/Key:{{ key }}">en</a>
|
<a href="{{ fr_page.url|default('https://wiki.openstreetmap.org/wiki/FR:' ~ key) }}">fr</a>
|
||||||
|
<a href="{{ en_page.url }}">en</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="https://wiki.openstreetmap.org/wiki/FR:Key:{{ key }}">fr</a>
|
||||||
|
<a href="https://wiki.openstreetmap.org/wiki/Key:{{ key }}">en</a>
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="lead">Comparaison détaillée des pages wiki en français et en anglais pour la clé OSM "{{ key }}".</p>
|
<p class="lead">
|
||||||
|
{% if en_page.is_specific_page is defined and en_page.is_specific_page %}
|
||||||
|
Comparaison détaillée des pages wiki en français et en anglais pour "{{ key }}".
|
||||||
|
{% else %}
|
||||||
|
Comparaison détaillée des pages wiki en français et en anglais pour la clé OSM "{{ key }}".
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
|
@ -1,51 +1,3 @@
|
||||||
# In all environments, the following files are loaded if they exist,
|
|
||||||
# the latter taking precedence over the former:
|
|
||||||
#
|
|
||||||
# * .env contains default values for the environment variables needed by the app
|
|
||||||
# * .env.local uncommitted file with local overrides
|
|
||||||
# * .env.$APP_ENV committed environment-specific defaults
|
|
||||||
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
|
||||||
#
|
|
||||||
# Real environment variables win over .env files.
|
|
||||||
#
|
|
||||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
|
||||||
# https://symfony.com/doc/current/configuration/secrets.html
|
|
||||||
#
|
|
||||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
|
||||||
|
|
||||||
###> symfony/framework-bundle ###
|
|
||||||
APP_ENV=dev
|
|
||||||
APP_SECRET=e9f84197a6d65c818076bb1d42e40124
|
|
||||||
###< symfony/framework-bundle ###
|
|
||||||
|
|
||||||
###> doctrine/doctrine-bundle ###
|
|
||||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
|
||||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
|
||||||
#
|
|
||||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db"
|
|
||||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
|
||||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
|
||||||
#DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
|
|
||||||
DATABASE_URL="postgresql://sf:jkazhreiidfsDFgfgsgFHGSshdffdshefJYIyl@127.0.0.1:5432/osm-my-commerce?serverVersion=15&charset=utf8"
|
|
||||||
###< doctrine/doctrine-bundle ###
|
|
||||||
|
|
||||||
###> symfony/messenger ###
|
|
||||||
# Choose one of the transports below
|
|
||||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
|
||||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
|
||||||
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
|
||||||
###< symfony/messenger ###
|
|
||||||
|
|
||||||
###> symfony/mailer ###
|
|
||||||
MAILER_DSN=null://null
|
|
||||||
###< symfony/mailer ###
|
|
||||||
#DEBUG=0
|
|
||||||
|
|
||||||
APP_OSM_BEARER=vowhiYkTFwbaXIW2eJ1fgzdojrzjKn2x3Mi4XAsRCFY
|
|
||||||
MAPBOX_TOKEN=BVM2NRJuzQunWvXbTnzg
|
|
||||||
MAPTILER_TOKEN=BVM2NRJuzQunWvXbTnzg
|
|
||||||
USE_PLACES_WITHOUT_EMAIL_TO_REFERENCE=true
|
|
||||||
TOKEN_CURATOR=dxUWpE_SrSc6oGinPjMt2n9rh4F463LEelqNEqPNDf8
|
TOKEN_CURATOR=dxUWpE_SrSc6oGinPjMt2n9rh4F463LEelqNEqPNDf8
|
||||||
MASTODON_ACCESS_TOKEN=dxUWpE_SrSc6oGinPjMt2n9rh4F463LEelqNEqPNDf8
|
MASTODON_ACCESS_TOKEN=dxUWpE_SrSc6oGinPjMt2n9rh4F463LEelqNEqPNDf8
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 43 KiB |
|
@ -2,401 +2,5 @@
|
||||||
{
|
{
|
||||||
"key": "building",
|
"key": "building",
|
||||||
"count": 657147429
|
"count": 657147429
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "source",
|
|
||||||
"count": 299885925
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "highway",
|
|
||||||
"count": 280633683
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:housenumber",
|
|
||||||
"count": 172160903
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:street",
|
|
||||||
"count": 161005721
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:city",
|
|
||||||
"count": 123355107
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "name",
|
|
||||||
"count": 109342549
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:postcode",
|
|
||||||
"count": 107014659
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "natural",
|
|
||||||
"count": 84723029
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "surface",
|
|
||||||
"count": 72309071
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:country",
|
|
||||||
"count": 50567842
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "landuse",
|
|
||||||
"count": 48196369
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "power",
|
|
||||||
"count": 44787307
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "waterway",
|
|
||||||
"count": 37279458
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "building:levels",
|
|
||||||
"count": 36502866
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "amenity",
|
|
||||||
"count": 30994353
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "barrier",
|
|
||||||
"count": 30164354
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "source:date",
|
|
||||||
"count": 29112775
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "service",
|
|
||||||
"count": 28396250
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:state",
|
|
||||||
"count": 25367076
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "access",
|
|
||||||
"count": 24253880
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "oneway",
|
|
||||||
"count": 24142755
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "height",
|
|
||||||
"count": 22751656
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ref",
|
|
||||||
"count": 21377968
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "maxspeed",
|
|
||||||
"count": 20638084
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "lanes",
|
|
||||||
"count": 18474748
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "start_date",
|
|
||||||
"count": 17811278
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:district",
|
|
||||||
"count": 16225592
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "layer",
|
|
||||||
"count": 14701214
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "type",
|
|
||||||
"count": 13779491
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "operator",
|
|
||||||
"count": 13564477
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "lit",
|
|
||||||
"count": 13470867
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "wall",
|
|
||||||
"count": 12772569
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:cfcc",
|
|
||||||
"count": 12591947
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "crossing",
|
|
||||||
"count": 12576456
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:county",
|
|
||||||
"count": 12487373
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "source:addr",
|
|
||||||
"count": 12411407
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "footway",
|
|
||||||
"count": 11543209
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ref:bag",
|
|
||||||
"count": 11343897
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:place",
|
|
||||||
"count": 11140176
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:reviewed",
|
|
||||||
"count": 10786509
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "leisure",
|
|
||||||
"count": 10683374
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:suburb",
|
|
||||||
"count": 10316819
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ele",
|
|
||||||
"count": 10277000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tracktype",
|
|
||||||
"count": 10162446
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:neighbourhood",
|
|
||||||
"count": 10133392
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:hamlet",
|
|
||||||
"count": 9972809
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:province",
|
|
||||||
"count": 9667541
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "leaf_type",
|
|
||||||
"count": 9558990
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:full",
|
|
||||||
"count": 9434269
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:TW:dataset",
|
|
||||||
"count": 9075532
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "place",
|
|
||||||
"count": 8936497
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "man_made",
|
|
||||||
"count": 8797198
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "bicycle",
|
|
||||||
"count": 8713608
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "roof:shape",
|
|
||||||
"count": 8573805
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:name_base",
|
|
||||||
"count": 8202148
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "foot",
|
|
||||||
"count": 8038433
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "railway",
|
|
||||||
"count": 7913244
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "source:geometry:date",
|
|
||||||
"count": 7582317
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "crossing:markings",
|
|
||||||
"count": 7549311
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:name_type",
|
|
||||||
"count": 7128421
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "bridge",
|
|
||||||
"count": 6955443
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "name:en",
|
|
||||||
"count": 6938352
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "intermittent",
|
|
||||||
"count": 6717574
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "shop",
|
|
||||||
"count": 6689843
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "source:geometry",
|
|
||||||
"count": 6684317
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "public_transport",
|
|
||||||
"count": 6010927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "smoothness",
|
|
||||||
"count": 5994463
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "leaf_cycle",
|
|
||||||
"count": 5460911
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tunnel",
|
|
||||||
"count": 5416244
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "generator:source",
|
|
||||||
"count": 5371810
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "generator:method",
|
|
||||||
"count": 5260428
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "material",
|
|
||||||
"count": 5236617
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "generator:type",
|
|
||||||
"count": 5164641
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tactile_paving",
|
|
||||||
"count": 5078435
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "water",
|
|
||||||
"count": 5044316
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "generator:output:electricity",
|
|
||||||
"count": 5015616
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:city:simc",
|
|
||||||
"count": 4809200
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "entrance",
|
|
||||||
"count": 4730489
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "created_by",
|
|
||||||
"count": 4679471
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "roof:levels",
|
|
||||||
"count": 4619732
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "bus",
|
|
||||||
"count": 4597154
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:floor",
|
|
||||||
"count": 4577753
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "sidewalk",
|
|
||||||
"count": 4405491
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "attribution",
|
|
||||||
"count": 4379869
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "nysgissam:nysaddresspointid",
|
|
||||||
"count": 4351509
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "operator:wikidata",
|
|
||||||
"count": 4283932
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "direction",
|
|
||||||
"count": 4277057
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "note",
|
|
||||||
"count": 4266829
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:conscriptionnumber",
|
|
||||||
"count": 4212397
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:zip_left",
|
|
||||||
"count": 4189091
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "opening_hours",
|
|
||||||
"count": 4165701
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "website",
|
|
||||||
"count": 4131842
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "parking",
|
|
||||||
"count": 4044624
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ref:bygningsnr",
|
|
||||||
"count": 3982182
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "addr:unit",
|
|
||||||
"count": 3942071
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "wikidata",
|
|
||||||
"count": 3867397
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tiger:zip_right",
|
|
||||||
"count": 3839962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ref:ruian:building",
|
|
||||||
"count": 3810878
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "tourism",
|
|
||||||
"count": 3748468
|
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -8,6 +8,10 @@ This script fetches the most used OpenStreetMap keys from TagInfo,
|
||||||
compares their English and French wiki pages, and identifies which pages
|
compares their English and French wiki pages, and identifies which pages
|
||||||
need updating based on modification dates and content analysis.
|
need updating based on modification dates and content analysis.
|
||||||
|
|
||||||
|
The script also compares a specific list of wiki pages defined in the
|
||||||
|
SPECIFIC_PAGES constant. This list can include regular page titles,
|
||||||
|
full URLs, or pages with FR: prefix.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
python wiki_compare.py
|
python wiki_compare.py
|
||||||
|
|
||||||
|
@ -15,6 +19,7 @@ Output:
|
||||||
- top_keys.json: JSON file containing the most used OSM keys
|
- top_keys.json: JSON file containing the most used OSM keys
|
||||||
- wiki_pages.csv: CSV file with information about each wiki page
|
- wiki_pages.csv: CSV file with information about each wiki page
|
||||||
- outdated_pages.json: JSON file containing pages that need updating
|
- outdated_pages.json: JSON file containing pages that need updating
|
||||||
|
- staleness_histogram.png: Histogram of staleness scores
|
||||||
- A console output listing the wiki pages that need updating
|
- A console output listing the wiki pages that need updating
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -47,14 +52,21 @@ WIKI_PAGES_CSV = "wiki_pages.csv"
|
||||||
OUTDATED_PAGES_FILE = "outdated_pages.json"
|
OUTDATED_PAGES_FILE = "outdated_pages.json"
|
||||||
STALENESS_HISTOGRAM_FILE = "staleness_histogram.png"
|
STALENESS_HISTOGRAM_FILE = "staleness_histogram.png"
|
||||||
# Number of wiki pages to examine
|
# Number of wiki pages to examine
|
||||||
NUM_WIKI_PAGES = 100
|
NUM_WIKI_PAGES = 1
|
||||||
|
|
||||||
# List of specific pages to compare
|
# List of specific pages to compare (in addition to top keys)
|
||||||
|
# This list can include:
|
||||||
|
# 1. Regular page titles (e.g., "Anatomie_des_étiquettes_osm")
|
||||||
|
# 2. Full URLs (e.g., "https://wiki.openstreetmap.org/wiki/FR:Projet_du_mois")
|
||||||
|
# 3. Pages with FR: prefix (e.g., "FR:Tag:leisure%3Dchildren_club")
|
||||||
SPECIFIC_PAGES = [
|
SPECIFIC_PAGES = [
|
||||||
"Anatomie_des_étiquettes_osm",
|
"Anatomie_des_étiquettes_osm",
|
||||||
"https://wiki.openstreetmap.org/wiki/FR:Projet_du_mois",
|
|
||||||
"FR:Tag:leisure%3Dchildren_club",
|
"FR:Tag:leisure%3Dchildren_club",
|
||||||
"FR:Tag:harassment_prevention%3Dask_angela"
|
"FR:Tag:harassment_prevention%3Dask_angela",
|
||||||
|
"Key:harassment_prevention",
|
||||||
|
"Proposal process",
|
||||||
|
"Automated_Edits_code_of_conduct",
|
||||||
|
"Key:cuisine"
|
||||||
]
|
]
|
||||||
|
|
||||||
def fetch_top_keys(limit=NUM_WIKI_PAGES):
|
def fetch_top_keys(limit=NUM_WIKI_PAGES):
|
||||||
|
@ -110,6 +122,13 @@ def fetch_wiki_page(key, language='en', is_specific_page=False):
|
||||||
"""
|
"""
|
||||||
Fetch wiki page for a given key or specific page
|
Fetch wiki page for a given key or specific page
|
||||||
|
|
||||||
|
This function handles different types of wiki pages:
|
||||||
|
1. Regular OSM key pages (e.g., "building", "highway")
|
||||||
|
2. Specific wiki pages that can be in various formats:
|
||||||
|
- Regular page titles (e.g., "Anatomie_des_étiquettes_osm")
|
||||||
|
- Full URLs (e.g., "https://wiki.openstreetmap.org/wiki/FR:Projet_du_mois")
|
||||||
|
- Pages with FR: prefix (e.g., "FR:Tag:leisure%3Dchildren_club")
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): OSM key or specific page title/URL
|
key (str): OSM key or specific page title/URL
|
||||||
language (str): Language code ('en' or 'fr')
|
language (str): Language code ('en' or 'fr')
|
||||||
|
@ -780,7 +799,18 @@ def analyze_wiki_pages(pages):
|
||||||
return needs_update
|
return needs_update
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function to execute the script"""
|
"""
|
||||||
|
Main function to execute the script
|
||||||
|
|
||||||
|
This function:
|
||||||
|
1. Fetches the top OSM keys from TagInfo API
|
||||||
|
2. Fetches and processes wiki pages for these keys
|
||||||
|
3. Processes specific wiki pages listed in SPECIFIC_PAGES
|
||||||
|
4. Calculates staleness scores for all pages
|
||||||
|
5. Generates a histogram of staleness scores
|
||||||
|
6. Saves the results to CSV and JSON files
|
||||||
|
7. Prints a list of pages that need updating
|
||||||
|
"""
|
||||||
logger.info("Starting wiki_compare.py")
|
logger.info("Starting wiki_compare.py")
|
||||||
|
|
||||||
# Create output directory if it doesn't exist
|
# Create output directory if it doesn't exist
|
||||||
|
@ -814,12 +844,13 @@ def main():
|
||||||
if fr_page:
|
if fr_page:
|
||||||
wiki_pages.append(fr_page)
|
wiki_pages.append(fr_page)
|
||||||
|
|
||||||
# Process specific pages
|
# Process specific pages from the SPECIFIC_PAGES list
|
||||||
|
# These are additional pages to compare beyond the top keys from TagInfo
|
||||||
logger.info("Processing specific pages...")
|
logger.info("Processing specific pages...")
|
||||||
for page in SPECIFIC_PAGES:
|
for page in SPECIFIC_PAGES:
|
||||||
# For specific pages, we need to handle different formats
|
# For specific pages, we need to handle different formats
|
||||||
|
|
||||||
# Case 1: Full URL
|
# Case 1: Full URL (e.g., "https://wiki.openstreetmap.org/wiki/FR:Projet_du_mois")
|
||||||
if page.startswith('http'):
|
if page.startswith('http'):
|
||||||
# For full URLs, we directly fetch the page
|
# For full URLs, we directly fetch the page
|
||||||
page_info = fetch_wiki_page(page, 'en', is_specific_page=True)
|
page_info = fetch_wiki_page(page, 'en', is_specific_page=True)
|
||||||
|
@ -831,6 +862,7 @@ def main():
|
||||||
# Try to get the English version by removing FR: prefix
|
# Try to get the English version by removing FR: prefix
|
||||||
en_title = page_info['page_title'].replace('FR:', '').replace('fr:', '')
|
en_title = page_info['page_title'].replace('FR:', '').replace('fr:', '')
|
||||||
en_url = f"{WIKI_BASE_URL}{en_title}"
|
en_url = f"{WIKI_BASE_URL}{en_title}"
|
||||||
|
logger.info(f"Trying to find English equivalent for {page}: {en_url}")
|
||||||
en_page = fetch_wiki_page(en_url, 'en', is_specific_page=True)
|
en_page = fetch_wiki_page(en_url, 'en', is_specific_page=True)
|
||||||
if en_page:
|
if en_page:
|
||||||
wiki_pages.append(en_page)
|
wiki_pages.append(en_page)
|
||||||
|
@ -839,11 +871,12 @@ def main():
|
||||||
# Try to get the French version by adding FR: prefix
|
# Try to get the French version by adding FR: prefix
|
||||||
fr_title = f"FR:{page_info['page_title']}"
|
fr_title = f"FR:{page_info['page_title']}"
|
||||||
fr_url = f"{WIKI_BASE_URL}{fr_title}"
|
fr_url = f"{WIKI_BASE_URL}{fr_title}"
|
||||||
|
logger.info(f"Trying to find French equivalent for {page}: {fr_url}")
|
||||||
fr_page = fetch_wiki_page(fr_url, 'fr', is_specific_page=True)
|
fr_page = fetch_wiki_page(fr_url, 'fr', is_specific_page=True)
|
||||||
if fr_page:
|
if fr_page:
|
||||||
wiki_pages.append(fr_page)
|
wiki_pages.append(fr_page)
|
||||||
|
|
||||||
# Case 2: Page with FR: prefix
|
# Case 2: Page with FR: prefix (e.g., "FR:Tag:leisure%3Dchildren_club")
|
||||||
elif page.startswith('FR:'):
|
elif page.startswith('FR:'):
|
||||||
# Fetch the French page
|
# Fetch the French page
|
||||||
fr_page = fetch_wiki_page(page, 'fr', is_specific_page=True)
|
fr_page = fetch_wiki_page(page, 'fr', is_specific_page=True)
|
||||||
|
@ -853,18 +886,19 @@ def main():
|
||||||
# Try to get the English version by removing FR: prefix
|
# Try to get the English version by removing FR: prefix
|
||||||
en_title = page[3:] # Remove FR: prefix
|
en_title = page[3:] # Remove FR: prefix
|
||||||
en_url = f"{WIKI_BASE_URL}{en_title}"
|
en_url = f"{WIKI_BASE_URL}{en_title}"
|
||||||
|
logger.info(f"Trying to find English equivalent for {page}: {en_url}")
|
||||||
en_page = fetch_wiki_page(en_url, 'en', is_specific_page=True)
|
en_page = fetch_wiki_page(en_url, 'en', is_specific_page=True)
|
||||||
if en_page:
|
if en_page:
|
||||||
wiki_pages.append(en_page)
|
wiki_pages.append(en_page)
|
||||||
|
|
||||||
# Case 3: Regular page title
|
# Case 3: Regular page title (e.g., "Anatomie_des_étiquettes_osm")
|
||||||
else:
|
else:
|
||||||
# Fetch the English page
|
# Fetch the English page
|
||||||
en_page = fetch_wiki_page(page, 'en', is_specific_page=True)
|
en_page = fetch_wiki_page(page, 'en', is_specific_page=True)
|
||||||
if en_page:
|
if en_page:
|
||||||
wiki_pages.append(en_page)
|
wiki_pages.append(en_page)
|
||||||
|
|
||||||
# Fetch the French page
|
# Fetch the French page (by adding FR: prefix)
|
||||||
fr_page = fetch_wiki_page(page, 'fr', is_specific_page=True)
|
fr_page = fetch_wiki_page(page, 'fr', is_specific_page=True)
|
||||||
if fr_page:
|
if fr_page:
|
||||||
wiki_pages.append(fr_page)
|
wiki_pages.append(fr_page)
|
||||||
|
@ -972,8 +1006,32 @@ def main():
|
||||||
# Analyze pages to find those needing updates
|
# Analyze pages to find those needing updates
|
||||||
pages_to_update = analyze_wiki_pages(wiki_pages)
|
pages_to_update = analyze_wiki_pages(wiki_pages)
|
||||||
|
|
||||||
|
# Separate regular pages and specific pages
|
||||||
|
regular_pages = []
|
||||||
|
specific_pages = []
|
||||||
|
|
||||||
|
for page in pages_to_update:
|
||||||
|
# Check if either English or French page is marked as specific
|
||||||
|
is_specific = False
|
||||||
|
if page['en_page'] and page['en_page'].get('is_specific_page', False):
|
||||||
|
is_specific = True
|
||||||
|
elif page['fr_page'] and page['fr_page'].get('is_specific_page', False):
|
||||||
|
is_specific = True
|
||||||
|
|
||||||
|
if is_specific:
|
||||||
|
specific_pages.append(page)
|
||||||
|
else:
|
||||||
|
regular_pages.append(page)
|
||||||
|
|
||||||
|
# Create a structured output with separate sections
|
||||||
|
output_data = {
|
||||||
|
"regular_pages": regular_pages,
|
||||||
|
"specific_pages": specific_pages,
|
||||||
|
"last_updated": datetime.now().isoformat()
|
||||||
|
}
|
||||||
|
|
||||||
# Save pages that need updating to JSON
|
# Save pages that need updating to JSON
|
||||||
save_to_json(pages_to_update, OUTDATED_PAGES_FILE)
|
save_to_json(output_data, OUTDATED_PAGES_FILE)
|
||||||
|
|
||||||
# Print the top pages needing updates
|
# Print the top pages needing updates
|
||||||
print(f"\n===== TOP {min(NUM_WIKI_PAGES, len(pages_to_update))} WIKI PAGES NEEDING UPDATES =====")
|
print(f"\n===== TOP {min(NUM_WIKI_PAGES, len(pages_to_update))} WIKI PAGES NEEDING UPDATES =====")
|
||||||
|
|
|
@ -1,900 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
wiki_compare.py
|
|
||||||
|
|
||||||
This script fetches the most used OpenStreetMap keys from TagInfo,
|
|
||||||
compares their English and French wiki pages, and identifies which pages
|
|
||||||
need updating based on modification dates and content analysis.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
python wiki_compare.py
|
|
||||||
|
|
||||||
Output:
|
|
||||||
- top_keys.json: JSON file containing the most used OSM keys
|
|
||||||
- wiki_pages.csv: CSV file with information about each wiki page
|
|
||||||
- outdated_pages.json: JSON file containing pages that need updating
|
|
||||||
- A console output listing the wiki pages that need updating
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import csv
|
|
||||||
import requests
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import logging
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
# Configure logging
|
|
||||||
logging.basicConfig(
|
|
||||||
level=logging.INFO,
|
|
||||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S'
|
|
||||||
)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# Constants
|
|
||||||
TAGINFO_API_URL = "https://taginfo.openstreetmap.org/api/4/keys/all"
|
|
||||||
WIKI_BASE_URL_EN = "https://wiki.openstreetmap.org/wiki/Key:"
|
|
||||||
WIKI_BASE_URL_FR = "https://wiki.openstreetmap.org/wiki/FR:Key:"
|
|
||||||
TOP_KEYS_FILE = "top_keys.json"
|
|
||||||
WIKI_PAGES_CSV = "wiki_pages.csv"
|
|
||||||
OUTDATED_PAGES_FILE = "outdated_pages.json"
|
|
||||||
STALENESS_HISTOGRAM_FILE = "staleness_histogram.png"
|
|
||||||
# Number of wiki pages to examine
|
|
||||||
NUM_WIKI_PAGES = 100
|
|
||||||
|
|
||||||
def fetch_top_keys(limit=NUM_WIKI_PAGES):
|
|
||||||
"""
|
|
||||||
Fetch the most used OSM keys from TagInfo API
|
|
||||||
|
|
||||||
Args:
|
|
||||||
limit (int): Number of keys to fetch
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: List of dictionaries containing key information
|
|
||||||
"""
|
|
||||||
logger.info(f"Fetching top {limit} OSM keys from TagInfo API...")
|
|
||||||
|
|
||||||
params = {
|
|
||||||
'page': 1,
|
|
||||||
'rp': limit,
|
|
||||||
'sortname': 'count_all',
|
|
||||||
'sortorder': 'desc'
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.get(TAGINFO_API_URL, params=params)
|
|
||||||
response.raise_for_status()
|
|
||||||
data = response.json()
|
|
||||||
|
|
||||||
# Extract just the key names and counts
|
|
||||||
top_keys = [{'key': item['key'], 'count': item['count_all']} for item in data['data']]
|
|
||||||
|
|
||||||
logger.info(f"Successfully fetched {len(top_keys)} keys")
|
|
||||||
return top_keys
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
logger.error(f"Error fetching data from TagInfo API: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def save_to_json(data, filename):
|
|
||||||
"""
|
|
||||||
Save data to a JSON file
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data: Data to save
|
|
||||||
filename (str): Name of the file
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
with open(filename, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
||||||
logger.info(f"Data saved to {filename}")
|
|
||||||
except IOError as e:
|
|
||||||
logger.error(f"Error saving data to {filename}: {e}")
|
|
||||||
|
|
||||||
def fetch_wiki_page(key, language='en'):
|
|
||||||
"""
|
|
||||||
Fetch wiki page for a given key
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key (str): OSM key
|
|
||||||
language (str): Language code ('en' or 'fr')
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: Dictionary with page information or None if page doesn't exist
|
|
||||||
"""
|
|
||||||
base_url = WIKI_BASE_URL_EN if language == 'en' else WIKI_BASE_URL_FR
|
|
||||||
url = f"{base_url}{key}"
|
|
||||||
|
|
||||||
logger.info(f"Fetching {language} wiki page for key '{key}': {url}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.get(url)
|
|
||||||
|
|
||||||
# Check if page exists
|
|
||||||
if response.status_code == 404:
|
|
||||||
logger.warning(f"Wiki page for key '{key}' in {language} does not exist")
|
|
||||||
return None
|
|
||||||
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
soup = BeautifulSoup(response.text, 'html.parser')
|
|
||||||
|
|
||||||
# Get last modification date
|
|
||||||
last_modified = None
|
|
||||||
footer_info = soup.select_one('#footer-info-lastmod')
|
|
||||||
if footer_info:
|
|
||||||
date_text = footer_info.text
|
|
||||||
# Extract date using regex
|
|
||||||
date_match = re.search(r'(\d{1,2} \w+ \d{4})', date_text)
|
|
||||||
if date_match:
|
|
||||||
date_str = date_match.group(1)
|
|
||||||
try:
|
|
||||||
# Parse date (format may vary based on wiki language)
|
|
||||||
last_modified = datetime.strptime(date_str, '%d %B %Y').strftime('%Y-%m-%d')
|
|
||||||
except ValueError:
|
|
||||||
logger.warning(f"Could not parse date: {date_str}")
|
|
||||||
|
|
||||||
# Extract sections (h2, h3, h4)
|
|
||||||
section_elements = soup.select('h2, h3, h4')
|
|
||||||
sections = len(section_elements)
|
|
||||||
|
|
||||||
# Extract section titles
|
|
||||||
section_titles = []
|
|
||||||
for section_elem in section_elements:
|
|
||||||
# Skip sections that are part of the table of contents, navigation, or DescriptionBox
|
|
||||||
if section_elem.parent and section_elem.parent.get('id') in ['toc', 'mw-navigation']:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Skip sections that are inside a table with class DescriptionBox
|
|
||||||
if section_elem.find_parent('table', class_='DescriptionBox'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Get the text of the section title, removing any edit links
|
|
||||||
for edit_link in section_elem.select('.mw-editsection'):
|
|
||||||
edit_link.extract()
|
|
||||||
|
|
||||||
section_title = section_elem.get_text(strip=True)
|
|
||||||
section_level = int(section_elem.name[1]) # h2 -> 2, h3 -> 3, h4 -> 4
|
|
||||||
|
|
||||||
section_titles.append({
|
|
||||||
'title': section_title,
|
|
||||||
'level': section_level
|
|
||||||
})
|
|
||||||
|
|
||||||
# Count words in the content
|
|
||||||
content = soup.select_one('#mw-content-text')
|
|
||||||
if content:
|
|
||||||
# Remove script and style elements
|
|
||||||
for script in content.select('script, style'):
|
|
||||||
script.extract()
|
|
||||||
|
|
||||||
# Remove .languages elements
|
|
||||||
for languages_elem in content.select('.languages'):
|
|
||||||
languages_elem.extract()
|
|
||||||
|
|
||||||
# Get text and count words
|
|
||||||
text = content.get_text(separator=' ', strip=True)
|
|
||||||
word_count = len(text.split())
|
|
||||||
|
|
||||||
# Extract links
|
|
||||||
links = content.select('a')
|
|
||||||
link_count = len(links)
|
|
||||||
|
|
||||||
# Get link details (text and href)
|
|
||||||
link_details = []
|
|
||||||
for link in links:
|
|
||||||
href = link.get('href', '')
|
|
||||||
# Skip edit section links and other non-content links
|
|
||||||
if 'action=edit' in href or 'redlink=1' in href or not href:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Make relative URLs absolute
|
|
||||||
if href.startswith('/'):
|
|
||||||
href = 'https://wiki.openstreetmap.org' + href
|
|
||||||
|
|
||||||
link_text = link.get_text(strip=True)
|
|
||||||
if link_text: # Only include links with text
|
|
||||||
link_details.append({
|
|
||||||
'text': link_text,
|
|
||||||
'href': href
|
|
||||||
})
|
|
||||||
|
|
||||||
# Extract media (images)
|
|
||||||
media_elements = content.select('img')
|
|
||||||
media_count = len(media_elements)
|
|
||||||
|
|
||||||
# Get media details (src and alt text)
|
|
||||||
media_details = []
|
|
||||||
|
|
||||||
# Extract description image specifically
|
|
||||||
# Try multiple selectors to find the description image
|
|
||||||
description_img = None
|
|
||||||
|
|
||||||
# Debug: Log the key we're processing
|
|
||||||
logger.info(f"Looking for description image for key '{key}' in {language}")
|
|
||||||
|
|
||||||
# Function to filter out OSM logo and small icons
|
|
||||||
def is_relevant_image(img):
|
|
||||||
src = img.get('src', '')
|
|
||||||
# Skip OSM logo
|
|
||||||
if 'osm_logo' in src:
|
|
||||||
return False
|
|
||||||
# Skip small icons (usually less than 30px)
|
|
||||||
width = img.get('width')
|
|
||||||
if width and int(width) < 30:
|
|
||||||
return False
|
|
||||||
height = img.get('height')
|
|
||||||
if height and int(height) < 30:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Special case for highway key - directly target the image we want
|
|
||||||
if key == 'highway':
|
|
||||||
# Try to find the specific image in figure elements
|
|
||||||
highway_img_elements = content.select('figure.mw-halign-center img')
|
|
||||||
logger.info(f" Highway specific selector 'figure.mw-halign-center img' found {len(highway_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in highway_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images for highway")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using highway-specific image: {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If not found with highway-specific selector, try the td.d_image selector
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('td.d_image img')
|
|
||||||
logger.info(f" Selector 'td.d_image img' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in td.d_image")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from 'td.d_image img': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If still not found, try the specific selector for .description img.mw-file-element
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('.description img.mw-file-element')
|
|
||||||
logger.info(f" Selector '.description img.mw-file-element' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in .description")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from '.description img.mw-file-element': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If still not found, try images in figures within the description box
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('.description figure img')
|
|
||||||
logger.info(f" Selector '.description figure img' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in .description figure")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from '.description figure img': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If still not found, try any image in the description box
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('.description img')
|
|
||||||
logger.info(f" Selector '.description img' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in .description general")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from '.description img': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If still not found, try images in the DescriptionBox table
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('table.DescriptionBox img')
|
|
||||||
logger.info(f" Selector 'table.DescriptionBox img' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in DescriptionBox")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from 'table.DescriptionBox img': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If still not found, try images in figure elements anywhere in the content
|
|
||||||
if not description_img:
|
|
||||||
description_img_elements = content.select('figure img')
|
|
||||||
logger.info(f" Selector 'figure img' found {len(description_img_elements)} elements")
|
|
||||||
|
|
||||||
# Filter for relevant images
|
|
||||||
relevant_images = [img for img in description_img_elements if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in figure elements")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using image from 'figure img': {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# If we still don't have an image, use any image that's not the OSM logo
|
|
||||||
if not description_img:
|
|
||||||
all_images = content.select('img')
|
|
||||||
relevant_images = [img for img in all_images if is_relevant_image(img)]
|
|
||||||
logger.info(f" Found {len(relevant_images)} relevant images in the entire page")
|
|
||||||
|
|
||||||
if relevant_images:
|
|
||||||
description_img = relevant_images[0]
|
|
||||||
logger.info(f" Using fallback image: {description_img.get('src', '')}")
|
|
||||||
|
|
||||||
# Process the found image
|
|
||||||
description_img_url = None
|
|
||||||
if description_img:
|
|
||||||
src = description_img.get('src', '')
|
|
||||||
if src:
|
|
||||||
# Make relative URLs absolute
|
|
||||||
if src.startswith('//'):
|
|
||||||
src = 'https:' + src
|
|
||||||
elif src.startswith('/'):
|
|
||||||
src = 'https://wiki.openstreetmap.org' + src
|
|
||||||
|
|
||||||
description_img_url = src
|
|
||||||
|
|
||||||
# Process all images
|
|
||||||
for img in media_elements:
|
|
||||||
src = img.get('src', '')
|
|
||||||
if src:
|
|
||||||
# Make relative URLs absolute
|
|
||||||
if src.startswith('//'):
|
|
||||||
src = 'https:' + src
|
|
||||||
elif src.startswith('/'):
|
|
||||||
src = 'https://wiki.openstreetmap.org' + src
|
|
||||||
|
|
||||||
alt_text = img.get('alt', '')
|
|
||||||
media_details.append({
|
|
||||||
'src': src,
|
|
||||||
'alt': alt_text
|
|
||||||
})
|
|
||||||
|
|
||||||
# Extract categories
|
|
||||||
categories = []
|
|
||||||
category_links = soup.select('#mw-normal-catlinks li a')
|
|
||||||
for cat_link in category_links:
|
|
||||||
categories.append(cat_link.get_text(strip=True))
|
|
||||||
else:
|
|
||||||
word_count = 0
|
|
||||||
link_count = 0
|
|
||||||
link_details = []
|
|
||||||
media_count = 0
|
|
||||||
media_details = []
|
|
||||||
categories = []
|
|
||||||
|
|
||||||
return {
|
|
||||||
'key': key,
|
|
||||||
'language': language,
|
|
||||||
'url': url,
|
|
||||||
'last_modified': last_modified,
|
|
||||||
'sections': sections,
|
|
||||||
'section_titles': section_titles,
|
|
||||||
'word_count': word_count,
|
|
||||||
'link_count': link_count,
|
|
||||||
'link_details': link_details,
|
|
||||||
'media_count': media_count,
|
|
||||||
'media_details': media_details,
|
|
||||||
'categories': categories,
|
|
||||||
'description_img_url': description_img_url
|
|
||||||
}
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
logger.error(f"Error fetching wiki page for key '{key}' in {language}: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def generate_staleness_histogram(wiki_pages):
|
|
||||||
"""
|
|
||||||
Generate a histogram of staleness scores by 10% ranges
|
|
||||||
|
|
||||||
Args:
|
|
||||||
wiki_pages (list): List of dictionaries containing page information with staleness scores
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
None: Saves the histogram to a file
|
|
||||||
"""
|
|
||||||
logger.info("Generating histogram of staleness scores by 10% ranges...")
|
|
||||||
|
|
||||||
# Extract staleness scores
|
|
||||||
staleness_scores = []
|
|
||||||
for page in wiki_pages:
|
|
||||||
if page and 'staleness_score' in page:
|
|
||||||
staleness_scores.append(page['staleness_score'])
|
|
||||||
|
|
||||||
if not staleness_scores:
|
|
||||||
logger.warning("No staleness scores found. Cannot generate histogram.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Determine the maximum score for binning
|
|
||||||
max_score = max(staleness_scores)
|
|
||||||
# Round up to the nearest 10 to ensure all scores are included
|
|
||||||
max_bin_edge = np.ceil(max_score / 10) * 10
|
|
||||||
|
|
||||||
# Create bins for 10% ranges
|
|
||||||
bins = np.arange(0, max_bin_edge + 10, 10)
|
|
||||||
|
|
||||||
# Count scores in each bin
|
|
||||||
hist, bin_edges = np.histogram(staleness_scores, bins=bins)
|
|
||||||
|
|
||||||
# Create histogram
|
|
||||||
plt.figure(figsize=(12, 6))
|
|
||||||
|
|
||||||
# Create bar chart
|
|
||||||
plt.bar(range(len(hist)), hist, align='center')
|
|
||||||
|
|
||||||
# Set x-axis labels for each bin
|
|
||||||
bin_labels = [f"{int(bin_edges[i])}-{int(bin_edges[i+1])}%" for i in range(len(bin_edges)-1)]
|
|
||||||
plt.xticks(range(len(hist)), bin_labels, rotation=45)
|
|
||||||
|
|
||||||
# Set labels and title
|
|
||||||
plt.xlabel('Tranches de score de décrépitude (en %)')
|
|
||||||
plt.ylabel('Nombre de pages')
|
|
||||||
plt.title('Répartition du score de décrépitude par tranches de 10%')
|
|
||||||
|
|
||||||
# Add grid for better readability
|
|
||||||
plt.grid(axis='y', linestyle='--', alpha=0.7)
|
|
||||||
|
|
||||||
# Adjust layout
|
|
||||||
plt.tight_layout()
|
|
||||||
|
|
||||||
# Save figure
|
|
||||||
plt.savefig(STALENESS_HISTOGRAM_FILE)
|
|
||||||
logger.info(f"Histogram saved to {STALENESS_HISTOGRAM_FILE}")
|
|
||||||
|
|
||||||
# Close the figure to free memory
|
|
||||||
plt.close()
|
|
||||||
|
|
||||||
def analyze_wiki_pages(pages):
|
|
||||||
"""
|
|
||||||
Analyze wiki pages to determine which ones need updating
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pages (list): List of dictionaries containing page information
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: List of pages that need updating, sorted by priority
|
|
||||||
"""
|
|
||||||
logger.info("Analyzing wiki pages to identify those needing updates...")
|
|
||||||
|
|
||||||
# Group pages by key
|
|
||||||
pages_by_key = {}
|
|
||||||
for page in pages:
|
|
||||||
if page is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key = page['key']
|
|
||||||
if key not in pages_by_key:
|
|
||||||
pages_by_key[key] = {}
|
|
||||||
|
|
||||||
pages_by_key[key][page['language']] = page
|
|
||||||
|
|
||||||
# Analyze each key's pages
|
|
||||||
needs_update = []
|
|
||||||
|
|
||||||
for key, lang_pages in pages_by_key.items():
|
|
||||||
# Skip if either language is missing
|
|
||||||
if 'en' not in lang_pages or 'fr' not in lang_pages:
|
|
||||||
if 'en' in lang_pages:
|
|
||||||
# French page is missing
|
|
||||||
# For missing French pages, calculate a high staleness score
|
|
||||||
# Use word count as the main factor (50% weight)
|
|
||||||
missing_staleness_score = (
|
|
||||||
30 * 0.2 + # Assume 30 days outdated (20%)
|
|
||||||
lang_pages['en']['word_count'] / 100 * 0.5 + # Word count (50%)
|
|
||||||
lang_pages['en']['sections'] * 0.15 + # Sections (15%)
|
|
||||||
lang_pages['en']['link_count'] / 10 * 0.15 # Links (15%)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Round to 2 decimal places and ensure it's high
|
|
||||||
missing_staleness_score = max(100, round(missing_staleness_score, 2))
|
|
||||||
|
|
||||||
# Get media count or default to 0
|
|
||||||
media_count = lang_pages['en'].get('media_count', 0)
|
|
||||||
|
|
||||||
needs_update.append({
|
|
||||||
'key': key,
|
|
||||||
'reason': 'French page missing',
|
|
||||||
'en_page': lang_pages['en'],
|
|
||||||
'fr_page': None,
|
|
||||||
'date_diff': 0,
|
|
||||||
'word_diff': lang_pages['en']['word_count'],
|
|
||||||
'section_diff': lang_pages['en']['sections'],
|
|
||||||
'link_diff': lang_pages['en']['link_count'],
|
|
||||||
'media_diff': media_count,
|
|
||||||
'staleness_score': missing_staleness_score,
|
|
||||||
'priority': missing_staleness_score, # Use staleness score as priority
|
|
||||||
'section_comparison': None, # No comparison possible
|
|
||||||
'link_comparison': None, # No comparison possible
|
|
||||||
'media_comparison': None, # No comparison possible
|
|
||||||
'category_comparison': None # No comparison possible
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
|
|
||||||
en_page = lang_pages['en']
|
|
||||||
fr_page = lang_pages['fr']
|
|
||||||
|
|
||||||
# Skip if dates are missing
|
|
||||||
if not en_page['last_modified'] or not fr_page['last_modified']:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Calculate date difference in days
|
|
||||||
en_date = datetime.strptime(en_page['last_modified'], '%Y-%m-%d')
|
|
||||||
fr_date = datetime.strptime(fr_page['last_modified'], '%Y-%m-%d')
|
|
||||||
date_diff = (en_date - fr_date).days
|
|
||||||
|
|
||||||
# Calculate content differences
|
|
||||||
word_diff = en_page['word_count'] - fr_page['word_count']
|
|
||||||
section_diff = en_page['sections'] - fr_page['sections']
|
|
||||||
link_diff = en_page['link_count'] - fr_page['link_count']
|
|
||||||
media_diff = en_page.get('media_count', 0) - fr_page.get('media_count', 0)
|
|
||||||
|
|
||||||
# Calculate staleness score (higher means more outdated/stale)
|
|
||||||
# Weight factors adjusted to emphasize word count differences
|
|
||||||
staleness_score = (
|
|
||||||
abs(date_diff) * 0.2 + # Date difference (20%)
|
|
||||||
abs(word_diff) / 100 * 0.5 + # Word count difference (normalized) (50%)
|
|
||||||
abs(section_diff) * 0.15 + # Section difference (15%)
|
|
||||||
abs(link_diff) / 10 * 0.15 # Link count difference (normalized) (15%)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Round to 2 decimal places for display
|
|
||||||
staleness_score = round(staleness_score, 2)
|
|
||||||
|
|
||||||
# Compare sections between English and French pages
|
|
||||||
section_comparison = {
|
|
||||||
'en_only': [],
|
|
||||||
'fr_only': [],
|
|
||||||
'common': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Group sections by their level for hierarchical comparison
|
|
||||||
en_sections_by_level = {}
|
|
||||||
fr_sections_by_level = {}
|
|
||||||
|
|
||||||
# Organize English sections by level
|
|
||||||
for section in en_page.get('section_titles', []):
|
|
||||||
level = section['level']
|
|
||||||
if level not in en_sections_by_level:
|
|
||||||
en_sections_by_level[level] = []
|
|
||||||
en_sections_by_level[level].append(section)
|
|
||||||
|
|
||||||
# Organize French sections by level
|
|
||||||
for section in fr_page.get('section_titles', []):
|
|
||||||
level = section['level']
|
|
||||||
if level not in fr_sections_by_level:
|
|
||||||
fr_sections_by_level[level] = []
|
|
||||||
fr_sections_by_level[level].append(section)
|
|
||||||
|
|
||||||
# Process each level to find matching sections
|
|
||||||
all_levels = set(list(en_sections_by_level.keys()) + list(fr_sections_by_level.keys()))
|
|
||||||
|
|
||||||
for level in all_levels:
|
|
||||||
en_level_sections = en_sections_by_level.get(level, [])
|
|
||||||
fr_level_sections = fr_sections_by_level.get(level, [])
|
|
||||||
|
|
||||||
# Create dictionaries for easier lookup, using lowercase titles
|
|
||||||
en_dict = {section['title'].lower(): section for section in en_level_sections}
|
|
||||||
fr_dict = {section['title'].lower(): section for section in fr_level_sections}
|
|
||||||
|
|
||||||
# Find sections at this level only in English
|
|
||||||
for title, section in en_dict.items():
|
|
||||||
if title not in fr_dict:
|
|
||||||
section_comparison['en_only'].append(section)
|
|
||||||
|
|
||||||
# Find sections at this level only in French
|
|
||||||
for title, section in fr_dict.items():
|
|
||||||
if title not in en_dict:
|
|
||||||
section_comparison['fr_only'].append(section)
|
|
||||||
|
|
||||||
# Find common sections at this level
|
|
||||||
for title in en_dict.keys():
|
|
||||||
if title in fr_dict:
|
|
||||||
section_comparison['common'].append({
|
|
||||||
'en': en_dict[title],
|
|
||||||
'fr': fr_dict[title]
|
|
||||||
})
|
|
||||||
|
|
||||||
# Compare links between English and French pages
|
|
||||||
link_comparison = {
|
|
||||||
'en_only': [],
|
|
||||||
'fr_only': [],
|
|
||||||
'common': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract link texts for comparison (case insensitive)
|
|
||||||
en_links = {link['text'].lower(): link for link in en_page.get('link_details', [])}
|
|
||||||
fr_links = {link['text'].lower(): link for link in fr_page.get('link_details', [])}
|
|
||||||
|
|
||||||
# Find links only in English
|
|
||||||
for text, link in en_links.items():
|
|
||||||
if text not in fr_links:
|
|
||||||
link_comparison['en_only'].append(link)
|
|
||||||
|
|
||||||
# Find links only in French
|
|
||||||
for text, link in fr_links.items():
|
|
||||||
if text not in en_links:
|
|
||||||
link_comparison['fr_only'].append(link)
|
|
||||||
|
|
||||||
# Find common links
|
|
||||||
for text in en_links.keys():
|
|
||||||
if text in fr_links:
|
|
||||||
link_comparison['common'].append({
|
|
||||||
'en': en_links[text],
|
|
||||||
'fr': fr_links[text]
|
|
||||||
})
|
|
||||||
|
|
||||||
# Compare media between English and French pages
|
|
||||||
media_comparison = {
|
|
||||||
'en_only': [],
|
|
||||||
'fr_only': [],
|
|
||||||
'common': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract media alt texts for comparison (case insensitive)
|
|
||||||
en_media = {media['alt'].lower(): media for media in en_page.get('media_details', []) if media['alt']}
|
|
||||||
fr_media = {media['alt'].lower(): media for media in fr_page.get('media_details', []) if media['alt']}
|
|
||||||
|
|
||||||
# Find media only in English
|
|
||||||
for alt, media in en_media.items():
|
|
||||||
if alt not in fr_media:
|
|
||||||
media_comparison['en_only'].append(media)
|
|
||||||
|
|
||||||
# Find media only in French
|
|
||||||
for alt, media in fr_media.items():
|
|
||||||
if alt not in en_media:
|
|
||||||
media_comparison['fr_only'].append(media)
|
|
||||||
|
|
||||||
# Find common media
|
|
||||||
for alt in en_media.keys():
|
|
||||||
if alt in fr_media:
|
|
||||||
media_comparison['common'].append({
|
|
||||||
'en': en_media[alt],
|
|
||||||
'fr': fr_media[alt]
|
|
||||||
})
|
|
||||||
|
|
||||||
# Add media without alt text to their respective language-only lists
|
|
||||||
for media in en_page.get('media_details', []):
|
|
||||||
if not media['alt'] or media['alt'].lower() not in en_media:
|
|
||||||
media_comparison['en_only'].append(media)
|
|
||||||
|
|
||||||
for media in fr_page.get('media_details', []):
|
|
||||||
if not media['alt'] or media['alt'].lower() not in fr_media:
|
|
||||||
media_comparison['fr_only'].append(media)
|
|
||||||
|
|
||||||
# Compare categories between English and French pages
|
|
||||||
category_comparison = {
|
|
||||||
'en_only': [],
|
|
||||||
'fr_only': [],
|
|
||||||
'common': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract categories for comparison (case insensitive)
|
|
||||||
en_categories = [cat.lower() for cat in en_page.get('categories', [])]
|
|
||||||
fr_categories = [cat.lower() for cat in fr_page.get('categories', [])]
|
|
||||||
|
|
||||||
# Find categories only in English
|
|
||||||
for cat in en_page.get('categories', []):
|
|
||||||
if cat.lower() not in fr_categories:
|
|
||||||
category_comparison['en_only'].append(cat)
|
|
||||||
|
|
||||||
# Find categories only in French
|
|
||||||
for cat in fr_page.get('categories', []):
|
|
||||||
if cat.lower() not in en_categories:
|
|
||||||
category_comparison['fr_only'].append(cat)
|
|
||||||
|
|
||||||
# Find common categories
|
|
||||||
for cat in en_page.get('categories', []):
|
|
||||||
if cat.lower() in fr_categories:
|
|
||||||
category_comparison['common'].append(cat)
|
|
||||||
|
|
||||||
if date_diff > 30 or word_diff > 200 or section_diff > 2 or link_diff > 20 or fr_page['word_count'] < en_page['word_count'] * 0.7:
|
|
||||||
reason = []
|
|
||||||
if date_diff > 30:
|
|
||||||
reason.append(f"La version Française est datée de {date_diff} jours")
|
|
||||||
if word_diff > 200:
|
|
||||||
reason.append(f"La version Anglaise a {word_diff} plus de mots")
|
|
||||||
if section_diff > 2:
|
|
||||||
reason.append(f"La version Anglaise a {section_diff} plus de sections")
|
|
||||||
if link_diff > 20:
|
|
||||||
reason.append(f"La version Anglaise a {link_diff} plus de liens")
|
|
||||||
if media_diff > 5:
|
|
||||||
reason.append(f"La version Anglaise a {media_diff} plus d'images")
|
|
||||||
if fr_page['word_count'] < en_page['word_count'] * 0.7:
|
|
||||||
reason.append(f"La version Française a seulement {fr_page['word_count'] / en_page['word_count']:.0%} % du contenu en Anglais.")
|
|
||||||
|
|
||||||
needs_update.append({
|
|
||||||
'key': key,
|
|
||||||
'reason': ', '.join(reason),
|
|
||||||
'en_page': en_page,
|
|
||||||
'fr_page': fr_page,
|
|
||||||
'date_diff': date_diff,
|
|
||||||
'word_diff': word_diff,
|
|
||||||
'section_diff': section_diff,
|
|
||||||
'link_diff': link_diff,
|
|
||||||
'media_diff': media_diff,
|
|
||||||
'staleness_score': staleness_score,
|
|
||||||
'priority': staleness_score, # Use staleness score as priority
|
|
||||||
'section_comparison': section_comparison,
|
|
||||||
'link_comparison': link_comparison,
|
|
||||||
'media_comparison': media_comparison,
|
|
||||||
'category_comparison': category_comparison
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sort by priority (descending)
|
|
||||||
needs_update.sort(key=lambda x: x['priority'], reverse=True)
|
|
||||||
|
|
||||||
return needs_update
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main function to execute the script"""
|
|
||||||
logger.info("Starting wiki_compare.py")
|
|
||||||
|
|
||||||
# Create output directory if it doesn't exist
|
|
||||||
os.makedirs(os.path.dirname(os.path.abspath(__file__)), exist_ok=True)
|
|
||||||
|
|
||||||
# Fetch top keys
|
|
||||||
top_keys = fetch_top_keys(NUM_WIKI_PAGES)
|
|
||||||
|
|
||||||
if not top_keys:
|
|
||||||
logger.error("Failed to fetch top keys. Exiting.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Save top keys to JSON
|
|
||||||
save_to_json(top_keys, TOP_KEYS_FILE)
|
|
||||||
|
|
||||||
# Fetch wiki pages for each key
|
|
||||||
wiki_pages = []
|
|
||||||
|
|
||||||
for key_info in top_keys:
|
|
||||||
key = key_info['key']
|
|
||||||
|
|
||||||
# Fetch English page
|
|
||||||
en_page = fetch_wiki_page(key, 'en')
|
|
||||||
if en_page:
|
|
||||||
wiki_pages.append(en_page)
|
|
||||||
|
|
||||||
# Fetch French page
|
|
||||||
fr_page = fetch_wiki_page(key, 'fr')
|
|
||||||
if fr_page:
|
|
||||||
wiki_pages.append(fr_page)
|
|
||||||
|
|
||||||
# Process wiki pages to add staleness score
|
|
||||||
processed_wiki_pages = []
|
|
||||||
pages_by_key = {}
|
|
||||||
|
|
||||||
# Group pages by key
|
|
||||||
for page in wiki_pages:
|
|
||||||
if page is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key = page['key']
|
|
||||||
if key not in pages_by_key:
|
|
||||||
pages_by_key[key] = {}
|
|
||||||
|
|
||||||
pages_by_key[key][page['language']] = page
|
|
||||||
|
|
||||||
# Calculate staleness score for each pair of pages
|
|
||||||
for key, lang_pages in pages_by_key.items():
|
|
||||||
# Add English page with staleness score
|
|
||||||
if 'en' in lang_pages:
|
|
||||||
en_page = lang_pages['en'].copy()
|
|
||||||
|
|
||||||
# If French page exists, calculate staleness score
|
|
||||||
if 'fr' in lang_pages:
|
|
||||||
fr_page = lang_pages['fr']
|
|
||||||
|
|
||||||
# Skip if dates are missing
|
|
||||||
if en_page['last_modified'] and fr_page['last_modified']:
|
|
||||||
# Calculate date difference in days
|
|
||||||
en_date = datetime.strptime(en_page['last_modified'], '%Y-%m-%d')
|
|
||||||
fr_date = datetime.strptime(fr_page['last_modified'], '%Y-%m-%d')
|
|
||||||
date_diff = (en_date - fr_date).days
|
|
||||||
|
|
||||||
# Calculate content differences
|
|
||||||
word_diff = en_page['word_count'] - fr_page['word_count']
|
|
||||||
section_diff = en_page['sections'] - fr_page['sections']
|
|
||||||
link_diff = en_page['link_count'] - fr_page['link_count']
|
|
||||||
|
|
||||||
# Calculate staleness score
|
|
||||||
staleness_score = (
|
|
||||||
abs(date_diff) * 0.2 +
|
|
||||||
abs(word_diff) / 100 * 0.5 +
|
|
||||||
abs(section_diff) * 0.15 +
|
|
||||||
abs(link_diff) / 10 * 0.15
|
|
||||||
)
|
|
||||||
|
|
||||||
# Round to 2 decimal places
|
|
||||||
staleness_score = round(staleness_score, 2)
|
|
||||||
|
|
||||||
en_page['staleness_score'] = staleness_score
|
|
||||||
fr_page['staleness_score'] = staleness_score
|
|
||||||
else:
|
|
||||||
en_page['staleness_score'] = 0
|
|
||||||
fr_page['staleness_score'] = 0
|
|
||||||
|
|
||||||
processed_wiki_pages.append(en_page)
|
|
||||||
processed_wiki_pages.append(fr_page)
|
|
||||||
else:
|
|
||||||
# French page is missing, calculate a high staleness score
|
|
||||||
missing_staleness_score = (
|
|
||||||
30 * 0.2 +
|
|
||||||
en_page['word_count'] / 100 * 0.5 +
|
|
||||||
en_page['sections'] * 0.15 +
|
|
||||||
en_page['link_count'] / 10 * 0.15
|
|
||||||
)
|
|
||||||
|
|
||||||
# Round to 2 decimal places and ensure it's high
|
|
||||||
missing_staleness_score = max(100, round(missing_staleness_score, 2))
|
|
||||||
|
|
||||||
en_page['staleness_score'] = missing_staleness_score
|
|
||||||
processed_wiki_pages.append(en_page)
|
|
||||||
|
|
||||||
# Add French page without English counterpart (rare case)
|
|
||||||
elif 'fr' in lang_pages:
|
|
||||||
fr_page = lang_pages['fr'].copy()
|
|
||||||
fr_page['staleness_score'] = 0
|
|
||||||
processed_wiki_pages.append(fr_page)
|
|
||||||
|
|
||||||
# Generate histogram of staleness scores
|
|
||||||
generate_staleness_histogram(processed_wiki_pages)
|
|
||||||
|
|
||||||
# Save processed wiki pages to CSV
|
|
||||||
try:
|
|
||||||
with open(WIKI_PAGES_CSV, 'w', newline='', encoding='utf-8') as f:
|
|
||||||
# Basic fields for CSV (detailed content will be in JSON only)
|
|
||||||
fieldnames = ['key', 'language', 'url', 'last_modified', 'sections', 'word_count', 'link_count', 'media_count', 'staleness_score', 'description_img_url']
|
|
||||||
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
||||||
|
|
||||||
writer.writeheader()
|
|
||||||
for page in processed_wiki_pages:
|
|
||||||
if page: # Skip None values
|
|
||||||
# Create a copy with only the CSV fields
|
|
||||||
csv_page = {field: page.get(field, '') for field in fieldnames if field in page}
|
|
||||||
writer.writerow(csv_page)
|
|
||||||
|
|
||||||
logger.info(f"Wiki page data saved to {WIKI_PAGES_CSV}")
|
|
||||||
|
|
||||||
except IOError as e:
|
|
||||||
logger.error(f"Error saving data to {WIKI_PAGES_CSV}: {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Analyze pages to find those needing updates
|
|
||||||
pages_to_update = analyze_wiki_pages(wiki_pages)
|
|
||||||
|
|
||||||
# Save pages that need updating to JSON
|
|
||||||
save_to_json(pages_to_update, OUTDATED_PAGES_FILE)
|
|
||||||
|
|
||||||
# Print the top pages needing updates
|
|
||||||
print(f"\n===== TOP {min(NUM_WIKI_PAGES, len(pages_to_update))} WIKI PAGES NEEDING UPDATES =====")
|
|
||||||
|
|
||||||
for i, page in enumerate(pages_to_update[:NUM_WIKI_PAGES], 1):
|
|
||||||
key = page['key']
|
|
||||||
reason = page['reason']
|
|
||||||
en_url = page['en_page']['url'] if page['en_page'] else "N/A"
|
|
||||||
fr_url = page['fr_page']['url'] if page['fr_page'] else "N/A"
|
|
||||||
|
|
||||||
print(f"{i}. Key: {key}")
|
|
||||||
print(f" Reason: {reason}")
|
|
||||||
print(f" English: {en_url}")
|
|
||||||
print(f" French: {fr_url}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
logger.info("Script completed successfully")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,174 +1,16 @@
|
||||||
key,language,url,last_modified,sections,word_count,link_count,media_count,staleness_score,description_img_url
|
key,language,url,last_modified,sections,word_count,link_count,media_count,staleness_score,description_img_url
|
||||||
building,en,https://wiki.openstreetmap.org/wiki/Key:building,2025-06-10,31,3774,627,158,8.91,https://wiki.openstreetmap.org/w/images/thumb/6/61/Emptyhouse.jpg/200px-Emptyhouse.jpg
|
building,en,https://wiki.openstreetmap.org/wiki/Key:building,2025-06-10,31,3774,627,158,8.91,https://wiki.openstreetmap.org/w/images/thumb/6/61/Emptyhouse.jpg/200px-Emptyhouse.jpg
|
||||||
building,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building,2025-05-22,25,3181,544,155,8.91,https://wiki.openstreetmap.org/w/images/thumb/6/61/Emptyhouse.jpg/200px-Emptyhouse.jpg
|
building,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building,2025-05-22,25,3181,544,155,8.91,https://wiki.openstreetmap.org/w/images/thumb/6/61/Emptyhouse.jpg/200px-Emptyhouse.jpg
|
||||||
source,en,https://wiki.openstreetmap.org/wiki/Key:source,2025-08-12,27,2752,314,42,113.06,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
Anatomie_des_étiquettes_osm,en,https://wiki.openstreetmap.org/wiki/Anatomie_des_étiquettes_osm,2025-06-08,22,963,53,0,100,
|
||||||
source,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source,2024-02-07,23,2593,230,35,113.06,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
FR:Tag:leisure%3Dchildren_club,fr,https://wiki.openstreetmap.org/wiki/FR:Tag:leisure%3Dchildren_club,2024-05-02,8,294,67,10,0,https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Dave_%26_Buster%27s_video_arcade_in_Columbus%2C_OH_-_17910.JPG/200px-Dave_%26_Buster%27s_video_arcade_in_Columbus%2C_OH_-_17910.JPG
|
||||||
highway,en,https://wiki.openstreetmap.org/wiki/Key:highway,2025-04-10,30,4126,780,314,20.35,https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Roads_in_Switzerland_%2827965437018%29.jpg/200px-Roads_in_Switzerland_%2827965437018%29.jpg
|
https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dchildren_club,en,https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dchildren_club,2025-02-02,9,163,69,9,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
||||||
highway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:highway,2025-01-05,30,4141,695,313,20.35,https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Roads_in_Switzerland_%2827965437018%29.jpg/200px-Roads_in_Switzerland_%2827965437018%29.jpg
|
FR:Tag:harassment_prevention%3Dask_angela,fr,https://wiki.openstreetmap.org/wiki/FR:Tag:harassment_prevention%3Dask_angela,2025-07-10,20,873,166,15,0,https://wiki.openstreetmap.org/w/images/thumb/1/15/2024-06-27T08.40.50_ask_angela_lyon.jpg/200px-2024-06-27T08.40.50_ask_angela_lyon.jpg
|
||||||
addr:housenumber,en,https://wiki.openstreetmap.org/wiki/Key:addr:housenumber,2025-07-24,11,330,97,20,14.01,https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Ferry_Street%2C_Portaferry_%2809%29%2C_October_2009.JPG/200px-Ferry_Street%2C_Portaferry_%2809%29%2C_October_2009.JPG
|
https://wiki.openstreetmap.org/wiki/Tag:harassment_prevention%3Dask_angela,en,https://wiki.openstreetmap.org/wiki/Tag:harassment_prevention%3Dask_angela,2025-02-22,14,463,72,9,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
||||||
addr:housenumber,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:housenumber,2025-08-23,15,1653,150,77,14.01,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
Key:harassment_prevention,en,https://wiki.openstreetmap.org/wiki/Key:harassment_prevention,2024-08-10,12,196,69,14,66.72,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
||||||
addr:street,en,https://wiki.openstreetmap.org/wiki/Key:addr:street,2024-10-29,12,602,101,16,66.04,https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/UK_-_London_%2830474933636%29.jpg/200px-UK_-_London_%2830474933636%29.jpg
|
Key:harassment_prevention,fr,https://wiki.openstreetmap.org/wiki/FR:Key:harassment_prevention,2025-07-03,15,328,83,14,66.72,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
||||||
addr:street,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:street,2025-08-23,15,1653,150,77,66.04,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
Proposal process,en,https://wiki.openstreetmap.org/wiki/Proposal process,2025-08-13,44,5253,187,4,165.53,https://wiki.openstreetmap.org/w/images/thumb/c/c2/Save_proposal_first.png/761px-Save_proposal_first.png
|
||||||
addr:city,en,https://wiki.openstreetmap.org/wiki/Key:addr:city,2025-07-29,15,802,105,17,9.93,https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Lillerod.jpg/200px-Lillerod.jpg
|
Proposal process,fr,https://wiki.openstreetmap.org/wiki/FR:Proposal process,2023-09-22,15,1146,24,0,165.53,
|
||||||
addr:city,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:city,2025-08-23,15,1653,150,77,9.93,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
Automated_Edits_code_of_conduct,en,https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct,2025-07-26,19,2062,69,0,26.35,
|
||||||
name,en,https://wiki.openstreetmap.org/wiki/Key:name,2025-07-25,17,2196,281,82,42.39,https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Helena%2C_Montana.jpg/200px-Helena%2C_Montana.jpg
|
Automated_Edits_code_of_conduct,fr,https://wiki.openstreetmap.org/wiki/FR:Automated_Edits_code_of_conduct,2025-04-03,17,1571,16,0,26.35,
|
||||||
name,fr,https://wiki.openstreetmap.org/wiki/FR:Key:name,2025-01-16,21,1720,187,60,42.39,https://wiki.openstreetmap.org/w/images/3/37/Strakers.jpg
|
Key:cuisine,en,https://wiki.openstreetmap.org/wiki/Key:cuisine,2025-07-23,17,3422,693,303,107.73,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Food_montage.jpg/200px-Food_montage.jpg
|
||||||
addr:postcode,en,https://wiki.openstreetmap.org/wiki/Key:addr:postcode,2024-10-29,14,382,83,11,67.11,https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Farrer_post_code.jpg/200px-Farrer_post_code.jpg
|
Key:cuisine,fr,https://wiki.openstreetmap.org/wiki/FR:Key:cuisine,2024-02-16,15,2866,690,316,107.73,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Food_montage.jpg/200px-Food_montage.jpg
|
||||||
addr:postcode,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:postcode,2025-08-23,15,1653,150,77,67.11,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
natural,en,https://wiki.openstreetmap.org/wiki/Key:natural,2025-07-17,17,2070,535,189,22.06,https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/VocaDi-Nature%2CGeneral.jpeg/200px-VocaDi-Nature%2CGeneral.jpeg
|
|
||||||
natural,fr,https://wiki.openstreetmap.org/wiki/FR:Key:natural,2025-04-21,13,1499,455,174,22.06,https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/VocaDi-Nature%2CGeneral.jpeg/200px-VocaDi-Nature%2CGeneral.jpeg
|
|
||||||
surface,en,https://wiki.openstreetmap.org/wiki/Key:surface,2025-08-28,24,3475,591,238,264.64,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Transportation_in_Tanzania_Traffic_problems.JPG/200px-Transportation_in_Tanzania_Traffic_problems.JPG
|
|
||||||
surface,fr,https://wiki.openstreetmap.org/wiki/FR:Key:surface,2022-02-22,13,2587,461,232,264.64,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Transportation_in_Tanzania_Traffic_problems.JPG/200px-Transportation_in_Tanzania_Traffic_problems.JPG
|
|
||||||
addr:country,en,https://wiki.openstreetmap.org/wiki/Key:addr:country,2024-12-01,9,184,65,11,22.96,https://upload.wikimedia.org/wikipedia/commons/thumb/8/86/Europe_ISO_3166-1.svg/200px-Europe_ISO_3166-1.svg.png
|
|
||||||
addr:country,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:country,2025-03-25,8,187,65,11,22.96,https://upload.wikimedia.org/wikipedia/commons/thumb/8/86/Europe_ISO_3166-1.svg/200px-Europe_ISO_3166-1.svg.png
|
|
||||||
landuse,en,https://wiki.openstreetmap.org/wiki/Key:landuse,2025-03-01,17,2071,446,168,39.41,https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Changing_landuse_-_geograph.org.uk_-_1137810.jpg/200px-Changing_landuse_-_geograph.org.uk_-_1137810.jpg
|
|
||||||
landuse,fr,https://wiki.openstreetmap.org/wiki/FR:Key:landuse,2024-08-20,19,2053,418,182,39.41,https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Changing_landuse_-_geograph.org.uk_-_1137810.jpg/200px-Changing_landuse_-_geograph.org.uk_-_1137810.jpg
|
|
||||||
power,en,https://wiki.openstreetmap.org/wiki/Key:power,2025-02-28,20,641,127,21,124.89,https://wiki.openstreetmap.org/w/images/thumb/0/01/Power-tower.JPG/200px-Power-tower.JPG
|
|
||||||
power,fr,https://wiki.openstreetmap.org/wiki/FR:Key:power,2023-06-27,14,390,105,25,124.89,https://wiki.openstreetmap.org/w/images/thumb/0/01/Power-tower.JPG/200px-Power-tower.JPG
|
|
||||||
waterway,en,https://wiki.openstreetmap.org/wiki/Key:waterway,2025-03-10,21,1830,365,118,77.94,https://wiki.openstreetmap.org/w/images/thumb/f/fe/450px-Marshall-county-indiana-yellow-river.jpg/200px-450px-Marshall-county-indiana-yellow-river.jpg
|
|
||||||
waterway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:waterway,2024-03-08,18,1291,272,113,77.94,https://wiki.openstreetmap.org/w/images/thumb/f/fe/450px-Marshall-county-indiana-yellow-river.jpg/200px-450px-Marshall-county-indiana-yellow-river.jpg
|
|
||||||
building:levels,en,https://wiki.openstreetmap.org/wiki/Key:building:levels,2025-08-13,16,1351,204,25,76.11,https://wiki.openstreetmap.org/w/images/thumb/4/47/Building-levels.png/200px-Building-levels.png
|
|
||||||
building:levels,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building:levels,2024-08-01,15,1457,202,26,76.11,https://wiki.openstreetmap.org/w/images/thumb/4/47/Building-levels.png/200px-Building-levels.png
|
|
||||||
amenity,en,https://wiki.openstreetmap.org/wiki/Key:amenity,2025-08-24,29,3066,915,504,160.78,https://wiki.openstreetmap.org/w/images/thumb/a/a5/Mapping-Features-Parking-Lot.png/200px-Mapping-Features-Parking-Lot.png
|
|
||||||
amenity,fr,https://wiki.openstreetmap.org/wiki/FR:Key:amenity,2023-07-19,22,2146,800,487,160.78,https://wiki.openstreetmap.org/w/images/thumb/a/a5/Mapping-Features-Parking-Lot.png/200px-Mapping-Features-Parking-Lot.png
|
|
||||||
barrier,en,https://wiki.openstreetmap.org/wiki/Key:barrier,2025-04-15,17,2137,443,173,207.98,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/2014_Bystrzyca_K%C5%82odzka%2C_mury_obronne_05.jpg/200px-2014_Bystrzyca_K%C5%82odzka%2C_mury_obronne_05.jpg
|
|
||||||
barrier,fr,https://wiki.openstreetmap.org/wiki/FR:Key:barrier,2022-08-16,15,542,103,18,207.98,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/2014_Bystrzyca_K%C5%82odzka%2C_mury_obronne_05.jpg/200px-2014_Bystrzyca_K%C5%82odzka%2C_mury_obronne_05.jpg
|
|
||||||
source:date,en,https://wiki.openstreetmap.org/wiki/Key:source:date,2023-04-01,11,395,75,10,22.47,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
source:date,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source:date,2023-07-21,10,419,75,11,22.47,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
service,en,https://wiki.openstreetmap.org/wiki/Key:service,2025-03-16,22,1436,218,17,83.79,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
service,fr,https://wiki.openstreetmap.org/wiki/FR:Key:service,2024-03-04,11,443,100,10,83.79,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
addr:state,en,https://wiki.openstreetmap.org/wiki/Key:addr:state,2023-06-23,12,289,74,11,100,https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/WVaCent.jpg/200px-WVaCent.jpg
|
|
||||||
access,en,https://wiki.openstreetmap.org/wiki/Key:access,2025-08-06,31,5803,708,98,66.75,https://wiki.openstreetmap.org/w/images/5/5e/WhichAccess.png
|
|
||||||
access,fr,https://wiki.openstreetmap.org/wiki/FR:Key:access,2024-11-27,33,3200,506,83,66.75,https://wiki.openstreetmap.org/w/images/5/5e/WhichAccess.png
|
|
||||||
oneway,en,https://wiki.openstreetmap.org/wiki/Key:oneway,2025-07-17,28,2318,290,30,19.4,https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/One_way_sign.JPG/200px-One_way_sign.JPG
|
|
||||||
oneway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:oneway,2025-06-16,14,645,108,14,19.4,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/France_road_sign_C12.svg/200px-France_road_sign_C12.svg.png
|
|
||||||
height,en,https://wiki.openstreetmap.org/wiki/Key:height,2025-07-21,24,1184,184,20,8.45,https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Height_demonstration_diagram.png/200px-Height_demonstration_diagram.png
|
|
||||||
height,fr,https://wiki.openstreetmap.org/wiki/FR:Key:height,2025-06-14,21,1285,190,21,8.45,https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Height_demonstration_diagram.png/200px-Height_demonstration_diagram.png
|
|
||||||
ref,en,https://wiki.openstreetmap.org/wiki/Key:ref,2025-07-25,26,4404,782,115,11.79,https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/UK_traffic_sign_2901.svg/200px-UK_traffic_sign_2901.svg.png
|
|
||||||
ref,fr,https://wiki.openstreetmap.org/wiki/FR:Key:ref,2025-07-30,20,3393,460,12,11.79,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Autoroute_fran%C3%A7aise_1.svg/200px-Autoroute_fran%C3%A7aise_1.svg.png
|
|
||||||
maxspeed,en,https://wiki.openstreetmap.org/wiki/Key:maxspeed,2025-08-20,30,4275,404,38,39.24,https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Zeichen_274-60_-_Zul%C3%A4ssige_H%C3%B6chstgeschwindigkeit%2C_StVO_2017.svg/200px-Zeichen_274-60_-_Zul%C3%A4ssige_H%C3%B6chstgeschwindigkeit%2C_StVO_2017.svg.png
|
|
||||||
maxspeed,fr,https://wiki.openstreetmap.org/wiki/FR:Key:maxspeed,2025-05-10,25,1401,156,23,39.24,https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Zeichen_274-60_-_Zul%C3%A4ssige_H%C3%B6chstgeschwindigkeit%2C_StVO_2017.svg/200px-Zeichen_274-60_-_Zul%C3%A4ssige_H%C3%B6chstgeschwindigkeit%2C_StVO_2017.svg.png
|
|
||||||
lanes,en,https://wiki.openstreetmap.org/wiki/Key:lanes,2025-08-21,26,2869,355,48,117.16,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/A55_trunk_road_looking_east_-_geograph.org.uk_-_932668.jpg/200px-A55_trunk_road_looking_east_-_geograph.org.uk_-_932668.jpg
|
|
||||||
lanes,fr,https://wiki.openstreetmap.org/wiki/FR:Key:lanes,2024-03-07,19,1492,167,19,117.16,https://wiki.openstreetmap.org/w/images/thumb/d/d4/Dscf0444_600.jpg/200px-Dscf0444_600.jpg
|
|
||||||
start_date,en,https://wiki.openstreetmap.org/wiki/Key:start_date,2025-08-01,22,1098,168,29,214.58,https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Connel_bridge_plate.jpg/200px-Connel_bridge_plate.jpg
|
|
||||||
start_date,fr,https://wiki.openstreetmap.org/wiki/FR:Key:start_date,2022-08-29,19,1097,133,22,214.58,https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Connel_bridge_plate.jpg/200px-Connel_bridge_plate.jpg
|
|
||||||
addr:district,en,https://wiki.openstreetmap.org/wiki/Key:addr:district,2023-11-06,11,244,76,11,139.96,https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Hangal_Taluk.jpg/200px-Hangal_Taluk.jpg
|
|
||||||
addr:district,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:district,2025-08-23,15,1653,150,77,139.96,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
layer,en,https://wiki.openstreetmap.org/wiki/Key:layer,2025-01-02,16,1967,181,17,65.95,https://wiki.openstreetmap.org/w/images/thumb/2/26/Washington_layers.png/200px-Washington_layers.png
|
|
||||||
layer,fr,https://wiki.openstreetmap.org/wiki/FR:Key:layer,2024-02-16,15,2231,162,17,65.95,https://wiki.openstreetmap.org/w/images/thumb/2/26/Washington_layers.png/200px-Washington_layers.png
|
|
||||||
type,en,https://wiki.openstreetmap.org/wiki/Key:type,2025-05-13,20,911,200,72,334.06,https://wiki.openstreetmap.org/w/images/thumb/5/58/Osm_element_node_no.svg/30px-Osm_element_node_no.svg.png
|
|
||||||
type,fr,https://wiki.openstreetmap.org/wiki/FR:Key:type,2020-11-13,10,444,78,10,334.06,https://wiki.openstreetmap.org/w/images/thumb/5/58/Osm_element_node_no.svg/30px-Osm_element_node_no.svg.png
|
|
||||||
operator,en,https://wiki.openstreetmap.org/wiki/Key:operator,2025-08-26,24,1908,241,37,223.28,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
operator,fr,https://wiki.openstreetmap.org/wiki/FR:Key:operator,2022-09-30,15,418,89,11,223.28,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
lit,en,https://wiki.openstreetmap.org/wiki/Key:lit,2024-07-20,17,931,174,52,38.88,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Peatonal_Bicentenario.JPG/200px-Peatonal_Bicentenario.JPG
|
|
||||||
lit,fr,https://wiki.openstreetmap.org/wiki/FR:Key:lit,2025-01-19,17,628,123,14,38.88,https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/2014_K%C5%82odzko%2C_ul._Grottgera_14.JPG/200px-2014_K%C5%82odzko%2C_ul._Grottgera_14.JPG
|
|
||||||
wall,en,https://wiki.openstreetmap.org/wiki/Key:wall,2024-05-02,14,715,206,55,100,https://wiki.openstreetmap.org/w/images/thumb/5/58/Osm_element_node_no.svg/30px-Osm_element_node_no.svg.png
|
|
||||||
tiger:cfcc,en,https://wiki.openstreetmap.org/wiki/Key:tiger:cfcc,2022-12-09,10,127,24,7,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
crossing,en,https://wiki.openstreetmap.org/wiki/Key:crossing,2024-02-18,25,2678,363,34,76.98,https://wiki.openstreetmap.org/w/images/thumb/7/75/Toucan.jpg/200px-Toucan.jpg
|
|
||||||
crossing,fr,https://wiki.openstreetmap.org/wiki/FR:Key:crossing,2025-01-20,15,1390,254,28,76.98,https://wiki.openstreetmap.org/w/images/thumb/7/75/Toucan.jpg/200px-Toucan.jpg
|
|
||||||
tiger:county,en,https://wiki.openstreetmap.org/wiki/Key:tiger:county,2022-12-09,10,127,24,7,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
source:addr,en,https://wiki.openstreetmap.org/wiki/Key:source:addr,2023-07-05,9,200,70,10,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
footway,en,https://wiki.openstreetmap.org/wiki/Key:footway,2025-08-20,23,2002,369,39,99.66,https://wiki.openstreetmap.org/w/images/thumb/b/b9/Sidewalk_and_zebra-crossing.jpg/200px-Sidewalk_and_zebra-crossing.jpg
|
|
||||||
footway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:footway,2024-06-04,14,685,147,28,99.66,https://wiki.openstreetmap.org/w/images/thumb/b/b9/Sidewalk_and_zebra-crossing.jpg/200px-Sidewalk_and_zebra-crossing.jpg
|
|
||||||
ref:bag,en,https://wiki.openstreetmap.org/wiki/Key:ref:bag,2024-10-09,10,254,69,11,100,https://wiki.openstreetmap.org/w/images/thumb/5/58/Osm_element_node_no.svg/30px-Osm_element_node_no.svg.png
|
|
||||||
addr:place,en,https://wiki.openstreetmap.org/wiki/Key:addr:place,2025-03-28,16,1204,154,13,136.57,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Suburb_of_Phillip.jpg/200px-Suburb_of_Phillip.jpg
|
|
||||||
addr:place,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:place,2023-06-17,11,276,75,12,136.57,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Suburb_of_Phillip.jpg/200px-Suburb_of_Phillip.jpg
|
|
||||||
tiger:reviewed,en,https://wiki.openstreetmap.org/wiki/Key:tiger:reviewed,2025-08-01,16,734,105,11,100,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/US-Census-TIGERLogo.svg/200px-US-Census-TIGERLogo.svg.png
|
|
||||||
leisure,en,https://wiki.openstreetmap.org/wiki/Key:leisure,2025-02-28,12,1084,374,180,232.43,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Hammock_-_Polynesia.jpg/200px-Hammock_-_Polynesia.jpg
|
|
||||||
leisure,fr,https://wiki.openstreetmap.org/wiki/FR:Key:leisure,2021-12-29,11,951,360,186,232.43,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Hammock_-_Polynesia.jpg/200px-Hammock_-_Polynesia.jpg
|
|
||||||
addr:suburb,en,https://wiki.openstreetmap.org/wiki/Key:addr:suburb,2024-02-24,14,439,89,11,1.49,https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Grosvenor_Place_2_2008_06_19.jpg/200px-Grosvenor_Place_2_2008_06_19.jpg
|
|
||||||
addr:suburb,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:suburb,2024-02-18,13,418,87,11,1.49,https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Grosvenor_Place_2_2008_06_19.jpg/200px-Grosvenor_Place_2_2008_06_19.jpg
|
|
||||||
ele,en,https://wiki.openstreetmap.org/wiki/Key:ele,2025-07-18,18,1846,165,24,104.45,https://wiki.openstreetmap.org/w/images/a/a3/Key-ele_mapnik.png
|
|
||||||
ele,fr,https://wiki.openstreetmap.org/wiki/FR:Key:ele,2024-03-02,15,1277,128,13,104.45,https://wiki.openstreetmap.org/w/images/a/a3/Key-ele_mapnik.png
|
|
||||||
tracktype,en,https://wiki.openstreetmap.org/wiki/Key:tracktype,2024-12-02,16,652,146,35,32.71,https://wiki.openstreetmap.org/w/images/thumb/1/13/Tracktype-collage.jpg/200px-Tracktype-collage.jpg
|
|
||||||
tracktype,fr,https://wiki.openstreetmap.org/wiki/FR:Key:tracktype,2025-05-03,11,463,105,29,32.71,https://wiki.openstreetmap.org/w/images/thumb/1/13/Tracktype-collage.jpg/200px-Tracktype-collage.jpg
|
|
||||||
addr:neighbourhood,en,https://wiki.openstreetmap.org/wiki/Key:addr:neighbourhood,2025-04-29,24,2020,235,83,100,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
addr:hamlet,en,https://wiki.openstreetmap.org/wiki/Key:addr:hamlet,2024-12-05,9,142,64,11,100,https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Grosvenor_Place_2_2008_06_19.jpg/200px-Grosvenor_Place_2_2008_06_19.jpg
|
|
||||||
addr:province,en,https://wiki.openstreetmap.org/wiki/Key:addr:province,2022-05-04,9,156,64,11,100,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Stamp_of_Indonesia_-_2002_-_Colnect_265917_-_Aceh_Province.jpeg/200px-Stamp_of_Indonesia_-_2002_-_Colnect_265917_-_Aceh_Province.jpeg
|
|
||||||
leaf_type,en,https://wiki.openstreetmap.org/wiki/Key:leaf_type,2025-01-22,15,739,201,57,114.46,https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Picea_abies_Nadelkissen.jpg/200px-Picea_abies_Nadelkissen.jpg
|
|
||||||
leaf_type,fr,https://wiki.openstreetmap.org/wiki/FR:Key:leaf_type,2023-07-02,14,734,220,64,114.46,https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Picea_abies_Nadelkissen.jpg/200px-Picea_abies_Nadelkissen.jpg
|
|
||||||
addr:full,en,https://wiki.openstreetmap.org/wiki/Key:addr:full,2025-04-29,24,2020,235,83,100,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
addr:TW:dataset,en,https://wiki.openstreetmap.org/wiki/Key:addr:TW:dataset,2023-06-23,9,128,63,9,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
place,en,https://wiki.openstreetmap.org/wiki/Key:place,2025-02-28,23,1342,150,12,128.24,https://wiki.openstreetmap.org/w/images/thumb/c/c4/Bremen.png/200px-Bremen.png
|
|
||||||
place,fr,https://wiki.openstreetmap.org/wiki/FR:Key:place,2023-06-29,18,1650,413,201,128.24,https://wiki.openstreetmap.org/w/images/thumb/c/c4/Bremen.png/200px-Bremen.png
|
|
||||||
man_made,en,https://wiki.openstreetmap.org/wiki/Key:man_made,2025-02-28,14,1789,631,323,16.11,https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Natural_Gas_Pipeline_Across_The_New_River_-_panoramio.jpg/200px-Natural_Gas_Pipeline_Across_The_New_River_-_panoramio.jpg
|
|
||||||
man_made,fr,https://wiki.openstreetmap.org/wiki/FR:Key:man_made,2025-05-13,10,1873,612,322,16.11,https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Natural_Gas_Pipeline_Across_The_New_River_-_panoramio.jpg/200px-Natural_Gas_Pipeline_Across_The_New_River_-_panoramio.jpg
|
|
||||||
bicycle,en,https://wiki.openstreetmap.org/wiki/Key:bicycle,2025-08-30,14,903,247,36,338.06,https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Sinnbild_Radfahrer%2C_StVO_1992.svg/200px-Sinnbild_Radfahrer%2C_StVO_1992.svg.png
|
|
||||||
bicycle,fr,https://wiki.openstreetmap.org/wiki/FR:Key:bicycle,2021-02-17,9,172,70,11,338.06,https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Sinnbild_Radfahrer%2C_StVO_1992.svg/200px-Sinnbild_Radfahrer%2C_StVO_1992.svg.png
|
|
||||||
roof:shape,en,https://wiki.openstreetmap.org/wiki/Key:roof:shape,2025-08-20,24,1554,260,44,2.0,https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Marienkapelle_und_Wohnhaus_%28Schafhauserm%C3%BChle%29.jpg/200px-Marienkapelle_und_Wohnhaus_%28Schafhauserm%C3%BChle%29.jpg
|
|
||||||
roof:shape,fr,https://wiki.openstreetmap.org/wiki/FR:Key:roof:shape,2025-08-20,18,1685,230,43,2.0,https://wiki.openstreetmap.org/w/images/thumb/2/2f/Roof4_0.jpg/200px-Roof4_0.jpg
|
|
||||||
tiger:name_base,en,https://wiki.openstreetmap.org/wiki/Key:tiger:name_base,2021-12-03,26,3319,53,1,100,https://wiki.openstreetmap.org/w/images/c/c9/Logo.png
|
|
||||||
foot,en,https://wiki.openstreetmap.org/wiki/Key:foot,2025-05-11,12,305,93,16,88.8,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Sinnbild_Fu%C3%9Fg%C3%A4nger.svg/200px-Sinnbild_Fu%C3%9Fg%C3%A4nger.svg.png
|
|
||||||
foot,fr,https://wiki.openstreetmap.org/wiki/FR:Key:foot,2024-03-02,8,143,67,11,88.8,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Sinnbild_Fu%C3%9Fg%C3%A4nger.svg/200px-Sinnbild_Fu%C3%9Fg%C3%A4nger.svg.png
|
|
||||||
railway,en,https://wiki.openstreetmap.org/wiki/Key:railway,2025-02-28,16,1481,331,154,72.73,https://wiki.openstreetmap.org/w/images/thumb/8/80/Mapping-Features-Railroad-With-Station.png/200px-Mapping-Features-Railroad-With-Station.png
|
|
||||||
railway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:railway,2024-03-08,15,1308,310,156,72.73,https://wiki.openstreetmap.org/w/images/thumb/8/80/Mapping-Features-Railroad-With-Station.png/200px-Mapping-Features-Railroad-With-Station.png
|
|
||||||
source:geometry:date,en,https://wiki.openstreetmap.org/wiki/Key:source:geometry:date,2024-04-07,10,389,88,10,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
crossing:markings,en,https://wiki.openstreetmap.org/wiki/Key:crossing:markings,2025-06-21,22,1471,301,64,43.84,https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Crosswalk_Styles_OpenStreetMap_%28en%29.svg/200px-Crosswalk_Styles_OpenStreetMap_%28en%29.svg.png
|
|
||||||
crossing:markings,fr,https://wiki.openstreetmap.org/wiki/FR:Key:crossing:markings,2024-12-08,16,964,207,46,43.84,https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Crosswalk_Styles_OpenStreetMap_%28en%29.svg/200px-Crosswalk_Styles_OpenStreetMap_%28en%29.svg.png
|
|
||||||
tiger:name_type,en,https://wiki.openstreetmap.org/wiki/Key:tiger:name_type,2021-12-03,26,3319,53,1,100,https://wiki.openstreetmap.org/w/images/c/c9/Logo.png
|
|
||||||
bridge,en,https://wiki.openstreetmap.org/wiki/Key:bridge,2025-03-16,30,3123,342,68,86.93,https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/2014_Karwina%2C_Dark%C3%B3w%2C_Most_%C5%BCelbetowy_01.jpg/200px-2014_Karwina%2C_Dark%C3%B3w%2C_Most_%C5%BCelbetowy_01.jpg
|
|
||||||
bridge,fr,https://wiki.openstreetmap.org/wiki/FR:Key:bridge,2024-03-07,19,1366,229,56,86.93,https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/2014_Karwina%2C_Dark%C3%B3w%2C_Most_%C5%BCelbetowy_01.jpg/200px-2014_Karwina%2C_Dark%C3%B3w%2C_Most_%C5%BCelbetowy_01.jpg
|
|
||||||
name:en,en,https://wiki.openstreetmap.org/wiki/Key:name:en,2025-03-15,12,325,100,16,100,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Polish_Embassy_in_Hungary._Plate._Bajza_Street_side._-_Budapest.JPG/200px-Polish_Embassy_in_Hungary._Plate._Bajza_Street_side._-_Budapest.JPG
|
|
||||||
intermittent,en,https://wiki.openstreetmap.org/wiki/Key:intermittent,2025-05-07,17,913,168,27,90.94,https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Oybach.JPG/200px-Oybach.JPG
|
|
||||||
intermittent,fr,https://wiki.openstreetmap.org/wiki/FR:Key:intermittent,2024-02-18,16,644,125,18,90.94,https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Oybach.JPG/200px-Oybach.JPG
|
|
||||||
shop,en,https://wiki.openstreetmap.org/wiki/Key:shop,2025-03-22,31,3638,816,392,124.2,https://wiki.openstreetmap.org/w/images/thumb/d/dc/North_london_shops.jpg/200px-North_london_shops.jpg
|
|
||||||
shop,fr,https://wiki.openstreetmap.org/wiki/FR:Key:shop,2023-07-25,33,3285,754,382,124.2,https://wiki.openstreetmap.org/w/images/thumb/2/26/Geograph_shop.jpg/200px-Geograph_shop.jpg
|
|
||||||
source:geometry,en,https://wiki.openstreetmap.org/wiki/Key:source:geometry,2024-04-07,10,389,88,10,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
public_transport,en,https://wiki.openstreetmap.org/wiki/Key:public_transport,2025-02-28,16,383,105,20,28.5,https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Citadis402Grenoble_citeinternationale.jpg/200px-Citadis402Grenoble_citeinternationale.jpg
|
|
||||||
public_transport,fr,https://wiki.openstreetmap.org/wiki/FR:Key:public_transport,2025-03-22,24,3688,530,103,28.5,https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Citadis402Grenoble_citeinternationale.jpg/200px-Citadis402Grenoble_citeinternationale.jpg
|
|
||||||
smoothness,en,https://wiki.openstreetmap.org/wiki/Key:smoothness,2025-08-05,16,1581,167,38,85.94,https://wiki.openstreetmap.org/w/images/thumb/6/69/Jena_Track_roots.jpg/200px-Jena_Track_roots.jpg
|
|
||||||
smoothness,fr,https://wiki.openstreetmap.org/wiki/FR:Key:smoothness,2024-06-11,15,1260,155,39,85.94,https://wiki.openstreetmap.org/w/images/thumb/6/69/Jena_Track_roots.jpg/200px-Jena_Track_roots.jpg
|
|
||||||
leaf_cycle,en,https://wiki.openstreetmap.org/wiki/Key:leaf_cycle,2024-09-28,14,499,144,21,10.48,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Olga_Wisinger-Florian_-_Falling_Leaves.JPG/200px-Olga_Wisinger-Florian_-_Falling_Leaves.JPG
|
|
||||||
leaf_cycle,fr,https://wiki.openstreetmap.org/wiki/FR:Key:leaf_cycle,2024-11-14,13,619,166,29,10.48,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Olga_Wisinger-Florian_-_Falling_Leaves.JPG/200px-Olga_Wisinger-Florian_-_Falling_Leaves.JPG
|
|
||||||
tunnel,en,https://wiki.openstreetmap.org/wiki/Key:tunnel,2025-06-16,15,1057,149,19,29.57,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Boston_Tunnel_Entrance.jpg/200px-Boston_Tunnel_Entrance.jpg
|
|
||||||
tunnel,fr,https://wiki.openstreetmap.org/wiki/FR:Key:tunnel,2025-01-24,16,921,140,16,29.57,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Boston_Tunnel_Entrance.jpg/200px-Boston_Tunnel_Entrance.jpg
|
|
||||||
generator:source,en,https://wiki.openstreetmap.org/wiki/Key:generator:source,2025-04-21,11,533,123,29,0.24,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Schematic_representation_different_types_of_energy.jpg/200px-Schematic_representation_different_types_of_energy.jpg
|
|
||||||
generator:source,fr,https://wiki.openstreetmap.org/wiki/FR:Key:generator:source,2025-04-21,11,534,139,29,0.24,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Schematic_representation_different_types_of_energy.jpg/200px-Schematic_representation_different_types_of_energy.jpg
|
|
||||||
generator:method,en,https://wiki.openstreetmap.org/wiki/Key:generator:method,2023-11-26,11,482,151,39,33.48,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Huntly_Power_Station.JPG/200px-Huntly_Power_Station.JPG
|
|
||||||
generator:method,fr,https://wiki.openstreetmap.org/wiki/FR:Key:generator:method,2023-06-19,9,396,101,13,33.48,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Huntly_Power_Station.JPG/200px-Huntly_Power_Station.JPG
|
|
||||||
material,en,https://wiki.openstreetmap.org/wiki/Key:material,2025-05-01,12,883,332,114,132.61,https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Stapel_bakstenen_-_Pile_of_bricks_2005_Fruggo.jpg/200px-Stapel_bakstenen_-_Pile_of_bricks_2005_Fruggo.jpg
|
|
||||||
material,fr,https://wiki.openstreetmap.org/wiki/FR:Key:material,2023-07-20,9,647,280,115,132.61,https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Stapel_bakstenen_-_Pile_of_bricks_2005_Fruggo.jpg/200px-Stapel_bakstenen_-_Pile_of_bricks_2005_Fruggo.jpg
|
|
||||||
generator:type,en,https://wiki.openstreetmap.org/wiki/Key:generator:type,2023-11-21,10,1338,330,29,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
tactile_paving,en,https://wiki.openstreetmap.org/wiki/Key:tactile_paving,2025-08-10,22,2054,298,44,156.14,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Tactile_paving.jpg/200px-Tactile_paving.jpg
|
|
||||||
tactile_paving,fr,https://wiki.openstreetmap.org/wiki/FR:Key:tactile_paving,2023-07-23,19,1277,164,47,156.14,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Detectable_Warnings.jpg/200px-Detectable_Warnings.jpg
|
|
||||||
water,en,https://wiki.openstreetmap.org/wiki/Key:water,2024-10-13,16,1261,261,38,15.41,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Nowitna_river.jpg/200px-Nowitna_river.jpg
|
|
||||||
water,fr,https://wiki.openstreetmap.org/wiki/FR:Key:water,2024-12-18,17,1516,313,61,15.41,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Nowitna_river.jpg/200px-Nowitna_river.jpg
|
|
||||||
generator:output:electricity,en,https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity,2024-01-01,10,296,40,9,124.37,https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Eoliennes_Gaspesie.jpg/200px-Eoliennes_Gaspesie.jpg
|
|
||||||
generator:output:electricity,fr,https://wiki.openstreetmap.org/wiki/FR:Key:generator:output:electricity,2022-04-25,9,371,83,10,124.37,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Huntly_Power_Station.JPG/200px-Huntly_Power_Station.JPG
|
|
||||||
addr:city:simc,en,https://wiki.openstreetmap.org/wiki/Key:addr:city:simc,2022-04-15,9,200,66,10,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
entrance,en,https://wiki.openstreetmap.org/wiki/Key:entrance,2025-08-30,19,1422,255,51,158.12,https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/SF_City_Hall_door.JPG/200px-SF_City_Hall_door.JPG
|
|
||||||
entrance,fr,https://wiki.openstreetmap.org/wiki/FR:Key:entrance,2023-07-25,16,834,166,37,158.12,https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/SF_City_Hall_door.JPG/200px-SF_City_Hall_door.JPG
|
|
||||||
created_by,en,https://wiki.openstreetmap.org/wiki/Key:created_by,2025-08-06,18,1225,355,16,100,https://wiki.openstreetmap.org/w/images/9/9e/Created_by_JOSM_15_6115_de.png
|
|
||||||
roof:levels,en,https://wiki.openstreetmap.org/wiki/Key:roof:levels,2025-05-07,12,654,140,18,6.72,https://wiki.openstreetmap.org/w/images/thumb/6/61/Roof_sample_6.png/200px-Roof_sample_6.png
|
|
||||||
roof:levels,fr,https://wiki.openstreetmap.org/wiki/FR:Key:roof:levels,2025-04-05,11,642,133,18,6.72,https://wiki.openstreetmap.org/w/images/thumb/6/61/Roof_sample_6.png/200px-Roof_sample_6.png
|
|
||||||
bus,en,https://wiki.openstreetmap.org/wiki/Key:bus,2024-09-29,16,885,149,12,238.72,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Bus_aus_Zusatzzeichen_1024-14.svg/200px-Bus_aus_Zusatzzeichen_1024-14.svg.png
|
|
||||||
bus,fr,https://wiki.openstreetmap.org/wiki/FR:Key:bus,2021-07-21,9,219,73,11,238.72,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
addr:floor,en,https://wiki.openstreetmap.org/wiki/Key:addr:floor,2024-09-02,12,458,82,11,78.44,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
addr:floor,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:floor,2025-08-23,15,1653,150,77,78.44,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
sidewalk,en,https://wiki.openstreetmap.org/wiki/Key:sidewalk,2025-08-26,23,2248,393,39,32.48,https://wiki.openstreetmap.org/w/images/thumb/b/b9/Sidewalk_and_zebra-crossing.jpg/200px-Sidewalk_and_zebra-crossing.jpg
|
|
||||||
sidewalk,fr,https://wiki.openstreetmap.org/wiki/FR:Key:sidewalk,2025-05-01,16,1177,215,16,32.48,https://wiki.openstreetmap.org/w/images/thumb/b/b9/Sidewalk_and_zebra-crossing.jpg/200px-Sidewalk_and_zebra-crossing.jpg
|
|
||||||
attribution,en,https://wiki.openstreetmap.org/wiki/Key:attribution,2024-09-14,14,372,98,17,100,https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Commons-emblem-hand.svg/150px-Commons-emblem-hand.svg.png
|
|
||||||
nysgissam:nysaddresspointid,en,https://wiki.openstreetmap.org/wiki/Key:nysgissam:nysaddresspointid,2022-09-14,39,3047,115,5,100,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/NYSGISSAM_-_Single_point_inside_building.png/300px-NYSGISSAM_-_Single_point_inside_building.png
|
|
||||||
operator:wikidata,en,https://wiki.openstreetmap.org/wiki/Key:operator:wikidata,2024-08-10,14,347,97,11,109.59,https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Wikidata-logo-en.svg/200px-Wikidata-logo-en.svg.png
|
|
||||||
operator:wikidata,fr,https://wiki.openstreetmap.org/wiki/FR:Key:operator:wikidata,2023-02-13,11,309,87,11,109.59,https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Wikidata-logo-en.svg/200px-Wikidata-logo-en.svg.png
|
|
||||||
direction,en,https://wiki.openstreetmap.org/wiki/Key:direction,2025-08-30,17,1515,169,34,114.26,https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Kompas_Sofia.JPG/200px-Kompas_Sofia.JPG
|
|
||||||
direction,fr,https://wiki.openstreetmap.org/wiki/FR:Key:direction,2024-02-23,23,1114,132,26,114.26,https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Kompas_Sofia.JPG/200px-Kompas_Sofia.JPG
|
|
||||||
note,en,https://wiki.openstreetmap.org/wiki/Key:note,2025-05-20,11,416,85,12,338.94,https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Wlm-icon-note-red.svg/200px-Wlm-icon-note-red.svg.png
|
|
||||||
note,fr,https://wiki.openstreetmap.org/wiki/FR:Key:note,2020-10-01,10,347,82,13,338.94,https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Wlm-icon-note-red.svg/200px-Wlm-icon-note-red.svg.png
|
|
||||||
addr:conscriptionnumber,en,https://wiki.openstreetmap.org/wiki/Key:addr:conscriptionnumber,2022-03-14,13,607,95,15,100,https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/D%C4%9B%C4%8D%C3%ADn%2C_Tyr%C5%A1ova_3%2C_domovn%C3%AD_%C4%8D%C3%ADsla.jpg/200px-D%C4%9B%C4%8D%C3%ADn%2C_Tyr%C5%A1ova_3%2C_domovn%C3%AD_%C4%8D%C3%ADsla.jpg
|
|
||||||
tiger:zip_left,en,https://wiki.openstreetmap.org/wiki/Key:tiger:zip_left,2021-12-03,26,3319,53,1,100,https://wiki.openstreetmap.org/w/images/c/c9/Logo.png
|
|
||||||
opening_hours,en,https://wiki.openstreetmap.org/wiki/Key:opening_hours,2025-08-16,49,5565,353,25,13.51,https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Neon_Internet_Cafe_open_24_hours.jpg/200px-Neon_Internet_Cafe_open_24_hours.jpg
|
|
||||||
opening_hours,fr,https://wiki.openstreetmap.org/wiki/FR:Key:opening_hours,2025-08-18,35,3748,225,17,13.51,https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Neon_Internet_Cafe_open_24_hours.jpg/200px-Neon_Internet_Cafe_open_24_hours.jpg
|
|
||||||
website,en,https://wiki.openstreetmap.org/wiki/Key:website,2025-01-26,22,1098,188,31,154.75,https://upload.wikimedia.org/wikipedia/commons/1/10/Vista-www.png
|
|
||||||
website,fr,https://wiki.openstreetmap.org/wiki/FR:Key:website,2023-01-04,14,672,133,25,154.75,https://upload.wikimedia.org/wikipedia/commons/1/10/Vista-www.png
|
|
||||||
parking,en,https://wiki.openstreetmap.org/wiki/Key:parking,2025-07-06,14,922,190,32,2.25,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/IE_road_sign_F-200.svg/200px-IE_road_sign_F-200.svg.png
|
|
||||||
parking,fr,https://wiki.openstreetmap.org/wiki/FR:Key:parking,2025-07-06,11,660,157,37,2.25,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/IE_road_sign_F-200.svg/200px-IE_road_sign_F-200.svg.png
|
|
||||||
ref:bygningsnr,en,https://wiki.openstreetmap.org/wiki/Key:ref:bygningsnr,2023-06-27,10,179,69,10,100,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
addr:unit,en,https://wiki.openstreetmap.org/wiki/Key:addr:unit,2025-08-13,9,174,71,12,11.48,https://wiki.openstreetmap.org/w/images/thumb/7/76/Osm_element_node.svg/30px-Osm_element_node.svg.png
|
|
||||||
addr:unit,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:unit,2025-08-23,15,1653,150,77,11.48,https://wiki.openstreetmap.org/w/images/thumb/e/e9/Housenumber-karlsruhe-de.png/200px-Housenumber-karlsruhe-de.png
|
|
||||||
wikidata,en,https://wiki.openstreetmap.org/wiki/Key:wikidata,2025-05-31,24,1616,239,49,345.95,https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Wikidata-logo-en.svg/200px-Wikidata-logo-en.svg.png
|
|
||||||
wikidata,fr,https://wiki.openstreetmap.org/wiki/FR:Key:wikidata,2020-10-01,19,997,139,20,345.95,https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Wikidata-logo-en.svg/200px-Wikidata-logo-en.svg.png
|
|
||||||
tiger:zip_right,en,https://wiki.openstreetmap.org/wiki/Key:tiger:zip_right,2021-12-03,26,3319,53,1,100,https://wiki.openstreetmap.org/w/images/c/c9/Logo.png
|
|
||||||
ref:ruian:building,en,https://wiki.openstreetmap.org/wiki/Key:ref:ruian:building,2022-09-01,9,203,71,11,100,https://wiki.openstreetmap.org/w/images/thumb/5/58/Osm_element_node_no.svg/30px-Osm_element_node_no.svg.png
|
|
||||||
tourism,en,https://wiki.openstreetmap.org/wiki/Key:tourism,2025-02-28,11,1032,227,116,401.64,https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Tourists_in_Munich_at_the_Marienplatz%2C_2011.JPG/200px-Tourists_in_Munich_at_the_Marienplatz%2C_2011.JPG
|
|
||||||
tourism,fr,https://wiki.openstreetmap.org/wiki/FR:Key:tourism,2019-09-14,13,581,208,103,401.64,https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Tourists_in_Munich_at_the_Marienplatz%2C_2011.JPG/200px-Tourists_in_Munich_at_the_Marienplatz%2C_2011.JPG
|
|
||||||
|
|
|
Loading…
Add table
Add a link
Reference in a new issue