mirror of
https://gitlab.com/news-flash/article_scraper.git
synced 2025-07-07 16:15:32 +02:00
Compare commits
59 commits
article_sc
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9f349f8c6f | ||
|
498008f630 | ||
|
ee53f58aeb | ||
|
06990acbc0 | ||
|
f361392c04 | ||
|
9b374a28c7 | ||
|
b92500fca2 | ||
|
0978335d3b | ||
|
9f56ed03b8 | ||
|
8cfcd6d9f3 | ||
|
ca1cc47af1 | ||
|
7c658a4ba8 | ||
|
89eb87fa85 | ||
|
7fcb781c68 | ||
|
11ee29feda | ||
|
b3ce28632d | ||
|
6932902b7b | ||
|
c16e11fdda | ||
|
f4e4e64b9e | ||
|
df8ebcbb35 | ||
|
e01c8e9d34 | ||
|
06018d98d4 | ||
|
11e9261bf2 | ||
|
3e5654e197 | ||
|
65b26370a2 | ||
|
a80b8a8274 | ||
|
eee7ffee05 | ||
|
e4140ff093 | ||
|
689a72e6cd | ||
|
0dcebe8b49 | ||
|
a1ee3b22f9 | ||
|
b13673ce3b | ||
|
ed8a83708b | ||
|
f9812b556c | ||
|
acb7d1d000 | ||
|
6116ba38ae | ||
|
8c7cdacd26 | ||
|
0133b20f06 | ||
|
1584649eb4 | ||
|
2c76a89f9d | ||
|
9aa6478e3c | ||
|
b91014c685 | ||
|
9c857a1481 | ||
|
3211b91bad | ||
|
7a4f5c500d | ||
|
a7e8661a09 | ||
|
eb1bfdbca0 | ||
|
40f065d9cd | ||
|
db007f752c | ||
|
bf7a89fef7 | ||
|
345518253a | ||
|
42eb9daf65 | ||
|
d562d41b81 | ||
|
be40383b1a | ||
|
d62aa8c31a | ||
|
fcec0d83ee | ||
|
fdb8d9a97e | ||
|
4fd41d98cc | ||
|
e32015c1d0 |
41 changed files with 6083 additions and 321 deletions
|
@ -4,12 +4,14 @@ stages:
|
|||
|
||||
run-build:
|
||||
stage: build
|
||||
image: rust:latest
|
||||
image: rust:1.86
|
||||
before_script:
|
||||
- rustup component add rustfmt
|
||||
- rustup component add clippy
|
||||
- export LIBXML2=$(pkg-config libxml-2.0 --variable=libdir)/libxml2.so
|
||||
script:
|
||||
- rustc --version && cargo --version
|
||||
- echo $LIBXML2
|
||||
- cargo fmt -- --check
|
||||
- cargo clippy --all-targets --all-features -- -D warnings
|
||||
- cargo build --release --jobs 1
|
||||
- cargo build --release
|
||||
|
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
|||
[submodule "article_scraper/ftr-site-config"]
|
||||
path = article_scraper/ftr-site-config
|
||||
url = https://github.com/jangernert/ftr-site-config.git
|
||||
branch = news-flash
|
||||
url = https://github.com/fivefilters/ftr-site-config.git
|
||||
branch = master
|
||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -1,6 +1,10 @@
|
|||
[workspace]
|
||||
members = ["article_scraper", "article_scraper_cli"]
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"article_scraper",
|
||||
"article_scraper_cli",
|
||||
]
|
||||
[workspace.package]
|
||||
version = "2.1.2"
|
||||
authors = ["Jan Lukas Gernert <jangernert@gmail.com>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-or-later"
|
||||
repository = "https://gitlab.com/news-flash/article_scraper"
|
|
@ -1,31 +1,33 @@
|
|||
[package]
|
||||
name = "article_scraper"
|
||||
version = "2.0.0"
|
||||
authors = ["Jan Lukas Gernert <jangernert@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later"
|
||||
description = "Scrap article contents from the web. Powered by fivefilters full text feed configurations & mozilla readability."
|
||||
repository = "https://gitlab.com/news-flash/article_scraper"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
readme = "../Readme.md"
|
||||
keywords = ["article", "scrape", "full-text", "readability"]
|
||||
exclude = ["resources/tests"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
thiserror = "2.0"
|
||||
libxml = "0.3"
|
||||
reqwest = { version = "0.11", features = ["json", "native-tls", "gzip", "brotli", "stream"] }
|
||||
tokio = { version = "1.27", features = ["macros", "fs", "io-util"] }
|
||||
url = "2.3"
|
||||
regex = "1.8"
|
||||
reqwest = { version = "0.12", features = ["stream"] }
|
||||
tokio = { version = "1", features = ["macros", "fs", "io-util"] }
|
||||
url = "2.5"
|
||||
regex = "1.11"
|
||||
encoding_rs = "0.8"
|
||||
chrono = "0.4"
|
||||
base64 = "0.21"
|
||||
image = "0.24"
|
||||
base64 = "0.22"
|
||||
image = "0.25"
|
||||
log = "0.4"
|
||||
rust-embed="6.6"
|
||||
once_cell = "1.17"
|
||||
rust-embed="8.6"
|
||||
once_cell = "1.20"
|
||||
escaper = "0.1"
|
||||
futures = "0.3"
|
||||
unic-emoji-char = "0.9"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.10"
|
||||
env_logger = "0.11"
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 40796c9a9db47189121e844abbf5d3fbce02c9f5
|
||||
Subproject commit 69aa220193d99427d3822fabccdfaeede56cd532
|
|
@ -122,7 +122,7 @@
|
|||
|
||||
|
||||
|
||||
<img alt="" decoding="async" height="190" loading="lazy" src="https://heise.cloudimg.io/width/696/q50.png-lossy-50.webp-lossy-50.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png" srcset="https://heise.cloudimg.io/width/336/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 336w, https://heise.cloudimg.io/width/1008/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 1008w, https://heise.cloudimg.io/width/1392/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 2x " width="696" data-old-src="/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png"/>
|
||||
<img alt="" height="190" src="https://heise.cloudimg.io/width/696/q50.png-lossy-50.webp-lossy-50.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png" srcset="https://heise.cloudimg.io/width/336/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 336w, https://heise.cloudimg.io/width/1008/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 1008w, https://heise.cloudimg.io/width/1392/q30.png-lossy-30.webp-lossy-30.foil1/_www-heise-de_/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png 2x " width="696" data-old-src="/imgs/18/4/1/5/0/0/2/4/tr-artikelbanner_insta_1830x500_11-2022-b1b5cf659568ea2b.png"/>
|
||||
|
||||
|
||||
|
||||
|
|
52
article_scraper/resources/tests/ftr/spiegel-1/expected.html
Normal file
52
article_scraper/resources/tests/ftr/spiegel-1/expected.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
<article><section data-article-el="body">
|
||||
<div data-area="top_element>image">
|
||||
<figure>
|
||||
<div data-sara-component="{"id":"51d712c3-9d59-4234-b369-6dc5de953038","name":"image","title":"\u003cp\u003e»Barbie« soll im Libanon nicht gezeigt werden\u003c/p\u003e","type":"media"}">
|
||||
<picture>
|
||||
<source srcset="https://cdn.prod.www.spiegel.de/images/51d712c3-9d59-4234-b369-6dc5de953038_w948_r2.1283783783783785_fpx55_fpy28.webp 948w, https://cdn.prod.www.spiegel.de/images/51d712c3-9d59-4234-b369-6dc5de953038_w520_r2.1283783783783785_fpx55_fpy28.webp 520w" sizes="(max-width: 519px) 100vw, (min-width: 520px) and (max-width: 719px) 520px, (min-width: 720px) and (max-width: 919px) 100vw, (min-width: 920px) and (max-width: 1011px) 920px, (min-width: 1012px) 948px" type="image/webp">
|
||||
<img data-image-el="img" src="https://cdn.prod.www.spiegel.de/images/51d712c3-9d59-4234-b369-6dc5de953038_w948_r2.1283783783783785_fpx55_fpy28.jpg" width="948" height="445" title="»Barbie« soll im Libanon nicht gezeigt werden" alt="»Barbie« soll im Libanon nicht gezeigt werden" data-image-animation-origin="0df59b8e-c667-4bf5-b686-3266795cecf1"/>
|
||||
</source></picture>
|
||||
</div>
|
||||
<figcaption>
|
||||
<p>»Barbie« soll im Libanon nicht gezeigt werden</p>
|
||||
<span>
|
||||
Foto: <p>- / dpa</p>
|
||||
</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div data-area="body">
|
||||
<div data-sara-click-el="body_element">
|
||||
<p>Im <a href="https://www.spiegel.de/thema/libanon/" data-link-flag="spon" target="_blank">Libanon</a> soll der erfolgreiche <a href="https://www.spiegel.de/thema/hollywood/" data-link-flag="spon" target="_blank">Hollywood</a>-Streifen »Barbie« verboten werden, weil dieser der Regierung zufolge »Werbung für Homosexualität und Geschlechtsumwandlung« macht. Der Film verstoße gegen die »moralischen und religiösen Werte« des Landes, erklärte der libanesische Kulturminister Mohammed Mourtada. Ursprünglich sollte der Blockbuster, der weltweit <a href="https://www.spiegel.de/kultur/kino/barbie-hat-eine-milliarde-us-dollar-weltweit-eingespielt-a-61b0c5f7-e354-4ce9-a021-8c3305a29ff7" data-link-flag="spon" target="_blank">bereits mehr als eine Milliarde Dollar </a>(rund 910 Millionen Euro) eingespielt hat, ab dem 31. August im Libanon gezeigt werden.</p>
|
||||
</div>
|
||||
|
||||
<div data-sara-click-el="body_element">
|
||||
<p>Mourtada erklärte weiter, »Barbie« unterstütze die »Ablehnung der Vormundschaft des Vaters«, ziehe die Rolle der Mutter ins Lächerliche und stelle die Ehe und die Gründung einer Familie infrage.</p>
|
||||
</div>
|
||||
<div data-sara-click-el="body_element">
|
||||
|
||||
|
||||
<div data-settings="{"consentType":"thirdparty"}">
|
||||
|
||||
An dieser Stelle finden Sie einen externen Inhalt von Twitter,
|
||||
der den Artikel ergänzt und von der Redaktion empfohlen wird. Sie können ihn sich mit einem Klick anzeigen lassen
|
||||
und wieder ausblenden.
|
||||
</div>
|
||||
|
||||
<div data-sara-click-el="body_element">
|
||||
<p>In dem Film von US-Regisseurin Greta Gerwig verlassen <a href="https://www.spiegel.de/thema/barbie/" data-link-flag="spon" target="_blank">Barbie</a> und Ken, gespielt von den Superstars <a href="https://www.spiegel.de/thema/margot-robbie/" data-link-flag="spon" target="_blank">Margot Robbie</a> und <a href="https://www.spiegel.de/thema/ryan_gosling/" data-link-flag="spon" target="_blank">Ryan Gosling</a>, die pinkfarbene Plastikwelt Barbieland und lernen in <a href="https://www.spiegel.de/thema/los_angeles/" data-link-flag="spon" target="_blank">Los Angeles</a> das echte Leben kennen.</p>
|
||||
</div>
|
||||
|
||||
<div data-sara-click-el="body_element">
|
||||
<h3>Community unter Druck</h3><p>Der Libanon gilt in Bezug auf Homosexualität als toleranter als andere arabische Staaten. Allerdings haben religiöse Organisationen wie die radikalislamische <a href="https://www.spiegel.de/thema/hisbollah/" data-link-flag="spon" target="_blank">Hisbollah</a> einen großen Einfluss auf soziale und kulturelle Einrichtungen.</p><p>Immer wieder wurden in den vergangenen Jahren Veranstaltungen der <a href="https://www.spiegel.de/kultur/musik/mashrou-leila-regenbogen-auf-halbmast-a-1e6bdb86-e0e4-4ffa-8f35-5aac4cb5d1e1" data-link-flag="spon" target="_blank">libanesischen LGBTQ+-Community </a>abgesagt. Zudem steht Homosexualität im Libanon nach wie vor unter Strafe.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-sara-click-el="body_element">
|
||||
<p>Die englische Abkürzung LGBTQ+ steht für lesbisch, schwul, bisexuell, transgender, queer und andere Geschlechtsidentitäten.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section></article>
|
3988
article_scraper/resources/tests/ftr/spiegel-1/source.html
Normal file
3988
article_scraper/resources/tests/ftr/spiegel-1/source.html
Normal file
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
<article><iframe id="video" width="100%" height="100%" src="https://www.youtube.com/embed/8KjaIumu-jI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" title="RIGGED! Arena Shuffler is BROKEN | 13 Land Mono Red Burn"><empty></empty></iframe></article>
|
||||
<article><iframe id="video" width="480" height="360" aspect-ratio="auto" src="https://www.youtube.com/embed/8KjaIumu-jI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" title="RIGGED! Arena Shuffler is BROKEN | 13 Land Mono Red Burn"><empty></empty></iframe></article>
|
|
@ -27,7 +27,18 @@
|
|||
<p>Forrest Jones said that anything that comes into contact with any of the previous guest’s skin should be taken out and washed every time the room is made, but that even the fanciest hotels don’t always do so. "Hotels are getting away from comforters. Blankets are here to stay, however. But some hotels are still hesitant about washing them every day if they think they can get out of it," he said.</p>
|
||||
|
||||
<div>
|
||||
|
||||
<div data-video-id="4685984084001" data-embed="default" data-player="2d3d4a83-ba40-464e-9bfb-2804b076bf67" data-account="624246174001" id="4685984084001" role="region" aria-label="video player">
|
||||
|
||||
|
||||
|
||||
|
||||
<p><span>Play Video</span></p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<p>Video shows bed bug infestation at New York hotel</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
|
||||
<p>At root</p>
|
||||
|
||||
|
||||
|
||||
<iframe width="480" height="360" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen="" aspect-ratio="auto"><empty></empty></iframe>
|
||||
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""><empty></empty></iframe>
|
||||
<iframe src="https://player.vimeo.com/video/32246206?color=ffffff+title=0+byline=0+portrait=0" width="500" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""><empty></empty></iframe>
|
||||
<p>In a paragraph</p>
|
||||
|
||||
<p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""><empty></empty></iframe></p>
|
||||
<p>In a div</p>
|
||||
|
||||
<div><iframe width="480" height="360" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen="" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<h2>Foo</h2>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -250,7 +250,9 @@
|
|||
capable HDR 10 standard. That makes sense since it's
|
||||
more widely supported, but it would have been nice
|
||||
to see Dolby's, too.</p>
|
||||
|
||||
<p>
|
||||
<iframe allowfullscreen="" frameborder="0" gesture="media" height="360" src="https://www.youtube.com/embed/c8aFcHFu8QM" width="480" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>And speaking of Dolby technology, Microsoft is also
|
||||
highlighting Atmos support on the One X, just like
|
||||
it did with the One S. The company's app lets you
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<ul>
|
||||
<li>
|
||||
<div id="attachment_994">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" target="_blank"><img aria-describedby="caption-attachment-994" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" alt="The about:restartrequired error page, saying "Sorry. We just need to do one small thing to keep going. Nightly has just been updated in the background. Click Restart Nightly to complete the update. We will restore all your pages, windows and tabs afterwards, so you can be on your way quickly.", followed by a button to restart Nightly." width="1600" height="805" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_0.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-300x151.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-600x302.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-768x386.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-1536x773.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-1000x503.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-994">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" target="_blank"><img aria-describedby="caption-attachment-994" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" alt="The about:restartrequired error page, saying "Sorry. We just need to do one small thing to keep going. Nightly has just been updated in the background. Click Restart Nightly to complete the update. We will restore all your pages, windows and tabs afterwards, so you can be on your way quickly.", followed by a button to restart Nightly." width="1600" height="805" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_0.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-300x151.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-600x302.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-768x386.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-1536x773.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_0-1000x503.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-994">
|
||||
Users who run multiple user profiles concurrently will probably see this less!
|
||||
</p>
|
||||
</div>
|
||||
|
@ -118,7 +118,7 @@
|
|||
<ul>
|
||||
<li>
|
||||
<div id="attachment_995">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" target="_blank"><img aria-describedby="caption-attachment-995" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" alt="A table showing the total number of remaining bugs for the MVP to make the DevTools Fission-compatible." width="1600" height="192" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_1.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-300x36.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-600x72.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-768x92.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-1536x184.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-1000x120.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-995">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" target="_blank"><img aria-describedby="caption-attachment-995" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" alt="A table showing the total number of remaining bugs for the MVP to make the DevTools Fission-compatible." width="1600" height="192" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_1.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-300x36.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-600x72.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-768x92.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-1536x184.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_1-1000x120.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-995">
|
||||
Our DevTools are ready for Fission (out-of-process iframes)!
|
||||
</p>
|
||||
</div>
|
||||
|
@ -130,7 +130,7 @@
|
|||
<ul>
|
||||
<li>
|
||||
<div id="attachment_996">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" target="_blank"><img aria-describedby="caption-attachment-996" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" alt="A table showing the total number of remaining bugs for the MVP to make Marionette Fission-compatible." width="1600" height="189" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_2.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-300x35.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-600x71.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-768x91.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-1536x181.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-1000x118.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-996">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" target="_blank"><img aria-describedby="caption-attachment-996" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" alt="A table showing the total number of remaining bugs for the MVP to make Marionette Fission-compatible." width="1600" height="189" srcset="https://blog.nightly.mozilla.org/files/2020/12/headlines85_2.png 1600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-300x35.png 300w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-600x71.png 600w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-768x91.png 768w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-1536x181.png 1536w, https://blog.nightly.mozilla.org/files/2020/12/headlines85_2-1000x118.png 1000w" sizes="(max-width: 1600px) 100vw, 1600px"/></a></p><p id="caption-attachment-996">
|
||||
Marionette, the framework that allows Firefox to be tested with automation, is now Fission compatible too!
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7"/>
|
||||
</td>
|
||||
<td/>
|
||||
<td><empty></empty></td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7"/>
|
||||
</td>
|
||||
|
@ -80,7 +80,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<audio src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3" controls=""/>
|
||||
<audio src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3" controls=""><empty></empty></audio>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -109,7 +109,7 @@
|
|||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7"/>
|
||||
</td>
|
||||
<td/>
|
||||
<td><empty></empty></td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7"/>
|
||||
</td>
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
</p>
|
||||
</td>
|
||||
<td width="10">
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" />
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" />
|
||||
</td>
|
||||
<td width="166" valign="top">
|
||||
<table width="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#C8FFC8">
|
||||
|
@ -204,14 +204,14 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td height="50" bgcolor="#ECFFEC">
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97" width="1" height="1" /><b><font size="-1">きょうの記念日</font></b><br />
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97" width="1" height="1" /><b><font size="-1">きょうの記念日</font></b><br />
|
||||
<br />
|
||||
<a href="../../../../366/kinenbi/pc/01gatu/1_01.htm"><font size="-1">元旦</font></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="50" bgcolor="#ECFFEC">
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /><b><font size="-1">きょうの誕生花</font></b><br />
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /><b><font size="-1">きょうの誕生花</font></b><br />
|
||||
<br />
|
||||
<a href="../../../../366/hana/pc/01gatu/1_01.htm"><font size="-1">松(まつ)</font></a>
|
||||
</td>
|
||||
|
@ -269,14 +269,14 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td height="50" bgcolor="#ECFFEC">
|
||||
<b><font size="-1">きょうの世界昔話<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /></font></b><br />
|
||||
<b><font size="-1">きょうの世界昔話<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /></font></b><br />
|
||||
<br />
|
||||
<a href="../../../../douwa/pc/world/01/01a.htm"><font size="-1">モンゴルの十二支話</font></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="50" bgcolor="#ECFFEC">
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /><b><font size="-1">きょうの日本民話</font></b><br />
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1" /><b><font size="-1">きょうの日本民話</font></b><br />
|
||||
<br />
|
||||
<a href="../../../../douwa/pc/minwa/01/01c.html"><font size="-1">仕事の取替えっこ</font></a>
|
||||
</td>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<article><div id="readability-page-1" itemprop="articleBody">
|
||||
|
||||
<P>
|
||||
<iframe src="http://www.dailymotion.com/embed/video/x2p552m?syndication=131181" frameborder="0" width="534" height="320"><empty></empty></iframe>
|
||||
</P>
|
||||
<p>Les députés ont, sans surprise, adopté à une large majorité (438 contre 86 et 42 abstentions) le projet de loi sur le renseignement défendu par le gouvernement lors d’un vote solennel, mardi 5 mai. Il sera désormais examiné par le Sénat, puis le Conseil constitutionnel, prochainement saisi par 75 députés. Dans un souci d'apaisement, François Hollande avait annoncé par avance qu'il saisirait les Sages.</p>
|
||||
<p><strong>Revivez <a href="http://fakehost/pixels/live/2015/05/05/suivez-le-vote-de-la-loi-renseignement-en-direct_4628012_4408996.html" target="_blank">le direct du vote à l’Assemblée avec vos questions.</a></strong></p>
|
||||
<p>Ont voté contre : 10 députés socialistes (sur 288), 35 UMP (sur 198), 11 écologistes (sur 18), 11 UDI (sur 30), 12 députés Front de gauche (sur 15) et 7 non-inscrits (sur 9). <a href="http://www2.assemblee-nationale.fr/scrutins/detail/%28legislature%29/14/%28num%29/1109" target="_blank">Le détail est disponible sur le site de l'Assemblée nationale.</a></p>
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
<p>L’appareil, mis à disposition par Airbus, était arrivé à Katmandou mercredi matin avec 55 personnels de santé et humanitaires, ainsi que 25 tonnes de matériel (abris, médicaments, aide alimentaire). Un deuxième avion dépêché par Paris, qui était immobilisé aux Emirats depuis mardi avec 20 tonnes de matériel, est arrivé jeudi à Katmandou, <a href="http://www.liberation.fr/monde/2015/04/29/embouteillages-et-retards-a-l-aeroport-de-katmandou_1276612" target="_blank">dont le petit aéroport est engorgé</a> par le trafic et l’afflux d’aide humanitaire. Il devait lui aussi ramener des Français, <em>«les plus éprouvés»</em> par la catastrophe et les <em>«plus vulnérables (blessés, familles avec enfants)»</em>, selon le ministère des Affaires étrangères.</p>
|
||||
<p>2 209 Français ont été localisés sains et saufs tandis que 393 n’ont pas encore pu être joints, selon le Quai d’Orsay. Environ 400 Français ont demandé à être rapatriés dans les vols mis en place par la France.</p>
|
||||
<p>Le séisme a fait près de 5 500 morts et touche huit des 28 millions d’habitants du Népal. Des dizaines de milliers de personnes sont sans abri.</p>
|
||||
|
||||
<p>
|
||||
<iframe src="http://www.dailymotion.com/embed/video/x2oikl3" frameborder="0" width="100%" data-aspect-ratio="0.5625" data-responsive="1"><empty></empty></iframe>
|
||||
<br/></p>
|
||||
</div>
|
||||
</article>
|
||||
</section></article>
|
|
@ -16,7 +16,7 @@
|
|||
<p>The name and basic idea might sound like one of those endless score attack games like "Temple Run," but that's not the case. "Super Mario Run" is divided into hand-crafted levels with a clear end-point like any other Mario game, meaning you're essentially getting the Mario experience for $10 without needing to control his movement.</p>
|
||||
<p>$10 might seem like a bit much compared to the $0 people pay for most mobile games, but it's possible the game has $10 worth of levels to play in it. It's also not iPhone exclusive, but the Android version will launch at a later, currently unknown date. </p>
|
||||
<p>To see "Super Mario Run" in action, check out the footage below:</p>
|
||||
|
||||
<div><iframe allowfullscreen="" src="https://www.youtube.com/embed/E39ychZKnDI" frameborder="0" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
|
||||
</section>
|
||||
</article></DIV></article>
|
|
@ -28,7 +28,7 @@
|
|||
<div id="rv-player">
|
||||
<p><span>转播到腾讯微博</span></p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAJAQMAAAAB5D5xAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURQAAAKd6PdoAAAABdFJOUwBA5thmAAAAC0lEQVQI12NgwAkAABsAAVJE5KkAAAAASUVORK5CYIIvKiAgfHhHdjAwfDUwZDc5YmEzMGM3MDcxY2I5OTIyMTk4MzYyZGRlZmNlICov"/></p></div>
|
||||
|
||||
|
||||
<iframe src="http://v.qq.com/video/playview.html?vid=x033633yrm8" height="0" width="0"><empty></empty></iframe>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
<h3 id="jDDW9T">
|
||||
21) <a href="https://www.vox.com/culture/2017/12/12/16765308/last-jedi-star-wars-review-rey-carrie-fisher-poe-finn-kylo-ren" target="_blank"><em>Star Wars: The Last Jedi</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="x5htN5">
|
||||
<iframe src="https://www.youtube.com/embed/Q0CbN8sfihY?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="WdtoaT">
|
||||
I am as shocked as anyone that a <em>Star Wars</em> movie found its way onto my list — but I was bowled over by <em>The Last Jedi</em>, which may be one of the series’ best. In the hands of writer-director <a href="https://www.vox.com/culture/2017/12/13/16761916/rian-johnson-star-wars-last-jedi-looper-brick-brothers-bloom-fly-breaking-bad" target="_blank">Rian Johnson</a> (who will also oversee <a href="https://www.theverge.com/2017/11/9/16630902/star-wars-new-trilogy-rian-johnson-disney-lucasfilm" target="_blank">a new <em>Star Wars</em> trilogy</a>), <em>The Last Jedi</em> is beautiful to look at and keeps its eye on the relationships between characters and how they communicate with one another, in addition to the bigger galactic story. The same characters are back, but they seem infused with new life, and the galaxy with a new kind of hope. The movie’s best details are in the strong bonds that develop between characters, and I left the film with the realization that for the first time in my life, I loved a <em>Star Wars</em> movie. Now I understand the magic.
|
||||
</p>
|
||||
|
@ -21,7 +23,9 @@
|
|||
<h3 id="3XHosO">
|
||||
20) <a href="https://www.vox.com/2017/10/6/16434046/faces-places-review-agnes-varda-jr" target="_blank"><em>Faces Places</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="FZOPyv">
|
||||
<iframe src="https://www.youtube.com/embed/KKbjnLpxv70?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="zP5jCd">
|
||||
The unusual documentary <a href="https://www.vox.com/2017/10/6/16434046/faces-places-review-agnes-varda-jr" target="_blank"><em>Faces Places</em></a> (in French, <em>Visages Villages</em>) turns on the friendship between the accomplished street artist JR and legendary film director Agnès Varda, whose work was central to the development of the French New Wave movement. The pair (whose difference in age is 55 years) met after years of admiring each other’s work and decided to create a documentary portrait of France — by making a number of actual portraits. The film chronicles a leg of the "Inside Outside Project," a roving art initiative in which JR makes enormous portraits of people he meets and pastes them onto buildings and walls. In the film, Varda joins him, and as they talk to people around the country, they grow in their understanding of themselves and of each other. The development of their friendship, which is both affectionate and mutually sharpening, forms <em>Faces Places</em>’ emotional center.
|
||||
</p>
|
||||
|
@ -32,7 +36,9 @@
|
|||
<h3 id="R0KXNO">
|
||||
19) <a href="https://www.vox.com/summer-movies/2017/8/8/16107088/ingrid-goes-west-review-aubrey-plaza-elizabeth-olsen" target="_blank"><em>Ingrid Goes West</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="94aRXv">
|
||||
<iframe src="https://www.youtube.com/embed/xP4vD1tWbPU?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="d2ZAUw">
|
||||
<a href="https://www.vox.com/summer-movies/2017/8/8/16107088/ingrid-goes-west-review-aubrey-plaza-elizabeth-olsen" target="_blank"><em>Ingrid Goes West</em></a> is a twisted and <a href="https://www.vox.com/culture/2017/8/9/16107140/matt-spicer-interview-ingrid-goes-west-dark-comedy-aubrey-plaza-sundance?utm_campaign=vox&utm_content=chorus&utm_medium=social&utm_source=twitter" target="_blank">dark comedy</a> — part addiction narrative, part stalker story — and yet it’s set in a world that’s almost pathologically cheery: the glossy, sunny, nourishing, superfood- and superlative-loving universe of Instagram celebrity. But despite <em>Ingrid Goes West</em>’s spot-on take on that world, the best thing about the film is that it refuses to traffic in lazy buzzwords and easy skewering, particularly at the expense of young women. Instead, the movie conveys that behind every Instagram image and meltdown is a real person, with real insecurities, real feelings, and real problems. And it recognizes that living a life performed in public can be its own kind of self-deluding prison.
|
||||
</p>
|
||||
|
@ -42,7 +48,9 @@
|
|||
<h3 id="qfZ4Iv">
|
||||
18) <a href="https://www.vox.com/summer-movies/2017/7/14/15955888/review-lady-macbeth-florence-pugh" target="_blank"><em>Lady Macbeth</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="0ZWzkX">
|
||||
<iframe src="https://www.youtube.com/embed/2Z0N8ULhuUA?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="Ii1QS5">
|
||||
<a href="https://www.vox.com/summer-movies/2017/7/14/15955888/review-lady-macbeth-florence-pugh" target="_blank"><em>Lady Macbeth</em></a> is no placid costume drama. Adapted from an 1865 Russian novella by Nikolai Leskov, the movie follows Katherine (the astounding Florence Pugh), a woman in the Lady Macbeth line characterized by a potent cocktail of very few scruples and a lot of determination. She's a chilling avatar for the ways that class and privilege — both obvious and hidden — insulate some people from the consequences of their actions while damning others. <em>Lady Macbeth</em> is also a dazzling directorial debut from William Oldroyd, a thrilling combination of sex, murder, intrigue, and power plays. It’s visually stunning, each frame composed so carefully and deliberately that the wildness and danger roiling just below the surface feels even more frightening. Each scene ratchets up the tension to an explosive, chilling end.
|
||||
</p>
|
||||
|
@ -52,7 +60,9 @@
|
|||
<h3 id="JhEBod">
|
||||
17) <em>BPM (Beats Per Minute)</em>
|
||||
</h3>
|
||||
|
||||
<div id="t3derk">
|
||||
<iframe src="https://www.youtube.com/embed/2fhO2A4SL24?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="DEyp0A">
|
||||
<em>BPM (Beats Per Minute)</em> is a remarkably tender and stirring story of the Paris chapter of ACT UP, an AIDS activism group, and the young people who found themselves caught in the crosshairs of the AIDS crisis in the early 1990s. The film follows both the group's actions and the individual members’ shifting relationships to one another — enemies becoming friends, friends becoming lovers, lovers becoming caretakers — as well as their struggles with the disease wracking their community. As an account of the period, it’s riveting; as an exploration of life and love set at the urgent intersection of the political and the personal, it’s devastating.
|
||||
</p>
|
||||
|
@ -62,7 +72,9 @@
|
|||
<h3 id="jocryI">
|
||||
16) <a href="https://www.vox.com/summer-movies/2017/6/21/15837678/big-sick-review-kumail-nanjiani-emily-gordon-zoe-kazan-islam" target="_blank"><em>The Big Sick</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="ZRFycn">
|
||||
<iframe src="https://www.youtube.com/embed/PJmpSMRQhhs?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="DqZc5Q">
|
||||
Few 2017 movies could top the charm and tenderness of <a href="https://www.vox.com/summer-movies/2017/6/21/15837678/big-sick-review-kumail-nanjiani-emily-gordon-zoe-kazan-islam" target="_blank"><em>The Big Sick</em></a>, which hits all the right romantic comedy notes with one unusual distinction: It feels like real life. That’s probably because <em>The Big Sick</em> is written by <a href="https://www.vox.com/2017/11/22/16687092/the-big-sick-kumail-nanjiani-emily-gordon-real-story" target="_blank">real-life married couple</a> Emily V. Gordon and <em>Silicon Valley</em>'s Kumail Nanjiani, and based on their real-life romance. <em>The Big Sick</em> — which stars Nanjiani as a version of himself, alongside Zoe Kazan as Emily — is funny and sweet while not backing away from matters that romantic comedies don’t usually touch on, like serious illness, struggles in long-term marriages, and religion. As it tells the couple’s story, which takes a serious turn when Emily falls ill with a mysterious infection and her parents (played by Holly Hunter and Ray Romano) come to town, it becomes a funny and wise story about real love.
|
||||
</p>
|
||||
|
@ -72,7 +84,9 @@
|
|||
<h3 id="dFyVjw">
|
||||
15) <a href="https://www.vox.com/culture/2017/9/10/16277234/mother-review-aronofsky-lawrence-bardem-tiff" target="_blank"><em>Mother!</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="kUMpyj">
|
||||
<iframe src="https://www.youtube.com/embed/XpICoc65uh0?rel=0&amp;start=17" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="LA1s4n">
|
||||
There’s so much pulsing beneath <a href="https://www.vox.com/culture/2017/9/10/16277234/mother-review-aronofsky-lawrence-bardem-tiff" target="_blank">the surface of <em>Mother!</em></a> that it’s hard to grab on to just one theme as what it “means.” It’s full-on apocalyptic fiction, and like all stories of apocalypse, it’s intended to draw back the veil on reality and show us what’s really beneath. And this movie gets wild: If its gleeful cracking apart of traditional theologies doesn’t get you (there’s a lot of Catholic folk imagery here, complete with an Ash Wednesday-like mud smearing on the foreheads of the faithful), its bonkers scenes of chaos probably will. <em>Mother!</em> is a movie designed to provoke fury, ecstasy, madness, catharsis, and more than a little awe. Watching it, and then participating in the flurry of arguments and discussions unpacking it, was among my best moviegoing experiences of 2017.
|
||||
</p>
|
||||
|
@ -82,7 +96,9 @@
|
|||
<h3 id="PL5PTS">
|
||||
14) <a href="https://www.vox.com/culture/2017/7/7/15925272/ghost-story-review-rooney-mara-casey-affleck" target="_blank"><em>A Ghost Story</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="76I1cH">
|
||||
<iframe src="https://www.youtube.com/embed/0Vb0F_CN83E?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="JWA6Pb">
|
||||
Director <a href="https://www.vox.com/summer-movies/2017/7/13/15960236/david-lowery-ghost-story-interview" target="_blank">David Lowery</a> filmed <a href="https://www.vox.com/culture/2017/7/7/15925272/ghost-story-review-rooney-mara-casey-affleck" target="_blank"><em>A Ghost Story</em></a> in secret, then premiered it at the Sundance Film Festival to critical acclaim. The movie starts out being about a grieving widow (Rooney Mara) trying to live through the pain of losing her beloved husband, but it soon shifts focus to the ghost of her husband (Casey Affleck, covered in a sheet), evolving into a compelling rumination on the nature of time, memory, history, and the universe. Bathed in warm humor and wistful longing, it's a film that stays with you long after it’s over, a lingering reminder of the inextricable link between love and place.
|
||||
</p>
|
||||
|
@ -92,7 +108,9 @@
|
|||
<h3 id="rRIM9r">
|
||||
13) <a href="https://www.vox.com/2017/10/24/16523642/square-review-ruben-ostlund-claes-bang-elisabeth-moss" target="_blank"><em>The Square</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="z1g0Cs">
|
||||
<iframe src="https://www.youtube.com/embed/EUzRjRv0Ib0?rel=0" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="NavzzU">
|
||||
Winner of the Palme d’Or at the 2017 Cannes Film Festival, <a href="https://www.vox.com/2017/10/24/16523642/square-review-ruben-ostlund-claes-bang-elisabeth-moss" target="_blank"><em>The Square</em></a> is a hilariously needling comedy about the contemporary art world, as well as the kind of idealistic liberalism that is tough to maintain in the face of real problems. The outstanding Claes Bang stars as Christian, a curator whose cluelessness leads him into some outlandishly rough spots, with Elisabeth Moss in a too-short but brilliant part as an American journalist who won’t let him get away with his shenanigans. It’s a heady film with a lot of ideas ricocheting around — and a <em>lot</em> of uncomfortable satire — but if you (like me) are the sort of viewer who loves that stuff, its sly jabs at the veneer of civilization that keeps the social contract intact are intoxicating.
|
||||
</p>
|
||||
|
@ -102,7 +120,9 @@
|
|||
<h3 id="Px2hT6">
|
||||
12) <a href="https://www.vox.com/culture/2017/7/17/15984026/dunkirk-review-nolan-rylance-hardy-styles-spoilers" target="_blank"><em>Dunkirk</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="TDSYe7">
|
||||
<iframe src="https://www.youtube.com/embed/F-eMt3SrfFU?rel=0&amp;start=24" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="MLatLf">
|
||||
<a href="https://www.vox.com/culture/2017/7/17/15984026/dunkirk-review-nolan-rylance-hardy-styles-spoilers" target="_blank"><em>Dunkirk</em></a>, a true cinematic achievement from acclaimed director Christopher Nolan, backs off conventional notions of narrative and chronology as much as possible, while leaning headfirst into everything else that makes a movie a visceral work of art aimed at the senses: the images, the sounds, the scale, the swelling vibrations of it all. You can’t smell the sea spray, but your brain may trick you into thinking you can. Nolan’s camera pushes the edges of the screen as far as it can as <em>Dunkirk</em> engulfs the audience in something that feels like a lot more than a war movie. It’s a symphony for the brave and broken, and it resolves in a major key — but one with an undercurrent of sorrow, and of sober warning. Courage in the face of danger is not just for characters in movies.
|
||||
</p>
|
||||
|
@ -112,7 +132,9 @@
|
|||
<h3 id="CPlXz5">
|
||||
11) <em>Rat Film</em>
|
||||
</h3>
|
||||
|
||||
<div id="s6q4gj">
|
||||
<iframe src="https://www.youtube.com/embed/f-kpMAKc0l4?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="GFFO6D">
|
||||
<em>Rat Film</em> is about rats, yes — and rat poison experts and rat hunters and people who keep rats as pets. But it’s also about the history of eugenics, dubious science, <a href="https://en.wikipedia.org/wiki/Redlining" target="_blank">“redlining,”</a> and segregated housing in Baltimore. All these pieces come together to form one big essay, where the meaning of each vignette only becomes clearer in light of the whole. It’s a fast-paced, no-holds-barred exploration of a damning history, and it accrues meaning as the images, sounds, and text pile up.
|
||||
</p>
|
||||
|
@ -122,7 +144,9 @@
|
|||
<h3 id="Qgio0l">
|
||||
10) <a href="https://www.vox.com/culture/2017/4/13/15243556/quiet-passion-review-emily-dickinson-passover-easter" target="_blank"><em>A Quiet Passion</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="Ya6IEK">
|
||||
<iframe src="https://www.youtube.com/embed/T3SyPbUTEeU?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="EO0XbC">
|
||||
<a href="https://www.vox.com/culture/2017/4/13/15243556/quiet-passion-review-emily-dickinson-passover-easter" target="_blank"><em>A Quiet Passion</em></a> is technically a biographical film about Emily Dickinson, but it transcends its genre to become something more like poetry. It’s a perplexing and challenging film, crafted without the traditional guardrails that guide most biographical movies — dates, times, major accomplishments, and so on. Time slips away in the film almost imperceptibly, and the narrative arc doesn’t yield easily to the viewer. Cynthia Nixon plays Emily Dickinson, whose poetry and life is a perfect match for the signature style of director Terence Davies: rich in detail, deeply enigmatic, and weighed down with a kind of sparkling, joy-tinged sorrow. <em>A Quiet Passion</em> is a portrait, both visual and narrative, of the kind of saint most modern people can understand: one who is certain of her uncertainty, and yearning to walk the path on which her passion and longing meet.
|
||||
</p>
|
||||
|
@ -132,7 +156,9 @@
|
|||
<h3 id="7dz2o3">
|
||||
9) <em>Columbus</em>
|
||||
</h3>
|
||||
|
||||
<div id="ZfQfEI">
|
||||
<iframe src="https://www.youtube.com/embed/r3dcnV6Z9Zs?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="pM0BdD">
|
||||
<em>Columbus</em> is a stunner of a debut from video essayist turned director Kogonada. Haley Lu Richardson stars as Casey, a young woman living in Columbus, Indiana, who cares for her mother, works at a library, and harbors a passion for architecture. (Columbus is a mecca for modernist architecture scholars and enthusiasts.) When a visiting architecture scholar falls into a coma in Columbus, his estranged son Jin (John Cho) arrives to wait for him and strikes up a friendship with Casey, who starts to show him her favorite buildings. The two begin to unlock something in each other that’s hard to define but life-changing for both. <em>Columbus</em> is beautiful and subtle, letting us feel how the places we build and the people we let near us move and mold us.
|
||||
</p>
|
||||
|
@ -142,7 +168,9 @@
|
|||
<h3 id="wkyPUl">
|
||||
8) <a href="https://www.vox.com/culture/2017/5/31/15706424/florida-project-review-cannes-sean-baker" target="_blank"><em>The Florida Project</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="RLHf4Z">
|
||||
<iframe src="https://www.youtube.com/embed/WwQ-NH1rRT4?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="J6kOkz">
|
||||
Sean Baker’s <a href="https://www.vox.com/culture/2017/5/31/15706424/florida-project-review-cannes-sean-baker" target="_blank"><em>The Florida Project</em></a> unfolds at first like a series of sketches about the characters who live in a purple-painted, $35-a-night motel called the Magic Castle down the street from Disney World. The film is held together by the hysterical antics of a kid named Moonee and her pack of young friends, as well as long-suffering hotel manager Bobby (a splendid, warm Willem Dafoe), who tries to put up with it all while keeping some kind of order. But as <em>The Florida Project</em> goes on, a narrative starts to form, one that chronicles with heartbreaking attention the sort of dilemmas that face poor parents and their children in America, and the broken systems that try to cope with impossible situations.
|
||||
</p>
|
||||
|
@ -152,7 +180,9 @@
|
|||
<h3 id="rLGNAf">
|
||||
7) <a href="https://www.vox.com/2017/11/21/16552862/call-me-by-your-name-review-timothee-chalamet-armie-hammer" target="_blank"><em>Call Me</em> <em>b</em><em>y Your Name</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="xGksjG">
|
||||
<iframe src="https://www.youtube.com/embed/Z9AYPxH5NTM?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="KyeOGQ">
|
||||
Luca Guadagnino’s gorgeous film <a href="https://www.vox.com/2017/11/21/16552862/call-me-by-your-name-review-timothee-chalamet-armie-hammer" target="_blank"><em>Call Me</em> <em>b</em><em>y Your Name</em></a> adapts André Aciman’s <a href="https://go.redirectingat.com/?id=66960X1516588&xs=1&url=https%3A%2F%2Fwww.amazon.com%2FCall-Me-Your-Name-Novel%2Fdp%2F031242678X" rel="nofollow noopener" target="_blank">2007 novel</a> about a precocious 17-year-old named Elio (Timothée Chalamet), who falls in lust and love with his father’s 24-year-old graduate student Oliver (Armie Hammer). It’s remarkable for how it turns literature into pure cinema, all emotion and image and heady sensation. Set in 1983 in Northern Italy, <em>Call Me</em> <em>b</em><em>y Your Name</em> is less about coming out than coming of age, but it also captures a particular sort of love that’s equal parts passion and torment, a kind of irrational heart fire that opens a gate into something longer-lasting. The film is a lush, heady experience for the body, but it’s also an arousal for the soul.
|
||||
</p>
|
||||
|
@ -162,7 +192,9 @@
|
|||
<h3 id="h6Biwc">
|
||||
6) <em>Personal Shopper</em>
|
||||
</h3>
|
||||
|
||||
<div id="NSQg2p">
|
||||
<iframe src="https://www.youtube.com/embed/xC8AjoqpBAY?rel=0&amp;start=15" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="pofJH9">
|
||||
In her second collaboration with French director <a href="http://www.imdb.com/name/nm0000801/?ref_=fn_al_nm_1" target="_blank">Olivier Assayas</a>, Kristen Stewart plays a personal shopper to a wealthy socialite, with a sideline as an amateur ghost hunter who’s searching for her dead twin brother. <em>Personal Shopper</em> is deeper than it seems at first blush, a meditation on grief and an exploration of “between” places — on the fringes of wealth, and in the space between life and death. Some souls are linked in a way that can’t be shaken, and whether or not there’s an afterlife doesn’t change the fact that we see and sense them everywhere. (<em>Personal Shopper</em> also has one of the most tense extended scenes involving text messaging ever seen onscreen.)
|
||||
</p>
|
||||
|
@ -172,7 +204,9 @@
|
|||
<h3 id="0RkMKy">
|
||||
5) <em>Princess Cyd</em>
|
||||
</h3>
|
||||
|
||||
<div id="7Tj1H6">
|
||||
<iframe src="https://www.youtube.com/embed/sr64EJfnJwE?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="2tSIHW">
|
||||
Stephen Cone is a master of small, carefully realized filmmaking; his earlier films such as <em>The Wise Kids</em> and <em>Henry Gamble’s Birthday Party</em> combine an unusual level of empathy for his characters with an unusual combination of interests: love, desire, sexual awakenings, and religion. <em>Princess Cyd</em> is his most accomplished film yet, about a young woman named Cyd (<a href="http://www.imdb.com/name/nm6570557/?ref_=tt_cl_t2" target="_blank">Jessie Pinnick</a>) who finds herself attracted to Katie (<a href="http://www.imdb.com/name/nm5154548/?ref_=tt_cl_t3" target="_blank">Malic White</a>), a barista, while visiting her Aunt Miranda (<a href="http://www.imdb.com/name/nm2050642/?ref_=tt_cl_t1" target="_blank">Rebecca Spence</a>, playing a character modeled on the author Marilynne Robinson) in Chicago. As she works through her own sexual awakening with Katie, Cyd unwinds some of the ways Miranda’s life has gotten too safe. They provoke each other while forming a bond and being prodded toward a bigger understanding of the world. It is a graceful and honest film, and it feels like a modest miracle.
|
||||
</p>
|
||||
|
@ -182,7 +216,9 @@
|
|||
<h3 id="ADtiAV">
|
||||
4) <a href="https://www.vox.com/culture/2017/2/24/14698632/get-out-review-jordan-peele" target="_blank"><em>Get Out</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="swjmhh">
|
||||
<iframe src="https://www.youtube.com/embed/sRfnevzM9kQ?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="h1ighb">
|
||||
Racism is sinister, frightening, and deadly. But <a href="https://www.vox.com/culture/2017/2/24/14698632/get-out-review-jordan-peele" target="_blank"><em>Get Out</em></a> (a stunning directorial debut from <em>Key & Peele</em>'s Jordan Peele) isn’t about the blatantly, obviously scary kind of racism — burning crosses and lynchings and snarling hate. Instead, it’s interested in showing how the parts of racism that try to be aggressively unscary are just as horrifying, and it’s interested in making us feel that horror in a visceral, bodily way. In the tradition of the best classic social thrillers, <em>Get Out</em> takes a topic that is often approached cerebrally — casual racism — and turns it into something you feel in your tummy. And it does it with a wicked sense of humor.
|
||||
</p>
|
||||
|
@ -192,7 +228,9 @@
|
|||
<h3 id="TQbjNr">
|
||||
3) <em>The Work</em>
|
||||
</h3>
|
||||
|
||||
<div id="GYqgVe">
|
||||
<iframe src="https://www.youtube.com/embed/h8OVXG2GhpQ?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="3Uotb3">
|
||||
<em>The Work</em> is an outstanding, astonishing accomplishment and a viewing experience that will leave you shaken (but in a good way). At Folsom Prison in California, incarcerated men regularly participate in group therapy, and each year other men from the “outside” apply to participate in an intense four-day period of group therapy alongside Folsom’s inmates. <em>The Work</em> spends almost all of its time inside the room where that therapy happens, observing the strong, visceral, and sometimes violent emotions the men feel as they expose the hurt and raw nerves that have shaped how they encounter the world. Watching is not always easy, but by letting us peek in, the film invites viewers to become part of the experience — as if we, too, are being asked to let go.
|
||||
</p>
|
||||
|
@ -202,7 +240,9 @@
|
|||
<h3 id="kUrRP6">
|
||||
2) <em>Ex Libris</em>
|
||||
</h3>
|
||||
|
||||
<div id="Lb1IzW">
|
||||
<iframe src="https://www.youtube.com/embed/YzKrlOFZBD8?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="rGpjUU">
|
||||
Frederick Wiseman is one of the towering giants of nonfiction film, a keen observer of American institutions — ranging from prisons to dance companies to welfare offices — for the past half-century. <em>Ex Libris</em> is his mesmerizing look at the New York Public Library and the many functions it fills, which go far beyond housing books. Wiseman works in the observational mode, which means his films contain no captions, dates, or talking-head interviews: We just see what his camera captured, which in this case includes community meetings, benefit dinners, after-school programs, readings with authors and scholars (including Richard Dawkins and Ta-Nehisi Coates), and NYPL patrons going about their business in the library’s branches all over the city. The result is almost hypnotic and, perhaps surprisingly, deeply moving. It makes a case for having faith in the public institutions where ordinary people work — away from the limelight, without trying to score political points — in order to make our communities truly better.
|
||||
</p>
|
||||
|
@ -212,7 +252,9 @@
|
|||
<h3 id="QJNuyl">
|
||||
1) <a href="https://www.vox.com/2017/11/2/16552860/lady-bird-review-saoirse-ronan-greta-gerwig" target="_blank"><em>Lady Bird</em></a>
|
||||
</h3>
|
||||
|
||||
<div id="mgxqrA">
|
||||
<iframe src="https://www.youtube.com/embed/cNi_HC839Wo?rel=0&" allowfullscreen="allowfullscreen" scrolling="no" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</div>
|
||||
<p id="z8uM1l">
|
||||
<em>Lady Bird</em> topped my list almost instantly, and only rose in my estimation on repeated viewings. For many who saw it (including me), it felt like a movie made not just for but <em>about</em> me. <em>Lady Bird</em> is a masterful, exquisite coming-of-age comedy starring the great Saoirse Ronan as Christine — or “Lady Bird,” as she’s re-christened herself — and it’s as funny, smart, and filled with yearning as its heroine. Writer-director Greta Gerwig made the film as an act of love, not just toward her hometown of Sacramento but also toward girlhood, and toward the feeling of always being on the outside of wherever real life is happening. <em>Lady Bird</em> is the rare movie that manages to be affectionate, entertaining, hilarious, witty, and confident. And one line from it struck me as the guiding principle of many of the year’s best films: “Don’t you think they are the same thing? Love, and attention?”
|
||||
</p>
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
<p>
|
||||
<strong><em>Vape Wave</em> (documentaire, 1h28, Planète+)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/lGL7RgHn5f0" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
Pendant quelques jours, le doute a plané : l’Etat comptait-il vraiment légiférer contre la cigarette dans les films français, que ce soit via une interdiction pure et simple ou via un système de «punition» (coupe des aides CNC, par exemple) pour les longs-métrages qui sentent le mégot ? Si <a href="https://www.liberation.fr/direct/element/agnes-buzyn-assure-quelle-na-jamais-envisage-linterdiction-de-la-cigarette-au-cinema_73855/" target="_blank">le rétropédalage de la ministre Buzyn</a> n’en est pas vraiment un (elle n’avait jamais clairement menacé le septième art), la polémique a le mérite de pointer la (sur)représentation clopesque sur écran. Et si, comme c’est le cas dans la vie quotidienne, on voyait progressivement les cigarettes électroniques remplacer les tiges nicotinées authentiques ? Que ceux qui mettraient en doute le potentiel cinématographique des vapoteuses se ruent sur <a href="http://www.vapewave.net/" target="_blank"><em>Vape Wave</em></a>, documentaire militant signé Jan Kounen, ex-fumeur reconverti à la vape dont les images magnifient les volutes de vapeur recrachée.
|
||||
</p>
|
||||
|
@ -21,7 +23,9 @@
|
|||
<p>
|
||||
<strong><em>Dans la tête d’Alan Moore</em> (websérie documentaire, 8x5min, Arte Creative)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/s_rw5fPHz2g" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
Le week-end dernier, <em>Libération</em> publiait <a href="http://next.liberation.fr/livres/2017/11/17/alan-moore-dernier-barde-avant-la-fin-du-monde_1610854" target="_blank">un portrait de der consacré à l’auteur britannique Alan Moore</a>, connu pour ses BD cultes (<em>V pour Vendetta, Watchmen, From Hell</em>), à l’occasion de la sortie de son deuxième roman, le pavé <em>Jérusalem</em>. En attendant l’imminente sortie d’une version longue de son entretien avec <em>Libé</em>, on pourra se replonger dans les épisodes d’une websérie documentaire d’Arte Creative en 8 épisodes consacré au maître. Brexit, magie, Anonymous font partie des sujets discutés avec le maître au fil de ce programme sobrement intitulé <a href="https://www.arte.tv/fr/videos/RC-014342/dans-la-tete-d-alan-moore/" target="_blank"><em>Dans la tête d’Alan Moore</em></a>. <strong>(A.H.)</strong>
|
||||
</p>
|
||||
|
@ -31,7 +35,9 @@
|
|||
<p>
|
||||
<strong><em>The Death and Life of Marsha P. Johnson</em> (docu, 1h45, Netflix)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/pADsuuPd79E" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
Marsha, la <em>«Rosa Parks du mouvement LGBTQ»</em>. Marsha <em>«la prostituée, l’actrice et la sainte, modèle d’Andy Warhol»</em> ou encore Marsha l’élaborée, la radicale, <em>«avec ses plumes et ce maquillage qu’elle ne mettait jamais bien»</em>. «Queen Marsha» a été retrouvée morte dans l’Hudson en juillet 1992, alors qu’on la voyait encore parader dans les rues de Greenwich Village quelques jours auparavant. Un choc glaçant. Là où son corps a été repêché puis ingratement déposé, les sans-abri ont constitué le lendemain un mémorial de bouteilles et de plantes qui délimitent les contours de l’absente.
|
||||
</p>
|
||||
|
@ -44,7 +50,9 @@
|
|||
<p>
|
||||
<strong><em>Alphonse President</em> (série, 10x26, OCS Max)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="100%" frameborder="0" src="https://www.dailymotion.com/embed/video/x67iqc9" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
Un temps baptisée <em>French Touch</em>, la série <em>Alphonse Président</em> est le dernier né des programmes originaux made in OCS. On savait les budgets de la chaîne bien moins généreux que ceux de Canal+ (voire que ceux de France 3 Limousin), et cette série le prouve à nouveau régulièrement, notamment lors d’une scène de conférence de presse alternant plans larges d’une authentique conf' à l’Elysée période François Hollande et plans serrés d’acteurs filmés dans un château des Pays de la Loire où a eu lieu le tournage. Le principal atout (et quel atout) de cette série écrite et réalisée par Nicolas Castro (<em>Des lendemains qui chantent</em>, 2014) réside dans son interprète principal, Michel Vuillermoz.
|
||||
</p>
|
||||
|
@ -57,7 +65,9 @@
|
|||
<p>
|
||||
<strong><em>Jim & Andy</em> (documentaire, 1h33, Netflix) </strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/kB15UFO5ebA" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
A la sortie de <em>Man on the Moon</em> (2000), le magnifique film de Milos Forman consacré à Andy Kaufman – comique et génie de la performance absurde mort en 1984 –, le cinéaste et les acteurs insistaient dans chaque interview sur l’incroyable comportement de Jim Carrey pendant le tournage : il aurait été comme possédé par Kaufman, se prenant pour lui 24 heures sur 24. Certains affirmaient même ne jamais avoir eu l’impression que l’acteur était présent, tant son modèle avait littéralement pris sa place. Nous en avons aujourd’hui la preuve en images car tout cela avait été filmé par Bob Zmuda et Lynne Margulies, l’ancien complice et la veuve de Kaufman.
|
||||
</p>
|
||||
|
@ -70,7 +80,9 @@
|
|||
<p>
|
||||
<strong><em>Braguino</em> (documentaire, 50min, Arte)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/OIS-P-0-cRk" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
La querelle peut se trouver derrière toutes les portes, y compris celle de l’exil. On a beau croire avoir tourné le dos à tout, à cette inclination humaine à nourrir sa propre haine, l’allergie peut regermer fissa sur une peau qui frissonne à l’approche de ce voisin que l’on ne comprend pas. Issu d’une lignée de vieux-croyants orthodoxes russes, Sacha Braguine a pris sa famille sous le bras, loin de toute autre présence humaine en taïga sibérienne. Un autre groupe, les Kiline, a décidé d’en faire de même et de s’installer de l’autre côté de la rivière. Qui est arrivé en premier ? Qui menace l’autre ? L’histoire de l’impossible communauté peut commencer.
|
||||
</p>
|
||||
|
@ -83,7 +95,9 @@
|
|||
<p>
|
||||
<strong><em>6 Days</em> (film, 1h34, Netflix)</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<iframe width="480" src="https://www.youtube.com/embed/7HthiTi_IcI" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="360" aspect-ratio="auto"><empty></empty></iframe>
|
||||
</p>
|
||||
<p>
|
||||
Fin avril 1980, l’ambassade d’Iran à Londres a été le théâtre d’une prise d’otages largement médiatisée : une trentaine de personnes ont ainsi été retenues pendant six jours par des soldats iraniens dissidents exigeant la libération de 91 prisonniers. Avec Margaret Thatcher au 10 Downing Street à l’époque, pas question pour l’Angleterre d’avoir l’air mou du genou sur la réponse à apporter à cette crise scrutée par les caméras du monde entier. Le SAS (Special Air Service) est sur le coup : l’opération Nimrod se met en place pour prendre d’assaut l’ambassade.
|
||||
</p>
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
<td colspan="2">
|
||||
<div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Flag_of_New_Zealand.svg" title="Flag of New Zealand" target="_blank"><img alt="Blue field with the Union Flag in the top right corner, and four red stars with white borders to the right." src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/125px-Flag_of_New_Zealand.svg.png" decoding="async" width="125" height="63" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/188px-Flag_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/250px-Flag_of_New_Zealand.svg.png 2x" data-file-width="1200" data-file-height="600"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Flag_of_New_Zealand.svg" title="Flag of New Zealand" target="_blank"><img alt="Blue field with the Union Flag in the top right corner, and four red stars with white borders to the right." src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/125px-Flag_of_New_Zealand.svg.png" width="125" height="63" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/188px-Flag_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/250px-Flag_of_New_Zealand.svg.png 2x" data-file-width="1200" data-file-height="600"/></a>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/Flag_of_New_Zealand" title="Flag of New Zealand" target="_blank">Flag</a>
|
||||
</p></div>
|
||||
</div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Coat_of_arms_of_New_Zealand.svg" title="Coat of arms of New Zealand" target="_blank"><img alt="A quartered shield, flanked by two figures, topped with a crown." src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/85px-Coat_of_arms_of_New_Zealand.svg.png" decoding="async" width="85" height="82" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/128px-Coat_of_arms_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/170px-Coat_of_arms_of_New_Zealand.svg.png 2x" data-file-width="725" data-file-height="699"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Coat_of_arms_of_New_Zealand.svg" title="Coat of arms of New Zealand" target="_blank"><img alt="A quartered shield, flanked by two figures, topped with a crown." src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/85px-Coat_of_arms_of_New_Zealand.svg.png" width="85" height="82" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/128px-Coat_of_arms_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Coat_of_arms_of_New_Zealand.svg/170px-Coat_of_arms_of_New_Zealand.svg.png 2x" data-file-width="725" data-file-height="699"/></a>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/Coat_of_arms_of_New_Zealand" title="Coat of arms of New Zealand" target="_blank">Coat of arms</a>
|
||||
|
@ -56,7 +56,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="http://fakehost/wiki/File:NZL_orthographic_NaturalEarth.svg" title="Location of New Zealand, including outlying islands, its territorial claim in the Antarctic, and Tokelau" target="_blank"><img alt="A map of the hemisphere centred on New Zealand, using an orthographic projection." src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/250px-NZL_orthographic_NaturalEarth.svg.png" decoding="async" width="250" height="250" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/375px-NZL_orthographic_NaturalEarth.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/500px-NZL_orthographic_NaturalEarth.svg.png 2x" data-file-width="512" data-file-height="512"/></a>
|
||||
<a href="http://fakehost/wiki/File:NZL_orthographic_NaturalEarth.svg" title="Location of New Zealand, including outlying islands, its territorial claim in the Antarctic, and Tokelau" target="_blank"><img alt="A map of the hemisphere centred on New Zealand, using an orthographic projection." src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/250px-NZL_orthographic_NaturalEarth.svg.png" width="250" height="250" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/375px-NZL_orthographic_NaturalEarth.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/NZL_orthographic_NaturalEarth.svg/500px-NZL_orthographic_NaturalEarth.svg.png 2x" data-file-width="512" data-file-height="512"/></a>
|
||||
<div><p>
|
||||
Location of New Zealand, including outlying islands, its <a href="http://fakehost/wiki/Ross_Dependency" title="Ross Dependency" target="_blank">territorial claim in the Antarctic</a>, and <a href="http://fakehost/wiki/Tokelau" title="Tokelau" target="_blank">Tokelau</a>
|
||||
</p></div>
|
||||
|
@ -354,7 +354,7 @@
|
|||
<a href="http://fakehost/wiki/Human_Development_Index" title="Human Development Index" target="_blank">HDI</a> <span>(2017)</span>
|
||||
</th>
|
||||
<td>
|
||||
<img alt="Increase" src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/11px-Increase2.svg.png" decoding="async" title="Increase" width="11" height="11" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/17px-Increase2.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/22px-Increase2.svg.png 2x" data-file-width="300" data-file-height="300"/> 0.917<sup id="cite_ref-HDI_12-0"><a href="#cite_note-HDI-12">[8]</a></sup><br/>
|
||||
<img alt="Increase" src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/11px-Increase2.svg.png" title="Increase" width="11" height="11" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/17px-Increase2.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Increase2.svg/22px-Increase2.svg.png 2x" data-file-width="300" data-file-height="300"/> 0.917<sup id="cite_ref-HDI_12-0"><a href="#cite_note-HDI-12">[8]</a></sup><br/>
|
||||
<span><span>very high</span></span> · <a href="http://fakehost/wiki/List_of_countries_by_Human_Development_Index" title="List of countries by Human Development Index" target="_blank">16th</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -548,7 +548,7 @@
|
|||
</h2>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius,_showing_Nova_Zeelandia.png" target="_blank"><img alt="Brown square paper with Dutch writing and a thick red, curved line" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/220px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png" decoding="async" width="220" height="171" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/330px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/440px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png 2x" data-file-width="684" data-file-height="532"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius,_showing_Nova_Zeelandia.png" target="_blank"><img alt="Brown square paper with Dutch writing and a thick red, curved line" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/220px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png" width="220" height="171" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/330px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png/440px-Detail_of_1657_map_Polus_Antarcticus_by_Jan_Janssonius%2C_showing_Nova_Zeelandia.png 2x" data-file-width="684" data-file-height="532"/></a></p><div>
|
||||
<p>Detail from a 1657 map showing the western coastline of "Nova Zeelandia". (In this map, north is at the bottom.)
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -564,7 +564,7 @@
|
|||
</h2>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Polynesian_Migration.svg" target="_blank"><img alt="One set of arrows point from Taiwan to Melanesia to Fiji/Samoa and then to the Marquesas Islands. The population then spread, some going south to New Zealand and others going north to Hawai'i. A second set start in southern Asia and end in Melanesia." src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/290px-Polynesian_Migration.svg.png" decoding="async" width="290" height="290" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/435px-Polynesian_Migration.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/580px-Polynesian_Migration.svg.png 2x" data-file-width="553" data-file-height="553"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Polynesian_Migration.svg" target="_blank"><img alt="One set of arrows point from Taiwan to Melanesia to Fiji/Samoa and then to the Marquesas Islands. The population then spread, some going south to New Zealand and others going north to Hawai'i. A second set start in southern Asia and end in Melanesia." src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/290px-Polynesian_Migration.svg.png" width="290" height="290" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/435px-Polynesian_Migration.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Polynesian_Migration.svg/580px-Polynesian_Migration.svg.png 2x" data-file-width="553" data-file-height="553"/></a></p><div>
|
||||
<p>The <a href="http://fakehost/wiki/M%C4%81ori_people" title="Māori people" target="_blank">Māori people</a> are most likely descended from people who emigrated from <a href="http://fakehost/wiki/Taiwan" title="Taiwan" target="_blank">Taiwan</a> to <a href="http://fakehost/wiki/Melanesia" title="Melanesia" target="_blank">Melanesia</a> and then travelled east through to the <a href="http://fakehost/wiki/Society_Islands" title="Society Islands" target="_blank">Society Islands</a>. After a pause of 70 to 265 years, a new wave of exploration led to the discovery and settlement of New Zealand.<sup id="cite_ref-28"><a href="#cite_note-28">[22]</a></sup>
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -572,7 +572,7 @@
|
|||
New Zealand was one of the last major landmasses settled by humans. <a href="http://fakehost/wiki/Radiocarbon_dating" title="Radiocarbon dating" target="_blank">Radiocarbon dating</a>, evidence of <a href="http://fakehost/wiki/Deforestation" title="Deforestation" target="_blank">deforestation</a><sup id="cite_ref-29"><a href="#cite_note-29">[23]</a></sup> and <a href="http://fakehost/wiki/Mitochondrial_DNA" title="Mitochondrial DNA" target="_blank">mitochondrial DNA</a> variability within <a href="http://fakehost/wiki/M%C4%81ori_people" title="Māori people" target="_blank">Māori</a> populations<sup id="cite_ref-30"><a href="#cite_note-30">[24]</a></sup> suggest New Zealand was first settled by Eastern <a href="http://fakehost/wiki/Polynesians" title="Polynesians" target="_blank">Polynesians</a> between 1250 and 1300,<sup id="cite_ref-FOOTNOTEMein_Smith20056_25-1"><a href="#cite_note-FOOTNOTEMein_Smith20056-25">[19]</a></sup><sup id="cite_ref-31"><a href="#cite_note-31">[25]</a></sup> concluding a long series of voyages through the southern Pacific islands.<sup id="cite_ref-32"><a href="#cite_note-32">[26]</a></sup> Over the centuries that followed, these settlers developed a distinct culture now known as Māori. The population was divided into <i><a href="http://fakehost/wiki/Iwi" title="Iwi" target="_blank">iwi</a></i> (tribes) and <i><a href="http://fakehost/wiki/Hap%C5%AB" title="Hapū" target="_blank">hapū</a></i> (subtribes) who would sometimes cooperate, sometimes compete and sometimes fight against each other.<sup id="cite_ref-33"><a href="#cite_note-33">[27]</a></sup> At some point a group of Māori migrated to <i>Rēkohu</i>, now known as the <a href="http://fakehost/wiki/Chatham_Islands" title="Chatham Islands" target="_blank">Chatham Islands</a>, where they developed their distinct <a href="http://fakehost/wiki/Moriori" title="Moriori" target="_blank">Moriori</a> culture.<sup id="cite_ref-34"><a href="#cite_note-34">[28]</a></sup><sup id="cite_ref-35"><a href="#cite_note-35">[29]</a></sup> The Moriori population was all but wiped out between 1835 and 1862, largely because of <a href="http://fakehost/wiki/Taranaki_(iwi)" title="Taranaki (iwi)" target="_blank">Taranaki</a> Māori invasion and enslavement in the 1830s, although European diseases also contributed. In 1862 only 101 survived, and the last known full-blooded Moriori died in 1933.<sup id="cite_ref-36"><a href="#cite_note-36">[30]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Cook_chart_of_New_Zealand.jpg" target="_blank"><img alt="An engraving of a sketched coastline on white background" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/170px-Cook_chart_of_New_Zealand.jpg" decoding="async" width="170" height="235" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/255px-Cook_chart_of_New_Zealand.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/340px-Cook_chart_of_New_Zealand.jpg 2x" data-file-width="1093" data-file-height="1508"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Cook_chart_of_New_Zealand.jpg" target="_blank"><img alt="An engraving of a sketched coastline on white background" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/170px-Cook_chart_of_New_Zealand.jpg" width="170" height="235" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/255px-Cook_chart_of_New_Zealand.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cook_chart_of_New_Zealand.jpg/340px-Cook_chart_of_New_Zealand.jpg 2x" data-file-width="1093" data-file-height="1508"/></a></p><div>
|
||||
<p>Map of the New Zealand coastline as Cook charted it on his <a href="http://fakehost/wiki/First_voyage_of_James_Cook" title="First voyage of James Cook" target="_blank">first visit</a> in 1769–70. The track of the <i><a href="http://fakehost/wiki/HMS_Endeavour" title="HMS Endeavour" target="_blank">Endeavour</a></i> is also shown.
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -580,13 +580,13 @@
|
|||
The first <a href="http://fakehost/wiki/Ethnic_groups_in_Europe" title="Ethnic groups in Europe" target="_blank">Europeans</a> known to have reached New Zealand were Dutch explorer <a href="http://fakehost/wiki/Abel_Tasman" title="Abel Tasman" target="_blank">Abel Tasman</a> and his crew in 1642.<sup id="cite_ref-FOOTNOTEMein_Smith200523_37-0"><a href="#cite_note-FOOTNOTEMein_Smith200523-37">[31]</a></sup> In a hostile encounter, four crew members were killed and at least one Māori was hit by <a href="http://fakehost/wiki/Canister_shot" title="Canister shot" target="_blank">canister shot</a>.<sup id="cite_ref-38"><a href="#cite_note-38">[32]</a></sup> Europeans did not revisit New Zealand until 1769 when British explorer <a href="http://fakehost/wiki/James_Cook" title="James Cook" target="_blank">James Cook</a> mapped almost the entire coastline.<sup id="cite_ref-FOOTNOTEMein_Smith200523_37-1"><a href="#cite_note-FOOTNOTEMein_Smith200523-37">[31]</a></sup> Following Cook, New Zealand was visited by numerous European and North American <a href="http://fakehost/wiki/History_of_whaling" title="History of whaling" target="_blank">whaling</a>, <a href="http://fakehost/wiki/Seal_hunting" title="Seal hunting" target="_blank">sealing</a> and trading ships. They traded European food, metal tools, weapons and other goods for timber, Māori food, artefacts and water.<sup id="cite_ref-FOOTNOTEKing2003122_39-0"><a href="#cite_note-FOOTNOTEKing2003122-39">[33]</a></sup> The introduction of the potato and the <a href="http://fakehost/wiki/Musket" title="Musket" target="_blank">musket</a> transformed Māori agriculture and warfare. Potatoes provided a reliable food surplus, which enabled longer and more sustained military campaigns.<sup id="cite_ref-40"><a href="#cite_note-40">[34]</a></sup> The resulting intertribal <a href="http://fakehost/wiki/Musket_Wars" title="Musket Wars" target="_blank">Musket Wars</a> encompassed over 600 battles between 1801 and 1840, killing 30,000–40,000 Māori.<sup id="cite_ref-41"><a href="#cite_note-41">[35]</a></sup> From the early 19th century, Christian <a href="http://fakehost/wiki/Missionary" title="Missionary" target="_blank">missionaries</a> began to settle New Zealand, eventually <a href="http://fakehost/wiki/Religious_conversion" title="Religious conversion" target="_blank">converting</a> most of the Māori population.<sup id="cite_ref-42"><a href="#cite_note-42">[36]</a></sup> The Māori population declined to around 40% of its pre-contact level during the 19th century; introduced diseases were the major factor.<sup id="cite_ref-43"><a href="#cite_note-43">[37]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Treatyofwaitangi.jpg" target="_blank"><img alt="A torn sheet of paper" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/170px-Treatyofwaitangi.jpg" decoding="async" width="170" height="318" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/255px-Treatyofwaitangi.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/340px-Treatyofwaitangi.jpg 2x" data-file-width="3091" data-file-height="5788"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Treatyofwaitangi.jpg" target="_blank"><img alt="A torn sheet of paper" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/170px-Treatyofwaitangi.jpg" width="170" height="318" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/255px-Treatyofwaitangi.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Treatyofwaitangi.jpg/340px-Treatyofwaitangi.jpg 2x" data-file-width="3091" data-file-height="5788"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
In 1788 Captain <a href="http://fakehost/wiki/Arthur_Phillip" title="Arthur Phillip" target="_blank">Arthur Phillip</a> assumed the position of <a href="http://fakehost/wiki/Governor_of_New_South_Wales" title="Governor of New South Wales" target="_blank">Governor</a> of the new British colony of <a href="http://fakehost/wiki/Colony_of_New_South_Wales" title="Colony of New South Wales" target="_blank">New South Wales</a> which according to his commission included New Zealand.<sup id="cite_ref-44"><a href="#cite_note-44">[38]</a></sup> The British Government appointed <a href="http://fakehost/wiki/James_Busby" title="James Busby" target="_blank">James Busby</a> as British Resident to New Zealand in 1832 following a petition from northern Māori.<sup id="cite_ref-Busby_45-0"><a href="#cite_note-Busby-45">[39]</a></sup> In 1835, following an announcement of impending French settlement by <a href="http://fakehost/wiki/Charles_de_Thierry" title="Charles de Thierry" target="_blank">Charles de Thierry</a>, the nebulous <a href="http://fakehost/wiki/United_Tribes_of_New_Zealand" title="United Tribes of New Zealand" target="_blank">United Tribes of New Zealand</a> sent a <a href="http://fakehost/wiki/Declaration_of_the_Independence_of_New_Zealand" title="Declaration of the Independence of New Zealand" target="_blank">Declaration of Independence</a> to King <a href="http://fakehost/wiki/William_IV_of_the_United_Kingdom" title="William IV of the United Kingdom" target="_blank">William IV of the United Kingdom</a> asking for protection.<sup id="cite_ref-Busby_45-1"><a href="#cite_note-Busby-45">[39]</a></sup> Ongoing unrest, the proposed settlement of New Zealand by the <a href="http://fakehost/wiki/New_Zealand_Company" title="New Zealand Company" target="_blank">New Zealand Company</a> (which had already sent its first ship of surveyors to buy land from Māori) and the dubious legal standing of the Declaration of Independence prompted the <a href="http://fakehost/wiki/Colonial_Office" title="Colonial Office" target="_blank">Colonial Office</a> to send Captain <a href="http://fakehost/wiki/William_Hobson" title="William Hobson" target="_blank">William Hobson</a> to claim sovereignty for the <a href="http://fakehost/wiki/United_Kingdom" title="United Kingdom" target="_blank">United Kingdom</a> and negotiate a treaty with the Māori.<sup id="cite_ref-46"><a href="#cite_note-46">[40]</a></sup> The <a href="http://fakehost/wiki/Treaty_of_Waitangi" title="Treaty of Waitangi" target="_blank">Treaty of Waitangi</a> was first signed in the <a href="http://fakehost/wiki/Bay_of_Islands" title="Bay of Islands" target="_blank">Bay of Islands</a> on 6 February 1840.<sup id="cite_ref-Wilson2009_47-0"><a href="#cite_note-Wilson2009-47">[41]</a></sup> In response to the New Zealand Company's attempts to establish an independent settlement in <a href="http://fakehost/wiki/Wellington" title="Wellington" target="_blank">Wellington</a><sup id="cite_ref-48"><a href="#cite_note-48">[42]</a></sup> and French settlers purchasing land in <a href="http://fakehost/wiki/Akaroa" title="Akaroa" target="_blank">Akaroa</a>,<sup id="cite_ref-49"><a href="#cite_note-49">[43]</a></sup> Hobson declared British sovereignty over all of New Zealand on 21 May 1840, even though copies of the Treaty were still circulating throughout the country for Māori to sign.<sup id="cite_ref-50"><a href="#cite_note-50">[44]</a></sup> With the signing of the Treaty and declaration of sovereignty the number of immigrants, particularly from the United Kingdom, began to increase.<sup id="cite_ref-51"><a href="#cite_note-51">[45]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay,_New_Zealand.jpg" target="_blank"><img alt="Black and white engraving depicting a crowd of people" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/290px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg" decoding="async" width="290" height="208" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/435px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/580px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg 2x" data-file-width="6000" data-file-height="4300"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay,_New_Zealand.jpg" target="_blank"><img alt="Black and white engraving depicting a crowd of people" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/290px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg" width="290" height="208" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/435px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg/580px-1863_Meeting_of_Settlers_and_Maoris_at_Hawke%27s_Bay%2C_New_Zealand.jpg 2x" data-file-width="6000" data-file-height="4300"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
New Zealand, still part of the colony of New South Wales, became a separate <a href="http://fakehost/wiki/Crown_colony" title="Crown colony" target="_blank">Colony</a> <a href="http://fakehost/wiki/Colony_of_New_Zealand" title="Colony of New Zealand" target="_blank">of New Zealand</a> on 1 July 1841.<sup id="cite_ref-52"><a href="#cite_note-52">[46]</a></sup> Armed conflict began between the Colonial government and Māori in 1843 with the <a href="http://fakehost/wiki/Wairau_Affray" title="Wairau Affray" target="_blank">Wairau Affray</a> over land and disagreements over sovereignty. These conflicts, mainly in the North Island, saw thousands of Imperial troops and the Royal Navy come to New Zealand and became known as the <a href="http://fakehost/wiki/New_Zealand_Wars" title="New Zealand Wars" target="_blank">New Zealand Wars</a>. Following these armed conflicts, large amounts of <a href="http://fakehost/wiki/New_Zealand_land_confiscations" title="New Zealand land confiscations" target="_blank">Māori land was confiscated by the government</a> to meet settler demands.<sup id="cite_ref-53"><a href="#cite_note-53">[47]</a></sup>
|
||||
|
@ -609,12 +609,12 @@
|
|||
|
||||
<div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/Elizabeth_II" title="Elizabeth II" target="_blank"><img alt="The Queen wearing her New Zealand insignia" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/152px-Queen_Elizabeth_II_of_New_Zealand_2.jpg" decoding="async" width="152" height="190" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/228px-Queen_Elizabeth_II_of_New_Zealand_2.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/304px-Queen_Elizabeth_II_of_New_Zealand_2.jpg 2x" data-file-width="1182" data-file-height="1478"/></a>
|
||||
<p><a href="http://fakehost/wiki/Elizabeth_II" title="Elizabeth II" target="_blank"><img alt="The Queen wearing her New Zealand insignia" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/152px-Queen_Elizabeth_II_of_New_Zealand_2.jpg" width="152" height="190" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/228px-Queen_Elizabeth_II_of_New_Zealand_2.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Queen_Elizabeth_II_of_New_Zealand_2.jpg/304px-Queen_Elizabeth_II_of_New_Zealand_2.jpg 2x" data-file-width="1182" data-file-height="1478"/></a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/Jacinda_Ardern" title="Jacinda Ardern" target="_blank"><img alt="A smiling woman wearing a black dress" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/152px-Ardern_Cropped.png" decoding="async" width="152" height="191" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/228px-Ardern_Cropped.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/304px-Ardern_Cropped.png 2x" data-file-width="499" data-file-height="627"/></a>
|
||||
<p><a href="http://fakehost/wiki/Jacinda_Ardern" title="Jacinda Ardern" target="_blank"><img alt="A smiling woman wearing a black dress" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/152px-Ardern_Cropped.png" width="152" height="191" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/228px-Ardern_Cropped.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Ardern_Cropped.png/304px-Ardern_Cropped.png 2x" data-file-width="499" data-file-height="627"/></a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
@ -629,7 +629,7 @@
|
|||
A <a href="http://fakehost/wiki/Elections_in_New_Zealand" title="Elections in New Zealand" target="_blank">parliamentary general election</a> must be called no later than three years after the previous election.<sup id="cite_ref-82"><a href="#cite_note-82">[76]</a></sup> Almost all general elections between <a href="http://fakehost/wiki/1853_New_Zealand_general_election" title="1853 New Zealand general election" target="_blank">1853</a> and <a href="http://fakehost/wiki/1993_New_Zealand_general_election" title="1993 New Zealand general election" target="_blank">1993</a> were held under the <a href="http://fakehost/wiki/First-past-the-post_voting" title="First-past-the-post voting" target="_blank">first-past-the-post voting</a> system.<sup id="cite_ref-road_83-0"><a href="#cite_note-road-83">[77]</a></sup> Since the <a href="http://fakehost/wiki/1996_New_Zealand_general_election" title="1996 New Zealand general election" target="_blank">1996 election</a>, a form of <a href="http://fakehost/wiki/Proportional_representation" title="Proportional representation" target="_blank">proportional representation</a> called <a href="http://fakehost/wiki/Mixed-member_proportional" title="Mixed-member proportional" target="_blank">mixed-member proportional</a> (MMP) has been used.<sup id="cite_ref-Economist_factsheet_72-1"><a href="#cite_note-Economist_factsheet-72">[66]</a></sup> Under the MMP system, each person has two votes; one is for a candidate standing in the voter's <a href="http://fakehost/wiki/New_Zealand_electorates" title="New Zealand electorates" target="_blank">electorate</a> and the other is for a party. Since the <a href="http://fakehost/wiki/2014_New_Zealand_general_election" title="2014 New Zealand general election" target="_blank">2014 election</a>, there have been 71 electorates (which include seven <a href="http://fakehost/wiki/M%C4%81ori_electorates" title="Māori electorates" target="_blank">Māori electorates</a> in which only Māori can optionally vote),<sup id="cite_ref-84"><a href="#cite_note-84">[78]</a></sup> and the remaining 49 of the 120 seats are assigned so that representation in parliament reflects the party vote, with the threshold that a party must win at least one electorate or 5% of the total party vote before it is eligible for a seat.<sup id="cite_ref-85"><a href="#cite_note-85">[79]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Seddon_Statue_in_Parliament_Grounds.jpg" target="_blank"><img alt="A block of buildings fronted by a large statue." src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/220px-Seddon_Statue_in_Parliament_Grounds.jpg" decoding="async" width="220" height="171" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/330px-Seddon_Statue_in_Parliament_Grounds.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/440px-Seddon_Statue_in_Parliament_Grounds.jpg 2x" data-file-width="3297" data-file-height="2557"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Seddon_Statue_in_Parliament_Grounds.jpg" target="_blank"><img alt="A block of buildings fronted by a large statue." src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/220px-Seddon_Statue_in_Parliament_Grounds.jpg" width="220" height="171" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/330px-Seddon_Statue_in_Parliament_Grounds.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Seddon_Statue_in_Parliament_Grounds.jpg/440px-Seddon_Statue_in_Parliament_Grounds.jpg 2x" data-file-width="3297" data-file-height="2557"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
Elections since the 1930s have been dominated by two political parties, <a href="http://fakehost/wiki/New_Zealand_National_Party" title="New Zealand National Party" target="_blank">National</a> and <a href="http://fakehost/wiki/New_Zealand_Labour_Party" title="New Zealand Labour Party" target="_blank">Labour</a>.<sup id="cite_ref-road_83-1"><a href="#cite_note-road-83">[77]</a></sup> Between March 2005 and August 2006, New Zealand became the first country in the world in which all the highest offices in the land—head of state, governor-general, prime minister, <a href="http://fakehost/wiki/Speaker_of_the_New_Zealand_House_of_Representatives" title="Speaker of the New Zealand House of Representatives" target="_blank">speaker</a> and <a href="http://fakehost/wiki/Chief_Justice_of_New_Zealand" title="Chief Justice of New Zealand" target="_blank">chief justice</a>—were occupied simultaneously by women.<sup id="cite_ref-86"><a href="#cite_note-86">[80]</a></sup> The current prime minister is <a href="http://fakehost/wiki/Jacinda_Ardern" title="Jacinda Ardern" target="_blank">Jacinda Ardern</a>, who has been in office since 26 October 2017.<sup id="cite_ref-87"><a href="#cite_note-87">[81]</a></sup> She is the country's third female prime minister.<sup id="cite_ref-88"><a href="#cite_note-88">[82]</a></sup>
|
||||
|
@ -646,7 +646,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:E_003261_E_Maoris_in_North_Africa_July_1941.jpg" target="_blank"><img alt="A squad of men kneel in the desert sand while performing a war dance" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/220px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg" decoding="async" width="220" height="217" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/330px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/440px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg 2x" data-file-width="3040" data-file-height="2999"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:E_003261_E_Maoris_in_North_Africa_July_1941.jpg" target="_blank"><img alt="A squad of men kneel in the desert sand while performing a war dance" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/220px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg" width="220" height="217" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/330px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/E_003261_E_Maoris_in_North_Africa_July_1941.jpg/440px-E_003261_E_Maoris_in_North_Africa_July_1941.jpg 2x" data-file-width="3040" data-file-height="2999"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
Early colonial New Zealand allowed the British Government to determine external trade and be responsible for foreign policy.<sup id="cite_ref-97"><a href="#cite_note-97">[91]</a></sup> The 1923 and 1926 <a href="http://fakehost/wiki/Imperial_Conference" title="Imperial Conference" target="_blank">Imperial Conferences</a> decided that New Zealand should be allowed to negotiate its own political <a href="http://fakehost/wiki/Treaty" title="Treaty" target="_blank">treaties</a> and the first commercial treaty was ratified in 1928 with Japan. On 3 September 1939 New Zealand allied itself with Britain and <a href="http://fakehost/wiki/Declaration_of_war" title="Declaration of war" target="_blank">declared war</a> on Germany with Prime Minister <a href="http://fakehost/wiki/Michael_Joseph_Savage" title="Michael Joseph Savage" target="_blank">Michael Joseph Savage</a> proclaiming, "Where she goes, we go; where she stands, we stand."<sup id="cite_ref-98"><a href="#cite_note-98">[92]</a></sup>
|
||||
|
@ -655,7 +655,7 @@
|
|||
In 1951 the United Kingdom became increasingly focused on its European interests,<sup id="cite_ref-99"><a href="#cite_note-99">[93]</a></sup> while New Zealand joined <a href="http://fakehost/wiki/Australia%E2%80%93New_Zealand_relations" title="Australia–New Zealand relations" target="_blank">Australia</a> and the <a href="http://fakehost/wiki/New_Zealand%E2%80%93United_States_relations" title="New Zealand–United States relations" target="_blank">United States</a> in the <a href="http://fakehost/wiki/ANZUS" title="ANZUS" target="_blank">ANZUS</a> security treaty.<sup id="cite_ref-100"><a href="#cite_note-100">[94]</a></sup> The influence of the United States on New Zealand weakened following protests over the <a href="http://fakehost/wiki/New_Zealand_in_the_Vietnam_War" title="New Zealand in the Vietnam War" target="_blank">Vietnam War</a>,<sup id="cite_ref-101"><a href="#cite_note-101">[95]</a></sup> the refusal of the United States to admonish France after the <a href="http://fakehost/wiki/Sinking_of_the_Rainbow_Warrior" title="Sinking of the Rainbow Warrior" target="_blank">sinking of the <i>Rainbow Warrior</i></a>,<sup id="cite_ref-102"><a href="#cite_note-102">[96]</a></sup> disagreements over environmental and agricultural trade issues and <a href="http://fakehost/wiki/New_Zealand_nuclear-free_zone" title="New Zealand nuclear-free zone" target="_blank">New Zealand's nuclear-free policy</a>.<sup id="cite_ref-103"><a href="#cite_note-103">[97]</a></sup><sup id="cite_ref-104"><a href="#cite_note-104">[98]</a></sup> Despite the United States' suspension of ANZUS obligations the treaty remained in effect between New Zealand and Australia, whose foreign policy has followed a similar historical trend.<sup id="cite_ref-105"><a href="#cite_note-105">[99]</a></sup> Close political contact is maintained between the two countries, with <a href="http://fakehost/wiki/Closer_Economic_Relations" title="Closer Economic Relations" target="_blank">free trade agreements</a> and <a href="http://fakehost/wiki/Trans-Tasman_Travel_Arrangement" title="Trans-Tasman Travel Arrangement" target="_blank">travel arrangements</a> that allow citizens to visit, live and work in both countries without restrictions.<sup id="cite_ref-NZ_in_brief_106-0"><a href="#cite_note-NZ_in_brief-106">[100]</a></sup> In 2013 there were about 650,000 New Zealand citizens living in Australia, which is equivalent to 15% of the resident population of New Zealand.<sup id="cite_ref-107"><a href="#cite_note-107">[101]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_(20).jpg" target="_blank"><img alt="A soldier in a green army uniform faces forwards" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/220px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/330px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/440px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg 2x" data-file-width="3888" data-file-height="2592"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_(20).jpg" target="_blank"><img alt="A soldier in a green army uniform faces forwards" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/220px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/330px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg/440px-ANZAC_Day_service_at_the_National_War_Memorial_-_Flickr_-_NZ_Defence_Force_%2820%29.jpg 2x" data-file-width="3888" data-file-height="2592"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/Anzac_Day" title="Anzac Day" target="_blank">Anzac Day</a> service at the National War Memorial
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -673,7 +673,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:NZL_orthographic_NaturalEarth_labelled_en.svg" target="_blank"><img alt="Map with the North, South, Stewart/Rakiura, Tokelau, Cook, Niue, Kermadec, Chatham, Bounty, Antipodes, Snare, Auckland and Campbell Islands highlighted. New Zealand's segment of Antarctica (the Ross Dependency) is also highlighted." src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/400px-NZL_orthographic_NaturalEarth_labelled_en.svg.png" decoding="async" width="400" height="400" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/600px-NZL_orthographic_NaturalEarth_labelled_en.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/800px-NZL_orthographic_NaturalEarth_labelled_en.svg.png 2x" data-file-width="553" data-file-height="553"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:NZL_orthographic_NaturalEarth_labelled_en.svg" target="_blank"><img alt="Map with the North, South, Stewart/Rakiura, Tokelau, Cook, Niue, Kermadec, Chatham, Bounty, Antipodes, Snare, Auckland and Campbell Islands highlighted. New Zealand's segment of Antarctica (the Ross Dependency) is also highlighted." src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/400px-NZL_orthographic_NaturalEarth_labelled_en.svg.png" width="400" height="400" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/600px-NZL_orthographic_NaturalEarth_labelled_en.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/NZL_orthographic_NaturalEarth_labelled_en.svg/800px-NZL_orthographic_NaturalEarth_labelled_en.svg.png 2x" data-file-width="553" data-file-height="553"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
The early European settlers divided New Zealand into <a href="http://fakehost/wiki/Provinces_of_New_Zealand" title="Provinces of New Zealand" target="_blank">provinces</a>, which had a degree of autonomy.<sup id="cite_ref-nine_provinces_127-0"><a href="#cite_note-nine_provinces-127">[121]</a></sup> Because of financial pressures and the desire to consolidate railways, education, land sales and other policies, government was centralised and the provinces were abolished in 1876.<sup id="cite_ref-128"><a href="#cite_note-128">[122]</a></sup> The provinces are remembered in <a href="http://fakehost/wiki/Public_holidays_in_New_Zealand" title="Public holidays in New Zealand" target="_blank">regional public holidays</a><sup id="cite_ref-129"><a href="#cite_note-129">[123]</a></sup> and sporting rivalries.<sup id="cite_ref-130"><a href="#cite_note-130">[124]</a></sup>
|
||||
|
@ -711,15 +711,15 @@
|
|||
Countries
|
||||
</th>
|
||||
<td colspan="7">
|
||||
<span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/23px-Flag_of_New_Zealand.svg.png" decoding="async" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/35px-Flag_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/46px-Flag_of_New_Zealand.svg.png 2x" data-file-width="1200" data-file-height="600"/> </span><a>New Zealand</a>
|
||||
<span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/23px-Flag_of_New_Zealand.svg.png" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/35px-Flag_of_New_Zealand.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/46px-Flag_of_New_Zealand.svg.png 2x" data-file-width="1200" data-file-height="600"/> </span><a>New Zealand</a>
|
||||
</td>
|
||||
|
||||
|
||||
<td rowspan="1">
|
||||
<span><span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/23px-Flag_of_the_Cook_Islands.svg.png" decoding="async" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/35px-Flag_of_the_Cook_Islands.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/46px-Flag_of_the_Cook_Islands.svg.png 2x" data-file-width="1200" data-file-height="600"/> </span><a href="http://fakehost/wiki/Cook_Islands" title="Cook Islands" target="_blank">Cook Islands</a></span>
|
||||
<span><span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/23px-Flag_of_the_Cook_Islands.svg.png" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/35px-Flag_of_the_Cook_Islands.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/46px-Flag_of_the_Cook_Islands.svg.png 2x" data-file-width="1200" data-file-height="600"/> </span><a href="http://fakehost/wiki/Cook_Islands" title="Cook Islands" target="_blank">Cook Islands</a></span>
|
||||
</td>
|
||||
<td rowspan="1">
|
||||
<span><span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/23px-Flag_of_Niue.svg.png" decoding="async" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/35px-Flag_of_Niue.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/46px-Flag_of_Niue.svg.png 2x" data-file-width="600" data-file-height="300"/> </span><a href="http://fakehost/wiki/Niue" title="Niue" target="_blank">Niue</a></span>
|
||||
<span><span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/23px-Flag_of_Niue.svg.png" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/35px-Flag_of_Niue.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/46px-Flag_of_Niue.svg.png 2x" data-file-width="600" data-file-height="300"/> </span><a href="http://fakehost/wiki/Niue" title="Niue" target="_blank">Niue</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -744,7 +744,7 @@
|
|||
<a href="http://fakehost/wiki/Ross_Dependency" title="Ross Dependency" target="_blank">Ross Dependency</a>
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/23px-Flag_of_Tokelau.svg.png" decoding="async" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/35px-Flag_of_Tokelau.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/46px-Flag_of_Tokelau.svg.png 2x" data-file-width="1800" data-file-height="900"/> </span><a href="http://fakehost/wiki/Tokelau" title="Tokelau" target="_blank">Tokelau</a>
|
||||
<span><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/23px-Flag_of_Tokelau.svg.png" width="23" height="12" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/35px-Flag_of_Tokelau.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/46px-Flag_of_Tokelau.svg.png 2x" data-file-width="1800" data-file-height="900"/> </span><a href="http://fakehost/wiki/Tokelau" title="Tokelau" target="_blank">Tokelau</a>
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<span>15 islands</span>
|
||||
|
@ -799,7 +799,7 @@
|
|||
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealand_23_October_2002.jpg" target="_blank"><img alt="Islands of New Zealand as seen from satellite" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/170px-New_Zealand_23_October_2002.jpg" decoding="async" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/255px-New_Zealand_23_October_2002.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/340px-New_Zealand_23_October_2002.jpg 2x" data-file-width="4200" data-file-height="5600"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealand_23_October_2002.jpg" target="_blank"><img alt="Islands of New Zealand as seen from satellite" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/170px-New_Zealand_23_October_2002.jpg" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/255px-New_Zealand_23_October_2002.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/New_Zealand_23_October_2002.jpg/340px-New_Zealand_23_October_2002.jpg 2x" data-file-width="4200" data-file-height="5600"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
New Zealand is located near the centre of the <a href="http://fakehost/wiki/Water_hemisphere" title="Water hemisphere" target="_blank">water hemisphere</a> and is made up of two main islands and a number of <a href="http://fakehost/wiki/List_of_islands_of_New_Zealand" title="List of islands of New Zealand" target="_blank">smaller islands</a>. The two main islands (the <a href="http://fakehost/wiki/North_Island" title="North Island" target="_blank">North Island</a>, or <i>Te Ika-a-Māui</i>, and the <a href="http://fakehost/wiki/South_Island" title="South Island" target="_blank">South Island</a>, or <i>Te Waipounamu</i>) are separated by <a href="http://fakehost/wiki/Cook_Strait" title="Cook Strait" target="_blank">Cook Strait</a>, 22 kilometres (14 mi) wide at its narrowest point.<sup id="cite_ref-145"><a href="#cite_note-145">[138]</a></sup> Besides the North and South Islands, the five largest inhabited islands are <a href="http://fakehost/wiki/Stewart_Island" title="Stewart Island" target="_blank">Stewart Island</a> (across the <a href="http://fakehost/wiki/Foveaux_Strait" title="Foveaux Strait" target="_blank">Foveaux Strait</a>), <a href="http://fakehost/wiki/Chatham_Island" title="Chatham Island" target="_blank">Chatham Island</a>, <a href="http://fakehost/wiki/Great_Barrier_Island" title="Great Barrier Island" target="_blank">Great Barrier Island</a> (in the <a href="http://fakehost/wiki/Hauraki_Gulf" title="Hauraki Gulf" target="_blank">Hauraki Gulf</a>),<sup id="cite_ref-146"><a href="#cite_note-146">[139]</a></sup> <a href="http://fakehost/wiki/D%27Urville_Island_(New_Zealand)" title="D'Urville Island (New Zealand)" target="_blank">D'Urville Island</a> (in the <a href="http://fakehost/wiki/Marlborough_Sounds" title="Marlborough Sounds" target="_blank">Marlborough Sounds</a>)<sup id="cite_ref-147"><a href="#cite_note-147">[140]</a></sup> and <a href="http://fakehost/wiki/Waiheke_Island" title="Waiheke Island" target="_blank">Waiheke Island</a> (about 22 km (14 mi) from central Auckland).<sup id="cite_ref-148"><a href="#cite_note-148">[141]</a></sup>
|
||||
|
@ -807,12 +807,12 @@
|
|||
|
||||
<div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Mt_Cook,_NZ.jpg" target="_blank"><img alt="A large mountain with a lake in the foreground" src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/220px-Mt_Cook%2C_NZ.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/330px-Mt_Cook%2C_NZ.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/440px-Mt_Cook%2C_NZ.jpg 2x" data-file-width="4608" data-file-height="3072"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Mt_Cook,_NZ.jpg" target="_blank"><img alt="A large mountain with a lake in the foreground" src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/220px-Mt_Cook%2C_NZ.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/330px-Mt_Cook%2C_NZ.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Mt_Cook%2C_NZ.jpg/440px-Mt_Cook%2C_NZ.jpg 2x" data-file-width="4608" data-file-height="3072"/></a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealand_moutain_ranges.jpg" target="_blank"><img alt="Snow-capped mountain range" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/220px-New_Zealand_moutain_ranges.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/330px-New_Zealand_moutain_ranges.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/440px-New_Zealand_moutain_ranges.jpg 2x" data-file-width="4272" data-file-height="2848"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealand_moutain_ranges.jpg" target="_blank"><img alt="Snow-capped mountain range" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/220px-New_Zealand_moutain_ranges.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/330px-New_Zealand_moutain_ranges.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/New_Zealand_moutain_ranges.jpg/440px-New_Zealand_moutain_ranges.jpg 2x" data-file-width="4272" data-file-height="2848"/></a>
|
||||
</p>
|
||||
<p>
|
||||
The Southern Alps stretch for 500 kilometres down the South Island
|
||||
|
@ -839,13 +839,13 @@
|
|||
|
||||
<li>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Lake_Gunn.jpg" target="_blank"><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/269px-Lake_Gunn.jpg" decoding="async" width="180" height="120" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/404px-Lake_Gunn.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/538px-Lake_Gunn.jpg 2x" data-file-width="1000" data-file-height="669"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Lake_Gunn.jpg" target="_blank"><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/269px-Lake_Gunn.jpg" width="180" height="120" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/404px-Lake_Gunn.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Lake_Gunn.jpg/538px-Lake_Gunn.jpg 2x" data-file-width="1000" data-file-height="669"/></a>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Pencarrow_Head,_Wellington,_New_Zealand_from_Santa_Regina,_24_Feb._2007.jpg" target="_blank"><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/269px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg" decoding="async" width="180" height="120" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/404px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/538px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg 2x" data-file-width="3872" data-file-height="2592"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Pencarrow_Head,_Wellington,_New_Zealand_from_Santa_Regina,_24_Feb._2007.jpg" target="_blank"><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/269px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg" width="180" height="120" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/404px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg/538px-Pencarrow_Head%2C_Wellington%2C_New_Zealand_from_Santa_Regina%2C_24_Feb._2007.jpg 2x" data-file-width="3872" data-file-height="2592"/></a>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -991,7 +991,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:TeTuatahianui.jpg" target="_blank"><img alt="Kiwi amongst sticks" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/170px-TeTuatahianui.jpg" decoding="async" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/255px-TeTuatahianui.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/340px-TeTuatahianui.jpg 2x" data-file-width="994" data-file-height="1325"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:TeTuatahianui.jpg" target="_blank"><img alt="Kiwi amongst sticks" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/170px-TeTuatahianui.jpg" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/255px-TeTuatahianui.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/82/TeTuatahianui.jpg/340px-TeTuatahianui.jpg 2x" data-file-width="994" data-file-height="1325"/></a></p><div>
|
||||
<p>The endemic flightless <a href="http://fakehost/wiki/Kiwi" title="Kiwi" target="_blank">kiwi</a> is a national icon.
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1002,7 +1002,7 @@
|
|||
Before the arrival of humans, an estimated 80% of the land was covered in forest, with only <a href="http://fakehost/wiki/Tree_line" title="Tree line" target="_blank">high alpine</a>, wet, infertile and volcanic areas without trees.<sup id="cite_ref-180"><a href="#cite_note-180">[173]</a></sup> Massive <a href="http://fakehost/wiki/Deforestation_in_New_Zealand" title="Deforestation in New Zealand" target="_blank">deforestation</a> occurred after humans arrived, with around half the forest cover lost to fire after Polynesian settlement.<sup id="cite_ref-181"><a href="#cite_note-181">[174]</a></sup> Much of the remaining forest fell after European settlement, being logged or cleared to make room for pastoral farming, leaving forest occupying only 23% of the land.<sup id="cite_ref-182"><a href="#cite_note-182">[175]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg" target="_blank"><img alt="An artist's rendition of a Haast's eagle attacking two moa" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/220px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg" decoding="async" width="220" height="176" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/330px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/440px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg 2x" data-file-width="1375" data-file-height="1101"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg" target="_blank"><img alt="An artist's rendition of a Haast's eagle attacking two moa" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/220px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg" width="220" height="176" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/330px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg/440px-Giant_Haasts_eagle_attacking_New_Zealand_moa.jpg 2x" data-file-width="1375" data-file-height="1101"/></a></p><div>
|
||||
<p>The giant <a href="http://fakehost/wiki/Haast%27s_eagle" title="Haast's eagle" target="_blank">Haast's eagle</a> died out when humans hunted its main prey, the <a href="http://fakehost/wiki/Moa" title="Moa" target="_blank">moa</a>, to extinction.
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1022,7 +1022,7 @@
|
|||
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Auckland_Waterfrt.jpg" target="_blank"><img alt="Boats docked in blue-green water. Plate glass skyscrapers rising up in the background." src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/220px-Auckland_Waterfrt.jpg" decoding="async" width="220" height="145" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/330px-Auckland_Waterfrt.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/440px-Auckland_Waterfrt.jpg 2x" data-file-width="4568" data-file-height="3019"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Auckland_Waterfrt.jpg" target="_blank"><img alt="Boats docked in blue-green water. Plate glass skyscrapers rising up in the background." src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/220px-Auckland_Waterfrt.jpg" width="220" height="145" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/330px-Auckland_Waterfrt.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Auckland_Waterfrt.jpg/440px-Auckland_Waterfrt.jpg 2x" data-file-width="4568" data-file-height="3019"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
New Zealand has an <a href="http://fakehost/wiki/Advanced_economy" title="Advanced economy" target="_blank">advanced</a> <a href="http://fakehost/wiki/Market_economy" title="Market economy" target="_blank">market economy</a>,<sup id="cite_ref-200"><a href="#cite_note-200">[193]</a></sup> ranked 16th in the 2018 <a href="http://fakehost/wiki/Human_Development_Index" title="Human Development Index" target="_blank">Human Development Index</a><sup id="cite_ref-HDI_12-1"><a href="#cite_note-HDI-12">[8]</a></sup> and third in the 2018 <a href="http://fakehost/wiki/Index_of_Economic_Freedom" title="Index of Economic Freedom" target="_blank">Index of Economic Freedom</a>.<sup id="cite_ref-201"><a href="#cite_note-201">[194]</a></sup> It is a <a href="http://fakehost/wiki/High-income_economy" title="High-income economy" target="_blank">high-income economy</a> with a <a href="http://fakehost/wiki/Nominal_value" title="Nominal value" target="_blank">nominal</a> <a href="http://fakehost/wiki/Gross_domestic_product" title="Gross domestic product" target="_blank">gross domestic product</a> (GDP) per capita of <a href="http://fakehost/wiki/United_States_dollar" title="United States dollar" target="_blank">US$</a>36,254.<sup id="cite_ref-imf2_10-4"><a href="#cite_note-imf2-10">[6]</a></sup> The currency is the <a href="http://fakehost/wiki/New_Zealand_dollar" title="New Zealand dollar" target="_blank">New Zealand dollar</a>, informally known as the "Kiwi dollar"; it also circulates in the Cook Islands (see <a href="http://fakehost/wiki/Cook_Islands_dollar" title="Cook Islands dollar" target="_blank">Cook Islands dollar</a>), Niue, Tokelau, and the <a href="http://fakehost/wiki/Pitcairn_Islands" title="Pitcairn Islands" target="_blank">Pitcairn Islands</a>.<sup id="cite_ref-202"><a href="#cite_note-202">[195]</a></sup>
|
||||
|
@ -1031,7 +1031,7 @@
|
|||
Historically, extractive industries have contributed strongly to New Zealand's economy, focussing at different times on sealing, whaling, <a href="http://fakehost/wiki/Phormium" title="Phormium" target="_blank">flax</a>, gold, <a href="http://fakehost/wiki/Kauri_gum" title="Kauri gum" target="_blank">kauri gum</a>, and native timber.<sup id="cite_ref-RWT_export_evolution_203-0"><a href="#cite_note-RWT_export_evolution-203">[196]</a></sup> The first shipment of refrigerated meat on the <i><a href="http://fakehost/wiki/Dunedin_(ship)" title="Dunedin (ship)" target="_blank">Dunedin</a></i> in 1882 led to the establishment of meat and dairy exports to Britain, a trade which provided the basis for strong economic growth in New Zealand.<sup id="cite_ref-204"><a href="#cite_note-204">[197]</a></sup> High demand for agricultural products from the United Kingdom and the United States helped New Zealanders achieve higher living standards than both Australia and Western Europe in the 1950s and 1960s.<sup id="cite_ref-205"><a href="#cite_note-205">[198]</a></sup> In 1973, New Zealand's export market was reduced when the United Kingdom joined the <a href="http://fakehost/wiki/European_Economic_Community" title="European Economic Community" target="_blank">European Economic Community</a><sup id="cite_ref-206"><a href="#cite_note-206">[199]</a></sup> and other compounding factors, such as the <a href="http://fakehost/wiki/1973_oil_crisis" title="1973 oil crisis" target="_blank">1973 oil</a> and <a href="http://fakehost/wiki/1979_oil_crisis" title="1979 oil crisis" target="_blank">1979 energy</a> crises, led to a severe <a href="http://fakehost/wiki/Depression_(economics)" title="Depression (economics)" target="_blank">economic depression</a>.<sup id="cite_ref-207"><a href="#cite_note-207">[200]</a></sup> Living standards in New Zealand fell behind those of Australia and Western Europe, and by 1982 New Zealand had the lowest per-capita income of all the developed nations surveyed by <a href="http://fakehost/wiki/World_Bank_Group" title="World Bank Group" target="_blank">the World Bank</a>.<sup id="cite_ref-208"><a href="#cite_note-208">[201]</a></sup> In the mid-1980s New Zealand deregulated its <a href="http://fakehost/wiki/Agriculture_in_New_Zealand" title="Agriculture in New Zealand" target="_blank">agricultural sector</a> by phasing out <a href="http://fakehost/wiki/Agricultural_subsidy" title="Agricultural subsidy" target="_blank">subsidies</a> over a three-year period.<sup id="cite_ref-209"><a href="#cite_note-209">[202]</a></sup><sup id="cite_ref-210"><a href="#cite_note-210">[203]</a></sup> Since 1984, successive governments engaged in major <a href="http://fakehost/wiki/Macroeconomic" title="Macroeconomic" target="_blank">macroeconomic</a> restructuring (known first as <a href="http://fakehost/wiki/Rogernomics" title="Rogernomics" target="_blank">Rogernomics</a> and then <a href="http://fakehost/wiki/Ruthanasia" title="Ruthanasia" target="_blank">Ruthanasia</a>), rapidly transforming New Zealand from a <a href="http://fakehost/wiki/Protectionism" title="Protectionism" target="_blank">protected</a> and highly regulated economy to a liberalised <a href="http://fakehost/wiki/Free-trade" title="Free-trade" target="_blank">free-trade</a> economy.<sup id="cite_ref-Liberalisation_211-0"><a href="#cite_note-Liberalisation-211">[204]</a></sup><sup id="cite_ref-212"><a href="#cite_note-212">[205]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:MilfordSound.jpg" target="_blank"><img alt="Blue water against a backdrop of snow-capped mountains" src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/220px-MilfordSound.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/330px-MilfordSound.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/440px-MilfordSound.jpg 2x" data-file-width="2048" data-file-height="1364"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:MilfordSound.jpg" target="_blank"><img alt="Blue water against a backdrop of snow-capped mountains" src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/220px-MilfordSound.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/330px-MilfordSound.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/4/42/MilfordSound.jpg/440px-MilfordSound.jpg 2x" data-file-width="2048" data-file-height="1364"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/Milford_Sound" title="Milford Sound" target="_blank">Milford Sound</a> is one of New Zealand's most famous tourist destinations.<sup id="cite_ref-213"><a href="#cite_note-213">[206]</a></sup>
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1045,7 +1045,7 @@
|
|||
New Zealand is heavily dependent on international trade,<sup id="cite_ref-224"><a href="#cite_note-224">[217]</a></sup> particularly in agricultural products.<sup id="cite_ref-225"><a href="#cite_note-225">[218]</a></sup> Exports account for 24% of its output,<sup id="cite_ref-CIA_150-1"><a href="#cite_note-CIA-150">[143]</a></sup> making New Zealand vulnerable to international commodity prices and global <a href="http://fakehost/wiki/Recession" title="Recession" target="_blank">economic slowdowns</a>. Food products made up 55% of the value of all the country's exports in 2014; wood was the second largest earner (7%).<sup id="cite_ref-226"><a href="#cite_note-226">[219]</a></sup> New Zealand's main trading partners, as at June 2018, are China (<a href="http://fakehost/wiki/NZ$" title="NZ$" target="_blank">NZ$</a>27.8b), Australia ($26.2b), the <a href="http://fakehost/wiki/European_Union" title="European Union" target="_blank">European Union</a> ($22.9b), the United States ($17.6b), and Japan ($8.4b).<sup id="cite_ref-GSTC_StatNZ_227-0"><a href="#cite_note-GSTC_StatNZ-227">[220]</a></sup> On 7 April 2008, New Zealand and China signed the <a href="http://fakehost/wiki/New_Zealand%E2%80%93China_Free_Trade_Agreement" title="New Zealand–China Free Trade Agreement" target="_blank">New Zealand–China Free Trade Agreement</a>, the first such agreement China has signed with a developed country.<sup id="cite_ref-228"><a href="#cite_note-228">[221]</a></sup> The service sector is the largest sector in the economy, followed by manufacturing and construction and then farming and raw material extraction.<sup id="cite_ref-CIA_150-2"><a href="#cite_note-CIA-150">[143]</a></sup> <a href="http://fakehost/wiki/Tourism_in_New_Zealand" title="Tourism in New Zealand" target="_blank">Tourism</a> plays a significant role in the economy, contributing $12.9 billion (or 5.6%) to New Zealand's total GDP and supporting 7.5% of the total workforce in 2016.<sup id="cite_ref-TourismStats_229-0"><a href="#cite_note-TourismStats-229">[222]</a></sup> International visitor arrivals are expected to increase at a rate of 5.4% annually up to 2022.<sup id="cite_ref-TourismStats_229-1"><a href="#cite_note-TourismStats-229">[222]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Fauna_de_Nueva_Zelanda07.JPG" target="_blank"><img alt="A Romney ewe with her two lambs" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/220px-Fauna_de_Nueva_Zelanda07.JPG" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/330px-Fauna_de_Nueva_Zelanda07.JPG 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/440px-Fauna_de_Nueva_Zelanda07.JPG 2x" data-file-width="3888" data-file-height="2592"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Fauna_de_Nueva_Zelanda07.JPG" target="_blank"><img alt="A Romney ewe with her two lambs" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/220px-Fauna_de_Nueva_Zelanda07.JPG" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/330px-Fauna_de_Nueva_Zelanda07.JPG 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Fauna_de_Nueva_Zelanda07.JPG/440px-Fauna_de_Nueva_Zelanda07.JPG 2x" data-file-width="3888" data-file-height="2592"/></a></p><div>
|
||||
<p>Wool has historically been one of New Zealand's major exports.
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1056,7 +1056,7 @@
|
|||
<span id="Infrastructure">Infrastructure</span>
|
||||
</h3>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Air_New_Zealand,_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_(27091961041).jpg" target="_blank"><img alt="A mid-size jet airliner in flight. The plane livery is all-black and features a New Zealand silver fern mark." src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/220px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/330px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/440px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg 2x" data-file-width="5625" data-file-height="3750"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Air_New_Zealand,_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_(27091961041).jpg" target="_blank"><img alt="A mid-size jet airliner in flight. The plane livery is all-black and features a New Zealand silver fern mark." src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/220px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/330px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg/440px-Air_New_Zealand%2C_Boeing_787-9_ZK-NZE_%27All_Blacks%27_NRT_%2827091961041%29.jpg 2x" data-file-width="5625" data-file-height="3750"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
In 2015, <a href="http://fakehost/wiki/Renewable_energy_in_New_Zealand" title="Renewable energy in New Zealand" target="_blank">renewable energy</a>, primarily <a href="http://fakehost/wiki/Geothermal_power_in_New_Zealand" title="Geothermal power in New Zealand" target="_blank">geothermal</a> and <a href="http://fakehost/wiki/Hydroelectric_power_in_New_Zealand" title="Hydroelectric power in New Zealand" target="_blank">hydroelectric power</a>, generated 40.1% of <a href="http://fakehost/wiki/Energy_in_New_Zealand" title="Energy in New Zealand" target="_blank">New Zealand's gross energy</a> supply.<sup id="cite_ref-Energy2015_238-0"><a href="#cite_note-Energy2015-238">[231]</a></sup> Geothermal power alone accounted for 22% of New Zealand's energy in 2015.<sup id="cite_ref-Energy2015_238-1"><a href="#cite_note-Energy2015-238">[231]</a></sup>
|
||||
|
@ -1075,7 +1075,7 @@
|
|||
</h2>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealandpop.svg" target="_blank"><img alt="Stationary population pyramid broken down into 21 age ranges." src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/280px-New_Zealandpop.svg.png" decoding="async" width="280" height="210" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/420px-New_Zealandpop.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/560px-New_Zealandpop.svg.png 2x" data-file-width="800" data-file-height="600"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:New_Zealandpop.svg" target="_blank"><img alt="Stationary population pyramid broken down into 21 age ranges." src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/280px-New_Zealandpop.svg.png" width="280" height="210" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/420px-New_Zealandpop.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/New_Zealandpop.svg/560px-New_Zealandpop.svg.png 2x" data-file-width="800" data-file-height="600"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
The <a href="http://fakehost/wiki/2013_New_Zealand_census" title="2013 New Zealand census" target="_blank">2013 New Zealand census</a> enumerated a resident population of 4,242,048, an increase of 5.3% over the 2006 figure.<sup id="cite_ref-252"><a href="#cite_note-252">[245]</a></sup><sup id="cite_ref-254"><a href="#cite_note-254">[n 8]</a></sup> As of September 2019, the total population has risen to an estimated 4,933,210.<sup id="cite_ref-populationestimate_9-1"><a href="#cite_note-populationestimate-9">[5]</a></sup>
|
||||
|
@ -1141,9 +1141,9 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td rowspan="11">
|
||||
<a href="http://fakehost/wiki/File:Auckland_Cbd_(217403753).jpeg" title="Auckland" target="_blank"><img alt="Auckland" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/120px-Auckland_Cbd_%28217403753%29.jpeg" decoding="async" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/180px-Auckland_Cbd_%28217403753%29.jpeg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/240px-Auckland_Cbd_%28217403753%29.jpeg 2x" data-file-width="2048" data-file-height="1362"/></a><br/>
|
||||
<a href="http://fakehost/wiki/File:Auckland_Cbd_(217403753).jpeg" title="Auckland" target="_blank"><img alt="Auckland" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/120px-Auckland_Cbd_%28217403753%29.jpeg" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/180px-Auckland_Cbd_%28217403753%29.jpeg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Auckland_Cbd_%28217403753%29.jpeg/240px-Auckland_Cbd_%28217403753%29.jpeg 2x" data-file-width="2048" data-file-height="1362"/></a><br/>
|
||||
<a href="http://fakehost/wiki/Auckland" title="Auckland" target="_blank">Auckland</a><br/>
|
||||
<a href="http://fakehost/wiki/File:Wellington_at_dawn.jpg" title="Wellington" target="_blank"><img alt="Wellington" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/120px-Wellington_at_dawn.jpg" decoding="async" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/180px-Wellington_at_dawn.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/240px-Wellington_at_dawn.jpg 2x" data-file-width="3718" data-file-height="2479"/></a><br/>
|
||||
<a href="http://fakehost/wiki/File:Wellington_at_dawn.jpg" title="Wellington" target="_blank"><img alt="Wellington" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/120px-Wellington_at_dawn.jpg" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/180px-Wellington_at_dawn.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Wellington_at_dawn.jpg/240px-Wellington_at_dawn.jpg 2x" data-file-width="3718" data-file-height="2479"/></a><br/>
|
||||
<a href="http://fakehost/wiki/Wellington" title="Wellington" target="_blank">Wellington</a>
|
||||
</td>
|
||||
<td>
|
||||
|
@ -1171,9 +1171,9 @@
|
|||
58,800
|
||||
</td>
|
||||
<td rowspan="11">
|
||||
<a href="http://fakehost/wiki/File:Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_(2).jpg" title="Christchurch" target="_blank"><img alt="Christchurch" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/120px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg" decoding="async" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/180px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/240px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg 2x" data-file-width="1800" data-file-height="1200"/></a><br/>
|
||||
<a href="http://fakehost/wiki/File:Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_(2).jpg" title="Christchurch" target="_blank"><img alt="Christchurch" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/120px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg" width="120" height="80" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/180px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg/240px-Aerial_image_of_Christchurch_suburbs_-_Flickr_-_NZ_Defence_Force_%282%29.jpg 2x" data-file-width="1800" data-file-height="1200"/></a><br/>
|
||||
<a href="http://fakehost/wiki/Christchurch" title="Christchurch" target="_blank">Christchurch</a><br/>
|
||||
<a href="http://fakehost/wiki/File:HamiltonNZfromUni.jpg" title="Hamilton" target="_blank"><img alt="Hamilton" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/120px-HamiltonNZfromUni.jpg" decoding="async" width="120" height="85" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/180px-HamiltonNZfromUni.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/240px-HamiltonNZfromUni.jpg 2x" data-file-width="3581" data-file-height="2528"/></a><br/>
|
||||
<a href="http://fakehost/wiki/File:HamiltonNZfromUni.jpg" title="Hamilton" target="_blank"><img alt="Hamilton" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/120px-HamiltonNZfromUni.jpg" width="120" height="85" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/180px-HamiltonNZfromUni.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/HamiltonNZfromUni.jpg/240px-HamiltonNZfromUni.jpg 2x" data-file-width="3581" data-file-height="2528"/></a><br/>
|
||||
<a href="http://fakehost/wiki/Hamilton,_New_Zealand" title="Hamilton, New Zealand" target="_blank">Hamilton</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1419,7 +1419,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Queen_Street_Midtown_Auckland.jpg" target="_blank"><img alt="Pedestrians crossing a wide street which is flanked by storefronts" src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/220px-Queen_Street_Midtown_Auckland.jpg" decoding="async" width="220" height="158" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/330px-Queen_Street_Midtown_Auckland.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/440px-Queen_Street_Midtown_Auckland.jpg 2x" data-file-width="841" data-file-height="604"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Queen_Street_Midtown_Auckland.jpg" target="_blank"><img alt="Pedestrians crossing a wide street which is flanked by storefronts" src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/220px-Queen_Street_Midtown_Auckland.jpg" width="220" height="158" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/330px-Queen_Street_Midtown_Auckland.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Queen_Street_Midtown_Auckland.jpg/440px-Queen_Street_Midtown_Auckland.jpg 2x" data-file-width="841" data-file-height="604"/></a></p><div>
|
||||
<p>Pedestrians on <a href="http://fakehost/wiki/Queen_Street,_Auckland" title="Queen Street, Auckland" target="_blank">Queen Street</a> in Auckland, an ethnically diverse city
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1437,7 +1437,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:TeReoMaori2013.png" target="_blank"><img alt="Map of New Zealand showing the percentage of people in each census area unit who speak Māori. Areas of the North Island exhibit the highest Māori proficiency." src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/220px-TeReoMaori2013.png" decoding="async" width="220" height="165" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/330px-TeReoMaori2013.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/440px-TeReoMaori2013.png 2x" data-file-width="5000" data-file-height="3759"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:TeReoMaori2013.png" target="_blank"><img alt="Map of New Zealand showing the percentage of people in each census area unit who speak Māori. Areas of the North Island exhibit the highest Māori proficiency." src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/220px-TeReoMaori2013.png" width="220" height="165" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/330px-TeReoMaori2013.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/TeReoMaori2013.png/440px-TeReoMaori2013.png 2x" data-file-width="5000" data-file-height="3759"/></a></p><div>
|
||||
<p>Speakers of Māori according to the 2013 census<sup id="cite_ref-278"><a href="#cite_note-278">[270]</a></sup></p><p> Less than 5%
|
||||
</p>
|
||||
<p> More than 5%
|
||||
|
@ -1469,7 +1469,7 @@
|
|||
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Ratana_Church_Raetihi.jpg" target="_blank"><img alt="Simple white building with two red domed towers" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/170px-Ratana_Church_Raetihi.jpg" decoding="async" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/255px-Ratana_Church_Raetihi.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/340px-Ratana_Church_Raetihi.jpg 2x" data-file-width="1624" data-file-height="2164"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Ratana_Church_Raetihi.jpg" target="_blank"><img alt="Simple white building with two red domed towers" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/170px-Ratana_Church_Raetihi.jpg" width="170" height="227" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/255px-Ratana_Church_Raetihi.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Ratana_Church_Raetihi.jpg/340px-Ratana_Church_Raetihi.jpg 2x" data-file-width="1624" data-file-height="2164"/></a></p><div>
|
||||
<p>A <a href="http://fakehost/wiki/R%C4%81tana" title="Rātana" target="_blank">Rātana</a> church on a hill near <a href="http://fakehost/wiki/Raetihi" title="Raetihi" target="_blank">Raetihi</a>. The two-tower construction is characteristic of Rātana buildings.
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -1489,7 +1489,7 @@
|
|||
</h2>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:KupeWheke.jpg" title="Use the scrollbar to see the full image." target="_blank"><img alt="Tall wooden carving showing Kupe above two tentacled sea creatures" src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/150px-KupeWheke.jpg" decoding="async" width="150" height="605" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/225px-KupeWheke.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/300px-KupeWheke.jpg 2x" data-file-width="389" data-file-height="1570"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:KupeWheke.jpg" title="Use the scrollbar to see the full image." target="_blank"><img alt="Tall wooden carving showing Kupe above two tentacled sea creatures" src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/150px-KupeWheke.jpg" width="150" height="605" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/225px-KupeWheke.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/KupeWheke.jpg/300px-KupeWheke.jpg 2x" data-file-width="389" data-file-height="1570"/></a>
|
||||
</p>
|
||||
<div>
|
||||
<p>Late 20th-century house-post depicting the navigator <a href="http://fakehost/wiki/Kupe" title="Kupe" target="_blank">Kupe</a> fighting two sea creatures
|
||||
|
@ -1515,7 +1515,7 @@
|
|||
Māori decorated the white wood of buildings, canoes and cenotaphs using red (a mixture of red <a href="http://fakehost/wiki/Ochre" title="Ochre" target="_blank">ochre</a> and shark fat) and black (made from soot) paint and painted pictures of birds, reptiles and other designs on cave walls.<sup id="cite_ref-321"><a href="#cite_note-321">[310]</a></sup> Māori tattoos (<i><a href="http://fakehost/wiki/T%C4%81_moko" title="Tā moko" target="_blank">moko</a></i>) consisting of coloured soot mixed with gum were cut into the flesh with a bone chisel.<sup id="cite_ref-322"><a href="#cite_note-322">[311]</a></sup> Since European arrival paintings and photographs have been dominated by landscapes, originally not as works of art but as factual portrayals of New Zealand.<sup id="cite_ref-beginnings_323-0"><a href="#cite_note-beginnings-323">[312]</a></sup> Portraits of Māori were also common, with early painters often portraying them as "<a href="http://fakehost/wiki/Noble_savage" title="Noble savage" target="_blank">noble savages</a>", exotic beauties or friendly natives.<sup id="cite_ref-beginnings_323-1"><a href="#cite_note-beginnings-323">[312]</a></sup> The country's isolation delayed the influence of European artistic trends allowing local artists to develop their own distinctive style of <a href="http://fakehost/wiki/Regionalism_(art)" title="Regionalism (art)" target="_blank">regionalism</a>.<sup id="cite_ref-324"><a href="#cite_note-324">[313]</a></sup> During the 1960s and 1970s many artists combined traditional Māori and Western techniques, creating unique art forms.<sup id="cite_ref-325"><a href="#cite_note-325">[314]</a></sup> New Zealand art and craft has gradually achieved an international audience, with exhibitions in the <a href="http://fakehost/wiki/Venice_Biennale" title="Venice Biennale" target="_blank">Venice Biennale</a> in 2001 and the "Paradise Now" exhibition in New York in 2004.<sup id="cite_ref-Creative_317-1"><a href="#cite_note-Creative-317">[306]</a></sup><sup id="cite_ref-326"><a href="#cite_note-326">[315]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Hinepare.jpg" target="_blank"><img alt="Refer to caption" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/170px-Hinepare.jpg" decoding="async" width="170" height="218" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/255px-Hinepare.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/340px-Hinepare.jpg 2x" data-file-width="545" data-file-height="700"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Hinepare.jpg" target="_blank"><img alt="Refer to caption" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/170px-Hinepare.jpg" width="170" height="218" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/255px-Hinepare.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Hinepare.jpg/340px-Hinepare.jpg 2x" data-file-width="545" data-file-height="700"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
Māori cloaks are made of fine flax fibre and patterned with black, red and white triangles, diamonds and other geometric shapes.<sup id="cite_ref-327"><a href="#cite_note-327">[316]</a></sup> <a href="http://fakehost/wiki/Pounamu" title="Pounamu" target="_blank">Greenstone</a> was fashioned into earrings and necklaces, with the most well-known design being the <a href="http://fakehost/wiki/Hei-tiki" title="Hei-tiki" target="_blank">hei-tiki</a>, a distorted human figure sitting cross-legged with its head tilted to the side.<sup id="cite_ref-328"><a href="#cite_note-328">[317]</a></sup> Europeans brought English fashion etiquette to New Zealand, and until the 1950s most people dressed up for social occasions.<sup id="cite_ref-329"><a href="#cite_note-329">[318]</a></sup> Standards have since relaxed and New Zealand fashion has received a reputation for being casual, practical and lacklustre.<sup id="cite_ref-330"><a href="#cite_note-330">[319]</a></sup><sup id="cite_ref-The_Economist_print_edition_331-0"><a href="#cite_note-The_Economist_print_edition-331">[320]</a></sup> However, the local fashion industry has grown significantly since 2000, doubling exports and increasing from a handful to about 50 established labels, with some labels gaining international recognition.<sup id="cite_ref-The_Economist_print_edition_331-1"><a href="#cite_note-The_Economist_print_edition-331">[320]</a></sup>
|
||||
|
@ -1535,7 +1535,7 @@
|
|||
New Zealand music has been influenced by <a href="http://fakehost/wiki/Blues" title="Blues" target="_blank">blues</a>, <a href="http://fakehost/wiki/Jazz" title="Jazz" target="_blank">jazz</a>, <a href="http://fakehost/wiki/Country_music" title="Country music" target="_blank">country</a>, <a href="http://fakehost/wiki/Rock_and_roll" title="Rock and roll" target="_blank">rock and roll</a> and <a href="http://fakehost/wiki/Hip_hop_music" title="Hip hop music" target="_blank">hip hop</a>, with many of these genres given a unique New Zealand interpretation.<sup id="cite_ref-music_337-0"><a href="#cite_note-music-337">[326]</a></sup> Māori developed traditional chants and songs from their ancient Southeast Asian origins, and after centuries of isolation created a unique "monotonous" and "<a href="https://en.wiktionary.org/wiki/doleful" title="wikt:doleful" target="_blank">doleful</a>" sound.<sup id="cite_ref-338"><a href="#cite_note-338">[327]</a></sup> Flutes and trumpets were used as musical instruments<sup id="cite_ref-339"><a href="#cite_note-339">[328]</a></sup> or as signalling devices during war or special occasions.<sup id="cite_ref-340"><a href="#cite_note-340">[329]</a></sup> Early settlers brought over their ethnic music, with <a href="http://fakehost/wiki/Brass_band" title="Brass band" target="_blank">brass bands</a> and <a href="http://fakehost/wiki/Choir" title="Choir" target="_blank">choral music</a> being popular, and musicians began touring New Zealand in the 1860s.<sup id="cite_ref-341"><a href="#cite_note-341">[330]</a></sup><sup id="cite_ref-342"><a href="#cite_note-342">[331]</a></sup> <a href="http://fakehost/wiki/Pipe_band" title="Pipe band" target="_blank">Pipe bands</a> became widespread during the early 20th century.<sup id="cite_ref-343"><a href="#cite_note-343">[332]</a></sup> The New Zealand recording industry began to develop from 1940 onwards and many New Zealand musicians have obtained success in Britain and the United States.<sup id="cite_ref-music_337-1"><a href="#cite_note-music-337">[326]</a></sup> Some artists release Māori language songs and the Māori tradition-based art of <i><a href="http://fakehost/wiki/Kapa_haka" title="Kapa haka" target="_blank">kapa haka</a></i> (song and dance) has made a resurgence.<sup id="cite_ref-344"><a href="#cite_note-344">[333]</a></sup> The <a href="http://fakehost/wiki/New_Zealand_Music_Awards" title="New Zealand Music Awards" target="_blank">New Zealand Music Awards</a> are held annually by <a href="http://fakehost/wiki/Recorded_Music_NZ" title="Recorded Music NZ" target="_blank">Recorded Music NZ</a>; the awards were first held in 1965 by <a href="http://fakehost/wiki/Reckitt_%26_Colman" title="Reckitt & Colman" target="_blank">Reckitt & Colman</a> as the <a href="http://fakehost/wiki/Loxene_Golden_Disc" title="Loxene Golden Disc" target="_blank">Loxene Golden Disc</a> awards.<sup id="cite_ref-345"><a href="#cite_note-345">[334]</a></sup> Recorded Music NZ also publishes the country's <a href="http://fakehost/wiki/Official_New_Zealand_Music_Chart" title="Official New Zealand Music Chart" target="_blank">official weekly record charts</a>.<sup id="cite_ref-346"><a href="#cite_note-346">[335]</a></sup>
|
||||
</p>
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Hobbit_holes_reflected_in_water.jpg" target="_blank"><img alt="Hills with inset, round doors. Reflected in water." src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/220px-Hobbit_holes_reflected_in_water.jpg" decoding="async" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/330px-Hobbit_holes_reflected_in_water.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/440px-Hobbit_holes_reflected_in_water.jpg 2x" data-file-width="5184" data-file-height="3456"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Hobbit_holes_reflected_in_water.jpg" target="_blank"><img alt="Hills with inset, round doors. Reflected in water." src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/220px-Hobbit_holes_reflected_in_water.jpg" width="220" height="147" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/330px-Hobbit_holes_reflected_in_water.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Hobbit_holes_reflected_in_water.jpg/440px-Hobbit_holes_reflected_in_water.jpg 2x" data-file-width="5184" data-file-height="3456"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
Public <a href="http://fakehost/wiki/Radio_in_New_Zealand" title="Radio in New Zealand" target="_blank">radio</a> was introduced in New Zealand in 1922.<sup id="cite_ref-348"><a href="#cite_note-348">[337]</a></sup> A state-owned <a href="http://fakehost/wiki/Television_in_New_Zealand" title="Television in New Zealand" target="_blank">television service</a> began in 1960.<sup id="cite_ref-349"><a href="#cite_note-349">[338]</a></sup> Deregulation in the 1980s saw a sudden increase in the numbers of radio and television stations.<sup id="cite_ref-NZ_TV_350-0"><a href="#cite_note-NZ_TV-350">[339]</a></sup> New Zealand television primarily broadcasts American and British programming, along with a large number of Australian and local shows.<sup id="cite_ref-351"><a href="#cite_note-351">[340]</a></sup> The number of <a href="http://fakehost/wiki/List_of_New_Zealand_films" title="List of New Zealand films" target="_blank">New Zealand films</a> significantly increased during the 1970s. In 1978 the <a href="http://fakehost/wiki/New_Zealand_Film_Commission" title="New Zealand Film Commission" target="_blank">New Zealand Film Commission</a> started assisting local film-makers and many films attained a world audience, some receiving international acknowledgement.<sup id="cite_ref-NZ_TV_350-1"><a href="#cite_note-NZ_TV-350">[339]</a></sup> The highest-grossing New Zealand films are <i><a href="http://fakehost/wiki/Hunt_for_the_Wilderpeople" title="Hunt for the Wilderpeople" target="_blank">Hunt for the Wilderpeople</a></i>, <i><a href="http://fakehost/wiki/Boy_(2010_film)" title="Boy (2010 film)" target="_blank">Boy</a></i>, <i><a href="http://fakehost/wiki/The_World%27s_Fastest_Indian" title="The World's Fastest Indian" target="_blank">The World's Fastest Indian</a></i>, <i><a href="http://fakehost/wiki/Once_Were_Warriors_(film)" title="Once Were Warriors (film)" target="_blank">Once Were Warriors</a></i> and <i><a href="http://fakehost/wiki/Whale_Rider" title="Whale Rider" target="_blank">Whale Rider</a></i>.<sup id="cite_ref-352"><a href="#cite_note-352">[341]</a></sup> The country's diverse scenery and compact size, plus government incentives,<sup id="cite_ref-353"><a href="#cite_note-353">[342]</a></sup> have encouraged some <a href="http://fakehost/wiki/Film_producer" title="Film producer" target="_blank">producers</a> to shoot big-budget productions in New Zealand, including <i><a href="http://fakehost/wiki/Avatar_(2009_film)" title="Avatar (2009 film)" target="_blank">Avatar</a></i>, <i><a href="http://fakehost/wiki/The_Lord_of_the_Rings_(film_series)" title="The Lord of the Rings (film series)" target="_blank">The Lord of the Rings</a></i>, <i><a href="http://fakehost/wiki/The_Hobbit_(film_series)" title="The Hobbit (film series)" target="_blank">The Hobbit</a></i>, <i><a href="http://fakehost/wiki/The_Chronicles_of_Narnia_(film_series)" title="The Chronicles of Narnia (film series)" target="_blank">The Chronicles of Narnia</a></i>, <i><a href="http://fakehost/wiki/King_Kong_(2005_film)" title="King Kong (2005 film)" target="_blank">King Kong</a></i> and <i><a href="http://fakehost/wiki/The_Last_Samurai" title="The Last Samurai" target="_blank">The Last Samurai</a></i>.<sup id="cite_ref-354"><a href="#cite_note-354">[343]</a></sup> The New Zealand media industry is dominated by a small number of companies, most of which are foreign-owned, although the <a href="http://fakehost/wiki/Crown_entity" title="Crown entity" target="_blank">state retains ownership</a> of some television and radio stations.<sup id="cite_ref-355"><a href="#cite_note-355">[344]</a></sup> Since 1994, <a href="http://fakehost/wiki/Freedom_House" title="Freedom House" target="_blank">Freedom House</a> has consistently ranked New Zealand's press freedom in the top twenty, with the 19th freest media in 2015.<sup id="cite_ref-356"><a href="#cite_note-356">[345]</a></sup>
|
||||
|
@ -1546,7 +1546,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Haka_2006.jpg" target="_blank"><img alt="Rugby team wearing all black, facing the camera, knees bent, and facing toward a team wearing white" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/220px-Haka_2006.jpg" decoding="async" width="220" height="146" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/330px-Haka_2006.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/440px-Haka_2006.jpg 2x" data-file-width="3008" data-file-height="2000"/></a></p>
|
||||
<p><a href="http://fakehost/wiki/File:Haka_2006.jpg" target="_blank"><img alt="Rugby team wearing all black, facing the camera, knees bent, and facing toward a team wearing white" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/220px-Haka_2006.jpg" width="220" height="146" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/330px-Haka_2006.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Haka_2006.jpg/440px-Haka_2006.jpg 2x" data-file-width="3008" data-file-height="2000"/></a></p>
|
||||
</div>
|
||||
<p>
|
||||
Most of the major sporting codes played in New Zealand have British origins.<sup id="cite_ref-357"><a href="#cite_note-357">[346]</a></sup> <a href="http://fakehost/wiki/Rugby_union" title="Rugby union" target="_blank">Rugby union</a> is considered the <a href="http://fakehost/wiki/National_sport" title="National sport" target="_blank">national sport</a><sup id="cite_ref-358"><a href="#cite_note-358">[347]</a></sup> and attracts the most spectators.<sup id="cite_ref-Organised_Sport_359-0"><a href="#cite_note-Organised_Sport-359">[348]</a></sup> <a href="http://fakehost/wiki/Golf" title="Golf" target="_blank">Golf</a>, <a href="http://fakehost/wiki/Netball" title="Netball" target="_blank">netball</a>, <a href="http://fakehost/wiki/Tennis" title="Tennis" target="_blank">tennis</a> and <a href="http://fakehost/wiki/Cricket" title="Cricket" target="_blank">cricket</a> have the highest rates of adult participation, while netball, rugby union and <a href="http://fakehost/wiki/Association_football" title="Association football" target="_blank">football (soccer)</a> are particularly popular among young people.<sup id="cite_ref-Organised_Sport_359-1"><a href="#cite_note-Organised_Sport-359">[348]</a></sup><sup id="cite_ref-nzsssc_360-0"><a href="#cite_note-nzsssc-360">[349]</a></sup> Around 54% of New Zealand adolescents participate in sports for their school.<sup id="cite_ref-nzsssc_360-1"><a href="#cite_note-nzsssc-360">[349]</a></sup> Victorious rugby tours to Australia and the United Kingdom in the <a href="http://fakehost/wiki/1888%E2%80%9389_New_Zealand_Native_football_team" title="1888–89 New Zealand Native football team" target="_blank">late 1880s</a> and the <a href="http://fakehost/wiki/The_Original_All_Blacks" title="The Original All Blacks" target="_blank">early 1900s</a> played an early role in instilling a national identity.<sup id="cite_ref-361"><a href="#cite_note-361">[350]</a></sup> <a href="http://fakehost/wiki/Horseracing_in_New_Zealand" title="Horseracing in New Zealand" target="_blank">Horseracing</a> was also a popular <a href="http://fakehost/wiki/Spectator_sport" title="Spectator sport" target="_blank">spectator sport</a> and became part of the "Rugby, Racing and Beer" culture during the 1960s.<sup id="cite_ref-362"><a href="#cite_note-362">[351]</a></sup> Māori participation in European sports was particularly evident in rugby and the country's team performs a <a href="http://fakehost/wiki/Haka_(sports)" title="Haka (sports)" target="_blank">haka</a>, a traditional Māori challenge, before international matches.<sup id="cite_ref-363"><a href="#cite_note-363">[352]</a></sup> New Zealand is known for its <a href="http://fakehost/wiki/Extreme_sport" title="Extreme sport" target="_blank">extreme sports</a>, <a href="http://fakehost/wiki/Adventure_travel" title="Adventure travel" target="_blank">adventure tourism</a><sup id="cite_ref-FOOTNOTEBain200669_364-0"><a href="#cite_note-FOOTNOTEBain200669-364">[353]</a></sup> and strong <a href="http://fakehost/wiki/Mountaineering" title="Mountaineering" target="_blank">mountaineering</a> tradition, as seen in the success of notable New Zealander <a href="http://fakehost/wiki/Edmund_Hillary" title="Edmund Hillary" target="_blank">Sir Edmund Hillary</a>.<sup id="cite_ref-365"><a href="#cite_note-365">[354]</a></sup><sup id="cite_ref-366"><a href="#cite_note-366">[355]</a></sup> Other outdoor pursuits such as <a href="http://fakehost/wiki/Cycling_in_New_Zealand" title="Cycling in New Zealand" target="_blank">cycling</a>, fishing, swimming, running, <a href="http://fakehost/wiki/Tramping_in_New_Zealand" title="Tramping in New Zealand" target="_blank">tramping</a>, canoeing, hunting, snowsports, surfing and sailing are also popular.<sup id="cite_ref-SportsParticipation_367-0"><a href="#cite_note-SportsParticipation-367">[356]</a></sup> The Polynesian sport of <a href="http://fakehost/wiki/Waka_ama" title="Waka ama" target="_blank">waka ama</a> racing has experienced a resurgence of interest in New Zealand since the 1980s.<sup id="cite_ref-368"><a href="#cite_note-368">[357]</a></sup>
|
||||
|
@ -1559,7 +1559,7 @@
|
|||
</h3>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/wiki/File:Hangi_ingredients.jpg" target="_blank"><img alt="Raw meat and vegetables" src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/220px-Hangi_ingredients.jpg" decoding="async" width="220" height="123" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/330px-Hangi_ingredients.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/440px-Hangi_ingredients.jpg 2x" data-file-width="3264" data-file-height="1832"/></a></p><div>
|
||||
<p><a href="http://fakehost/wiki/File:Hangi_ingredients.jpg" target="_blank"><img alt="Raw meat and vegetables" src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/220px-Hangi_ingredients.jpg" width="220" height="123" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/330px-Hangi_ingredients.jpg 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Hangi_ingredients.jpg/440px-Hangi_ingredients.jpg 2x" data-file-width="3264" data-file-height="1832"/></a></p><div>
|
||||
<p>Ingredients to be prepared for a <a href="http://fakehost/wiki/H%C4%81ngi" title="Hāngi" target="_blank">hāngi</a>
|
||||
</p></div>
|
||||
</div>
|
||||
|
@ -3202,7 +3202,7 @@
|
|||
<a rel="nofollow" href="http://www.ifs.du.edu/ifs/frm_CountryProfile.aspx?Country=NZ" target="_blank">Key Development Forecasts for New Zealand</a> from <a href="http://fakehost/wiki/International_Futures" title="International Futures" target="_blank">International Futures</a>
|
||||
</li>
|
||||
<li>
|
||||
<img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/16px-Gnome-globe.svg.png" decoding="async" width="16" height="16" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/24px-Gnome-globe.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/32px-Gnome-globe.svg.png 2x" data-file-width="48" data-file-height="48"/> <a href="https://commons.wikimedia.org/wiki/Atlas_of_New_Zealand" title="commons:Atlas of New Zealand" target="_blank">Wikimedia Atlas of New Zealand</a>
|
||||
<img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/16px-Gnome-globe.svg.png" width="16" height="16" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/24px-Gnome-globe.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Gnome-globe.svg/32px-Gnome-globe.svg.png 2x" data-file-width="48" data-file-height="48"/> <a href="https://commons.wikimedia.org/wiki/Atlas_of_New_Zealand" title="commons:Atlas of New Zealand" target="_blank">Wikimedia Atlas of New Zealand</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p><a href="http://fakehost/wiki/File:Wiki_letter_w_cropped.svg" target="_blank"><img alt="[icon]" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/44px-Wiki_letter_w_cropped.svg.png" decoding="async" width="44" height="31" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/66px-Wiki_letter_w_cropped.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/88px-Wiki_letter_w_cropped.svg.png 2x" data-file-width="44" data-file-height="31"/></a>
|
||||
<p><a href="http://fakehost/wiki/File:Wiki_letter_w_cropped.svg" target="_blank"><img alt="[icon]" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/44px-Wiki_letter_w_cropped.svg.png" width="44" height="31" srcset="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/66px-Wiki_letter_w_cropped.svg.png 1.5x, http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Wiki_letter_w_cropped.svg/88px-Wiki_letter_w_cropped.svg.png 2x" data-file-width="44" data-file-height="31"/></a>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -11,28 +11,28 @@
|
|||
<p data-type="text" data-reactid="419">Virtual reality has officially reached the consoles. And it’s pretty good! <a href="http://finance.yahoo.com/news/review-playstation-vr-is-comfortable-and-affordable-but-lacks-must-have-games-165053851.html" target="_blank">Sony’s PlayStation VR</a> is extremely comfortable and reasonably priced, and while it’s lacking killer apps, it’s loaded with lots of interesting ones.</p>
|
||||
<p data-type="text" data-reactid="420">But which ones should you buy? I’ve played just about every launch game, and while some are worth your time, others you might want to skip. To help you decide what’s what, I’ve put together this list of the eight PSVR games worth considering.</p>
|
||||
<h3 data-type="text" data-reactid="421"><a href="https://www.playstation.com/en-us/games/rez-infinite-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Rez Infinite” ($30)</a></h3>
|
||||
|
||||
<div data-reactid="422"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/YlDxEOwj5j8" data-reactid="423" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="424">Beloved cult hit “Rez” gets the VR treatment to help launch the PSVR, and the results are terrific. It includes a fully remastered take on the original “Rez” – you zoom through a Matrix-like computer system, shooting down enemies to the steady beat of thumping electronica – but the VR setting makes it incredibly immersive. It gets better the more you play it, too; unlock the amazing Area X mode and you’ll find yourself flying, shooting and bobbing your head to some of the trippiest visuals yet seen in VR.</p>
|
||||
<h3 data-type="text" data-reactid="425"><a href="https://www.playstation.com/en-us/games/thumper-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Thumper” ($20)</a></h3>
|
||||
|
||||
<div data-reactid="426"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/gtPGX8i1Eaw" data-reactid="427" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="428">What would happen if Tron, the board game Simon, a Clown beetle, Cthulhu and a noise band met in VR? Chaos, for sure, and also “Thumper.” Called a “violent rhythm game” by its creators, “Thumper” is, well, a violent rhythm game that’s also a gorgeous, unsettling and totally captivating assault on the senses. With simple controls and a straightforward premise – click the X button and the analog stick in time with the music as you barrel down a neon highway — it’s one of the rare games that works equally well both in and out of VR. But since you have PSVR, play it there. It’s marvelous.</p>
|
||||
<h3 data-type="text" data-reactid="429"><a href="https://www.playstation.com/en-us/games/until-dawn-rush-of-blood-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Until Dawn: Rush of Blood” ($20)</a></h3>
|
||||
|
||||
<div data-reactid="430"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/EL3svUfC8Ds" data-reactid="431" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="432">Cheeky horror game “Until Dawn” was a breakout hit for the PS4 last year, channeling the classic “dumb teens in the woods” horror trope into an effective interactive drama. Well, forget all that if you fire up “Rush of Blood,” because this one sticks you front and center on a rollercoaster ride from Hell. Literally. You ride through a dimly-lit carnival of terror, dual-wielding pistols as you take down targets, hideous pig monsters and, naturally, maniac clowns. Be warned: If the bad guys don’t get you, the jump scares will.</p>
|
||||
<h3 data-type="text" data-reactid="433"><a href="https://www.playstation.com/en-us/games/headmaster-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Headmaster” ($20)</a></h3>
|
||||
|
||||
<div data-reactid="434"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/a7CSMKw1E7g" data-reactid="435" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="436">Soccer meets “Portal” in the weird (and weirdly fun) “Headmaster,” a game about heading soccer balls into nets, targets and a variety of other things while stuck in some diabolical training facility. While at first it seems a little basic, increasingly challenging shots and a consistently entertaining narrative keep it from running off the pitch. Funny, ridiculous and as easy as literally moving your head back and forth, it’s a pleasant PSVR surprise.</p>
|
||||
<h3 data-type="text" data-reactid="437"><a href="https://www.playstation.com/en-us/games/rigs-mechanized-combat-league-ps4/" rel="nofollow noopener noreferrer" target="_blank">“RIGS: Mechanized Combat League” ($50)</a></h3>
|
||||
|
||||
<div data-reactid="438"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/Rnqlf9EQ2zA" data-reactid="439" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="440">Giant mechs + sports? That’s the gist of this robotic blast-a-thon, which pits two teams of three against one another in gorgeous, explosive and downright fun VR combat. At its best, “RIGS” marries the thrill of fast-paced competitive shooters with the insanity of piloting a giant mech in VR. It can, however, be one of the barfier PSVR games. So pack your Dramamine, you’re going to have to ease yourself into this one.</p>
|
||||
<h3 data-type="text" data-reactid="441"><a href="https://www.playstation.com/en-us/games/batman-arkham-vr-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Batman Arkham VR” ($20)</a></h3>
|
||||
|
||||
<div data-reactid="442"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/eS4g0py16N8" data-reactid="443" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="444">“I’m Batman,” you will say. And you’ll actually be right this time, because you are Batman in this detective yarn, and you know this because you actually grab the famous cowl and mask, stick it on your head, and stare into the mirrored reflection of Rocksteady Games’ impressive Dark Knight character model. It lacks the action of its fellow “Arkham” games and runs disappointingly short, but it’s a high-quality experience that really shows off how powerfully immersive VR can be.</p>
|
||||
<h3 data-type="text" data-reactid="445"><a href="https://www.playstation.com/en-us/games/job-simulator-the-2050-archives-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Job Simulator” ($30)</a></h3>
|
||||
|
||||
<div data-reactid="446"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/3-iMlQIGH8Y" data-reactid="447" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="448">There are a number of good VR ports in the PSVR launch lineup, but the HTC Vive launch game “Job Simulator” might be the best. Your task? Lots of tasks, actually, from cooking food to fixing cars to working in an office, all for robots, because did I mention you were in the future? Infinitely charming and surprisingly challenging, it’s a great showpiece for VR.</p>
|
||||
<h3 data-type="text" data-reactid="449"><a href="https://www.playstation.com/en-us/games/eve-valkyrie-ps4/" rel="nofollow noopener noreferrer" target="_blank">“Eve Valkyrie” ($60)</a></h3>
|
||||
|
||||
<div data-reactid="450"><iframe data-type="videoIframe" src="https://www.youtube.com/embed/0KFHw12CTbo" data-reactid="451" width="480" height="360" aspect-ratio="auto"><empty></empty></iframe></div>
|
||||
<p data-type="text" data-reactid="452">Already a hit on the Oculus Rift, this space dogfighting game was one of the first to really show off how VR can turn a traditional game experience into something special. It’s pricey and not quite as hi-res as the Rift version, but “Eve Valkyrie” does an admirable job filling the void left since “Battlestar Galactica” ended. Too bad there aren’t any Cylons in it (or are there?)</p>
|
||||
<p data-type="text" data-reactid="453"><em><strong>More games news:</strong></em></p>
|
||||
<ul data-type="list" data-reactid="454">
|
||||
|
|
808
article_scraper/resources/tests/thumbnails/a-chacon.html
Normal file
808
article_scraper/resources/tests/thumbnails/a-chacon.html
Normal file
|
@ -0,0 +1,808 @@
|
|||
<!doctype html>
|
||||
<html lang="es">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="/assets/css/dist-style.css" rel="stylesheet" />
|
||||
<link href="/assets/css/fonts.css" rel="stylesheet" />
|
||||
|
||||
<script src="https://unpkg.com/typeit@8.8.4/dist/index.umd.js"></script>
|
||||
<!-- Begin Jekyll SEO tag v2.8.0 -->
|
||||
<title>PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only. | a-chacon</title>
|
||||
<meta name="generator" content="Jekyll v4.3.4" />
|
||||
<meta property="og:title" content="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only." />
|
||||
<meta name="author" content="Andrés" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta name="description" content="Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only." />
|
||||
<meta property="og:description" content="Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only." />
|
||||
<link rel="canonical" href="https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" />
|
||||
<meta property="og:url" content="https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" />
|
||||
<meta property="og:site_name" content="a-chacon" />
|
||||
<meta property="og:image" content="https://a-chacon.com/assets/images/rails8-poc-api-auth.webp" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content="2024-10-16T00:00:00+00:00" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="https://a-chacon.com/assets/images/rails8-poc-api-auth.webp" />
|
||||
<meta property="twitter:title" content="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only." />
|
||||
<script type="application/ld+json">
|
||||
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Andrés"},"dateModified":"2024-10-16T00:00:00+00:00","datePublished":"2024-10-16T00:00:00+00:00","description":"Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only.","headline":"PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.","image":"https://a-chacon.com/assets/images/rails8-poc-api-auth.webp","mainEntityOfPage":{"@type":"WebPage","@id":"https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://a-chacon.com/assets/images/keyboard-key-a.png"},"name":"Andrés"},"url":"https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"}</script>
|
||||
<!-- End Jekyll SEO tag -->
|
||||
<link type="application/atom+xml" rel="alternate" href="https://a-chacon.com/feed.xml" title="a-chacon" />
|
||||
|
||||
<script data-host="https://app.microanalytics.io" data-dnt="false" src="https://app.microanalytics.io/js/script.js"
|
||||
id="ZwSg9rf6GA" async defer></script>
|
||||
|
||||
<style>
|
||||
.mini-banner {
|
||||
background-color: #6eea8e;
|
||||
/* Light red background color */
|
||||
color: #1c2a18;
|
||||
/* Dark red text color */
|
||||
padding: 10px 20px;
|
||||
/* Padding around the text */
|
||||
text-align: center;
|
||||
/* Center the text */
|
||||
position: fixed;
|
||||
/* Fix the banner to the top of the page */
|
||||
bottom: 0;
|
||||
/* Position at the very top */
|
||||
left: 0;
|
||||
/* Full width */
|
||||
right: 0;
|
||||
/* Full width */
|
||||
z-index: 1000;
|
||||
/* Ensure it's above other elements */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
/* Slight shadow for depth */
|
||||
}
|
||||
|
||||
.mini-banner p {
|
||||
margin: 0;
|
||||
/* Remove default paragraph margin */
|
||||
font-size: 16px;
|
||||
/* Font size */
|
||||
font-weight: bold;
|
||||
/* Bold text */
|
||||
}
|
||||
|
||||
body {
|
||||
margin-top: 60px;
|
||||
/* Adjust based on the banner height */
|
||||
}
|
||||
</style>
|
||||
<div class="mini-banner">
|
||||
<p>Building an API with Rails? Discover
|
||||
<a href="https://github.com/a-chacon/oas_rails" style="color: #826cf6; text-decoration: underline;">
|
||||
OasRails</a>, a Rails engine for generate automatic interactive documentation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="bg-white text-gray-900 dark:bg-gray-700 dark:text-slate-100">
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
new TypeIt("h1", {}).go();
|
||||
});
|
||||
</script>
|
||||
<nav class="absolute top-0 left-0 right-0 flex w-full flex-wrap items-center justify-between py-4">
|
||||
<div class="flex w-full flex-wrap items-center justify-between px-5">
|
||||
<a class="flex" href="/" aria-label="Andres Chacon - Developer">
|
||||
<img src="/assets/images/keyboard-key-a.png" alt="webpage logo" class="block h-8 w-auto">
|
||||
<p class="pl-4 hidden md:block text-lg font-bold">a-chacon <span
|
||||
class="text-mulish text-sm font-normal">~/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html</span>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<div class="flex divide-x">
|
||||
|
||||
|
||||
|
||||
|
||||
<div><a class="px-4 hover:text-sky-400 "
|
||||
href="/blog.html">Blog</a></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div><a class="px-4 hover:text-sky-400 "
|
||||
href="/projects">Proyectos</a></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="language-switcher relative">
|
||||
<button class="current-language px-4 hover:text-sky-400">
|
||||
ES
|
||||
</button>
|
||||
|
||||
<div class="dropdown-content absolute hidden mt-2 py-2 bg-white rounded shadow-lg z-20">
|
||||
|
||||
|
||||
<a class="p-4 hover:text-sky-400" href="/en/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html">EN</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const currentLangButton = document.querySelector('.current-language');
|
||||
const dropdownContent = document.querySelector('.dropdown-content');
|
||||
|
||||
if (currentLangButton && dropdownContent) {
|
||||
currentLangButton.addEventListener('click', function () {
|
||||
dropdownContent.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
if (!currentLangButton.contains(event.target) && !dropdownContent.contains(event.target)) {
|
||||
dropdownContent.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</nav>
|
||||
<link rel="stylesheet" href="/assets/css/monokai.css">
|
||||
<div class="container mx-auto">
|
||||
<div id="post" class="prose max-w-[75ch] prose-neutral mx-auto pb-10 pt-20 lg:pt-[90px] lg:pb-20">
|
||||
<div class="pb-4">
|
||||
<a href="https://a-chacon.com/category/on-rails"
|
||||
class="no-underline font-mulish text-sm hover:text-sky-400 text-gray-500">
|
||||
ON RAILS
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h1 class="text-left text-2xl font-bold md:text-5xl text-black">PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.</h1>
|
||||
|
||||
<div class="flex flex-col md:flex-row text-sm font-mulish justify-between items-center">
|
||||
<div class="flex">
|
||||
<p>Andrés</p>
|
||||
<p class="px-2">•</p>
|
||||
<p>16 October 2024</p>
|
||||
<p class="px-2">•</p>
|
||||
<p>
|
||||
|
||||
6 mins </p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="sharing-buttons flex flex-wrap gap-1 justify-center ">
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://facebook.com/sharer/sharer.php?u=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
|
||||
aria-label="Share on Facebook">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Facebook</title>
|
||||
<path
|
||||
d="M379 22v75h-44c-36 0-42 17-42 41v54h84l-12 85h-72v217h-88V277h-72v-85h72v-62c0-72 45-112 109-112 31 0 58 3 65 4z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://twitter.com/intent/tweet?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&text=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Twitter">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Twitter</title>
|
||||
<path
|
||||
d="m459 152 1 13c0 139-106 299-299 299-59 0-115-17-161-47a217 217 0 0 0 156-44c-47-1-85-31-98-72l19 1c10 0 19-1 28-3-48-10-84-52-84-103v-2c14 8 30 13 47 14A105 105 0 0 1 36 67c51 64 129 106 216 110-2-8-2-16-2-24a105 105 0 0 1 181-72c24-4 47-13 67-25-8 24-25 45-46 58 21-3 41-8 60-17-14 21-32 40-53 55z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://www.linkedin.com/shareArticle?mini=true&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&summary=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&source=https://a-chacon.com"
|
||||
aria-label="Share on Linkedin">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Linkedin</title>
|
||||
<path
|
||||
d="M136 183v283H42V183h94zm6-88c1 27-20 49-53 49-32 0-52-22-52-49 0-28 21-49 53-49s52 21 52 49zm333 208v163h-94V314c0-38-13-64-47-64-26 0-42 18-49 35-2 6-3 14-3 23v158h-94V183h94v41c12-20 34-48 85-48 62 0 108 41 108 127z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://pinterest.com/pin/create/button/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&media=https://a-chacon.com&description=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Pinterest" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Pinterest</title>
|
||||
<path
|
||||
d="M268 6C165 6 64 75 64 186c0 70 40 110 64 110 9 0 15-28 15-35 0-10-24-30-24-68 0-81 62-138 141-138 68 0 118 39 118 110 0 53-21 153-90 153-25 0-46-18-46-44 0-38 26-74 26-113 0-67-94-55-94 25 0 17 2 36 10 51-14 60-42 148-42 209 0 19 3 38 4 57 4 3 2 3 7 1 51-69 49-82 72-173 12 24 44 36 69 36 106 0 154-103 154-196C448 71 362 6 268 6z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://reddit.com/submit/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&resubmit=true&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Reddit" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Reddit</title>
|
||||
<path
|
||||
d="M440 204c-15 0-28 6-38 15-35-24-83-40-137-42l28-125 88 20c0 22 18 39 39 39 22 0 40-18 40-39s-17-40-40-40c-15 0-28 9-35 22l-97-22c-5-1-10 3-11 7l-31 138c-53 2-100 18-136 43a53 53 0 0 0-38-16c-56 0-74 74-23 100l-3 24c0 84 95 152 210 152 117 0 211-68 211-152 0-8-1-17-3-25 50-25 32-99-24-99zM129 309a40 40 0 1 1 80 0 40 40 0 0 1-80 0zm215 93c-37 37-139 37-176 0-4-3-4-9 0-13s10-4 13 0c28 28 120 29 149 0 4-4 10-4 14 0s4 10 0 13zm-1-54c-22 0-39-17-39-39a39 39 0 1 1 39 39z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://wa.me/?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.%20https://a-chacon.com"
|
||||
aria-label="Share on Whatsapp" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Whatsapp</title>
|
||||
<path
|
||||
d="M413 97A222 222 0 0 0 64 365L31 480l118-31a224 224 0 0 0 330-195c0-59-25-115-67-157zM256 439c-33 0-66-9-94-26l-7-4-70 18 19-68-4-7a185 185 0 0 1 287-229c34 36 56 82 55 131 1 102-84 185-186 185zm101-138c-5-3-33-17-38-18-5-2-9-3-12 2l-18 22c-3 4-6 4-12 2-32-17-54-30-75-66-6-10 5-10 16-31 2-4 1-7-1-10l-17-41c-4-10-9-9-12-9h-11c-4 0-9 1-15 7-5 5-19 19-19 46s20 54 23 57c2 4 39 60 94 84 36 15 49 17 67 14 11-2 33-14 37-27s5-24 4-26c-2-2-5-4-11-6z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://telegram.me/share/url?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
|
||||
aria-label="Share on Telegram" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Telegram</title>
|
||||
<path
|
||||
d="M256 8a248 248 0 1 0 0 496 248 248 0 0 0 0-496zm115 169c-4 39-20 134-28 178-4 19-10 25-17 25-14 2-25-9-39-18l-56-37c-24-17-8-25 6-40 3-4 67-61 68-67l-1-4-5-1q-4 1-105 70-15 10-27 9c-9 0-26-5-38-9-16-5-28-7-27-16q1-7 18-14l145-62c69-29 83-34 92-34 2 0 7 1 10 3l4 7a43 43 0 0 1 0 10z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700" target="_blank" rel="noopener" href="/cdn-cgi/l/email-protection#68571b1d0a020d0b1c5538072b524d5a583d1b09060c074d5a580d044d5a582f0d060d1a090c071a4d5a580c0d4d5a58291d1c0d061c010b090b014d2b5b4d2a5b064d5a580c0d4d5a583a0901041b4d5a58504d5a58402a0d1c09414d5a582d064d5a5825070c074d5a582938214527060411464e0a070c1155001c1c181b52474709450b00090b0706460b07054707064d5a581a0901041b475a585a5c47595847595e4718070b451d1b01060f451a0901041b455045091d1c00451b111b1c0d0545010645091801450706041146001c0504" aria-label="Share by Email" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Email</title>
|
||||
<path
|
||||
d="M464 64a48 48 0 0 1 29 86L275 314c-11 8-27 8-38 0L19 150a48 48 0 0 1 29-86h416zM218 339c22 17 54 17 76 0l218-163v208c0 35-29 64-64 64H64c-35 0-64-29-64-64V176l218 163z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img class="w-full" src="/assets/images/rails8-poc-api-auth.webp" alt="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.">
|
||||
|
||||
<div class="my-6">
|
||||
<p>Como ya saben, una de las funcionalidades nuevas de Rails 8 es el <strong>nuevo generador básico de autenticación</strong> que viene a demostrar que no es tan complejo desarrollar todo lo que respecta a autenticación en una aplicación con Rails y que muchas veces no es necesario depender de terceros (gemas). La discusión comenzó <a href="https://github.com/rails/rails/issues/50446">aquí</a>.</p>
|
||||
|
||||
<p>Dicho esto, veamos que pasa usando el generador en una aplicación API-Only:</p>
|
||||
|
||||
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails <span class="nt">-v</span>
|
||||
Rails 8.0.0.beta1
|
||||
</code></pre></div></div>
|
||||
|
||||
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails new app <span class="nt">--api</span> & <span class="nb">cd </span>app
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Y ejecutamos el nuevo comando:</p>
|
||||
|
||||
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails g authentication
|
||||
create app/models/session.rb
|
||||
create app/models/user.rb
|
||||
create app/models/current.rb
|
||||
create app/controllers/sessions_controller.rb
|
||||
create app/controllers/concerns/authentication.rb
|
||||
create app/controllers/passwords_controller.rb
|
||||
create app/mailers/passwords_mailer.rb
|
||||
create app/views/passwords_mailer/reset.html.erb
|
||||
create app/views/passwords_mailer/reset.text.erb
|
||||
create <span class="nb">test</span>/mailers/previews/passwords_mailer_preview.rb
|
||||
gsub app/controllers/application_controller.rb
|
||||
route resources :passwords, param: :token
|
||||
route resource :session
|
||||
gsub Gemfile
|
||||
bundle <span class="nb">install</span> <span class="nt">--quiet</span>
|
||||
generate migration CreateUsers email_address:string!:uniq password_digest:string! <span class="nt">--force</span>
|
||||
rails generate migration CreateUsers email_address:string!:uniq password_digest:string! <span class="nt">--force</span>
|
||||
invoke active_record
|
||||
create db/migrate/20241016002139_create_users.rb
|
||||
generate migration CreateSessions user:references ip_address:string user_agent:string <span class="nt">--force</span>
|
||||
rails generate migration CreateSessions user:references ip_address:string user_agent:string <span class="nt">--force</span>
|
||||
invoke active_record
|
||||
create db/migrate/20241016002140_create_sessions.rb
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Ok, ahora por ejemplo, si revisamos <code class="language-plaintext highlighter-rouge">SessionsController</code> veremos que el método de <code class="language-plaintext highlighter-rouge">Login</code> se ve de la siguiente forma:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">def</span> <span class="nf">create</span>
|
||||
<span class="k">if</span> <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">authenticate_by</span><span class="p">(</span><span class="n">params</span><span class="p">.</span><span class="nf">permit</span><span class="p">(</span><span class="ss">:email_address</span><span class="p">,</span> <span class="ss">:password</span><span class="p">))</span>
|
||||
<span class="n">start_new_session_for</span> <span class="n">user</span>
|
||||
<span class="n">redirect_to</span> <span class="n">after_authentication_url</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">redirect_to</span> <span class="n">new_session_url</span><span class="p">,</span> <span class="ss">alert: </span><span class="s2">"Try another email address or password."</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>O sea, redirecciona a rutas y/o vistas que en nuestra API no existen ni hacen sentido, y además si inspeccionamos el metodo <code class="language-plaintext highlighter-rouge">start_new_session_for</code> nos daremos cuenta de que el sistema está basado 100% en <strong>autenticación mediante cookies</strong>. Entonces, ¿qué hacemos?</p>
|
||||
|
||||
<p>Mi propuesta es la siguiente: el generador crea las bases para la autenticación y creo que funciona bastante bien, por lo que con unas pequeñas modificaciones podemos dejar funcionando una <strong>autenticación Bearer</strong> (Token Authentication) rápidamente en nuestra API con Rails 8 más los archivos ya generados.</p>
|
||||
|
||||
<p>El primer paso será agregar <strong>persistencia para nuestro token</strong>, para esto modificaremos la migración que crea las sessiones y agregaremos un nuevo campo llamado <code class="language-plaintext highlighter-rouge">token</code>:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">create_table</span> <span class="ss">:sessions</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
|
||||
<span class="n">t</span><span class="p">.</span><span class="nf">references</span> <span class="ss">:user</span><span class="p">,</span> <span class="ss">null: </span><span class="kp">false</span><span class="p">,</span> <span class="ss">foreign_key: </span><span class="kp">true</span>
|
||||
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:ip_address</span>
|
||||
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:user_agent</span>
|
||||
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:token</span> <span class="c1"># HERE</span>
|
||||
|
||||
<span class="n">t</span><span class="p">.</span><span class="nf">timestamps</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Ahora simplemente ejecuta <code class="language-plaintext highlighter-rouge">rails db:migrate</code> y create un usuario de prueba por consola, yo lo haré con esta línea <code class="language-plaintext highlighter-rouge">User.create(email_address: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a6d3d5c3d4e6d2c3d5d288c5c9cb">[email protected]</a>", password: "123456789")</code> (Lo utilizaremos más tarde). Luego debemos crear un nuevo token para cada sesión nueva de un usuario, para esto lo más simple es usar un callback en el modelo <code class="language-plaintext highlighter-rouge">Session</code>:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/models/sessions.rb</span>
|
||||
<span class="k">class</span> <span class="nc">Session</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
|
||||
<span class="n">belongs_to</span> <span class="ss">:user</span>
|
||||
<span class="n">before_create</span> <span class="ss">:generate_token</span> <span class="c1"># Here call</span>
|
||||
|
||||
<span class="kp">private</span>
|
||||
<span class="k">def</span> <span class="nf">generate_token</span> <span class="c1"># Here implement, generate the token as you wish.</span>
|
||||
<span class="nb">self</span><span class="p">.</span><span class="nf">token</span> <span class="o">=</span> <span class="no">Digest</span><span class="o">::</span><span class="no">SHA1</span><span class="p">.</span><span class="nf">hexdigest</span><span class="p">([</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">,</span> <span class="nb">rand</span> <span class="p">].</span><span class="nf">join</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Ahora volviendo al metodo <code class="language-plaintext highlighter-rouge">start_new_session_for</code> en el concern <code class="language-plaintext highlighter-rouge">Authentication</code>, no es necesario que creemos una cookie, asi que debemos remover esa linea y dejar el metodo de la siguiente forma:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/concerns/authentication.rb</span>
|
||||
<span class="k">def</span> <span class="nf">start_new_session_for</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
|
||||
<span class="n">user</span><span class="p">.</span><span class="nf">sessions</span><span class="p">.</span><span class="nf">create!</span><span class="p">(</span><span class="ss">user_agent: </span><span class="n">request</span><span class="p">.</span><span class="nf">user_agent</span><span class="p">,</span> <span class="ss">ip_address: </span><span class="n">request</span><span class="p">.</span><span class="nf">remote_ip</span><span class="p">).</span><span class="nf">tap</span> <span class="k">do</span> <span class="o">|</span><span class="n">session</span><span class="o">|</span>
|
||||
<span class="no">Current</span><span class="p">.</span><span class="nf">session</span> <span class="o">=</span> <span class="n">session</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Y modificaremos el <code class="language-plaintext highlighter-rouge">create</code> de <code class="language-plaintext highlighter-rouge">SessionsController</code> para que las respuestas sean en formato json y no redirecciones:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/sessions_controller.rb</span>
|
||||
<span class="k">def</span> <span class="nf">create</span>
|
||||
<span class="k">if</span> <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">authenticate_by</span><span class="p">(</span><span class="n">params</span><span class="p">.</span><span class="nf">permit</span><span class="p">(</span><span class="ss">:email_address</span><span class="p">,</span> <span class="ss">:password</span><span class="p">))</span>
|
||||
<span class="n">start_new_session_for</span> <span class="n">user</span>
|
||||
<span class="n">render</span> <span class="ss">json: </span><span class="p">{</span> <span class="ss">data: </span><span class="p">{</span> <span class="ss">token: </span><span class="no">Current</span><span class="p">.</span><span class="nf">session</span><span class="p">.</span><span class="nf">token</span> <span class="p">}</span> <span class="p">}</span>
|
||||
<span class="k">else</span>
|
||||
<span class="n">render</span> <span class="ss">json: </span><span class="p">{},</span> <span class="ss">status: :unauthorized</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p><strong>Para hacer que todo esto funcione debemos hacer dos cosas:</strong></p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<p>Incluir el modulo <code class="language-plaintext highlighter-rouge">Authentication</code> en <code class="language-plaintext highlighter-rouge">ApplicationController</code>:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/application_controller.rb</span>
|
||||
<span class="k">class</span> <span class="nc">ApplicationController</span> <span class="o"><</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">API</span>
|
||||
<span class="kp">include</span> <span class="no">Authentication</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div> </div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Eliminar la linea numero 6 de este mismo concern:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/concerns/authentication.rb</span>
|
||||
<span class="n">included</span> <span class="k">do</span>
|
||||
<span class="n">before_action</span> <span class="ss">:require_authentication</span>
|
||||
<span class="n">helper_method</span> <span class="ss">:authenticated?</span> <span class="c1"># This, we don't use helpers in APIs</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div> </div>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>Hasta este punto ya deberíamos tener el <strong>login funcionando</strong>. Para probar esto voy a agregar <a href="https://github.com/a-chacon/oas_rails">OasRails</a>, que a propósito <strong>ya está funcionando con Rails 8</strong> y voy a enviar un par de peticiones a ver como se comporta, no explicaré como implementar OasRails, para eso puedes ver el repositorio o leer más en <a href="/on rails/2024/07/25/documenting-rails-apis">este post</a>.</p>
|
||||
|
||||
<p>Inicio de sesión exitoso:</p>
|
||||
|
||||
<p><img src="/assets/images/rails8_success_login.png" alt="" /></p>
|
||||
|
||||
<p>Inicio de sesión fallido:</p>
|
||||
|
||||
<p><img src="/assets/images/rails8_fail_login.png" alt="" /></p>
|
||||
|
||||
<hr />
|
||||
|
||||
<p>Ya podemos generar tokens, ahora modificaremos el código para <strong>autenticarnos con ese mismo token</strong>. Para eso, cambiaremos la lógica de buscar la sesión actual del usuario con base en la cookie a buscarla basándonos en la cabecera <code class="language-plaintext highlighter-rouge">Authorization</code>:</p>
|
||||
|
||||
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
|
||||
<span class="c1"># app/controllers/concerns/authentication.rb</span>
|
||||
<span class="k">def</span> <span class="nf">resume_session</span>
|
||||
<span class="no">Current</span><span class="p">.</span><span class="nf">session</span> <span class="o">=</span> <span class="n">find_session_by_token</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">find_session_by_cookie</span>
|
||||
<span class="no">Session</span><span class="p">.</span><span class="nf">find_by</span><span class="p">(</span><span class="ss">token: </span><span class="n">request</span><span class="p">.</span><span class="nf">headers</span><span class="p">[</span><span class="ss">:authorization</span><span class="p">]</span><span class="o">&</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="k">end</span>
|
||||
</code></pre></div></div>
|
||||
|
||||
<p>Para probar esto creo que tendremos que hacer rápidamente un modelo que dependa de <code class="language-plaintext highlighter-rouge">User</code> y que requiera autenticación para utilizar. Intentemos con <code class="language-plaintext highlighter-rouge">rails g scaffold project title:string description:text user:references</code> y le agregamos al principio del controlador la línea de código <code class="language-plaintext highlighter-rouge">before_action :require_authentication</code>.</p>
|
||||
|
||||
<p>Aquí les dejo una pequeña prueba del index de Projects autenticado con el token que obtuve en las pruebas anteriores:</p>
|
||||
|
||||
<p><img src="/assets/images/rails8_projects.png" alt="" /></p>
|
||||
|
||||
<hr />
|
||||
|
||||
<p>Con esto ya tienes gran parte de la lógica de autenticación funcionando en la aplicación API-Only. Te queda continuar con las modificaciones en el resto de los endpoints para que las respuestas sean en formato json y no supuestas vistas que no existen en la aplicación.</p>
|
||||
|
||||
<p>Probablemente de aquí a que se lance la versión final de Rails 8 aparezca un <strong>PR solucionando esto y el generador funcione correctamente en modo API-Only</strong>. Hasta entonces, con estas pequeñas modificaciones ya puedes seguir construyendo tu API.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mx-auto py-8">
|
||||
<p class="text-center font-extrabold italic">
|
||||
¿Te gustó? ¡Compártelo!
|
||||
</p>
|
||||
<div class="sharing-buttons flex flex-wrap gap-1 justify-center ">
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://facebook.com/sharer/sharer.php?u=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
|
||||
aria-label="Share on Facebook">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Facebook</title>
|
||||
<path
|
||||
d="M379 22v75h-44c-36 0-42 17-42 41v54h84l-12 85h-72v217h-88V277h-72v-85h72v-62c0-72 45-112 109-112 31 0 58 3 65 4z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://twitter.com/intent/tweet?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&text=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Twitter">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Twitter</title>
|
||||
<path
|
||||
d="m459 152 1 13c0 139-106 299-299 299-59 0-115-17-161-47a217 217 0 0 0 156-44c-47-1-85-31-98-72l19 1c10 0 19-1 28-3-48-10-84-52-84-103v-2c14 8 30 13 47 14A105 105 0 0 1 36 67c51 64 129 106 216 110-2-8-2-16-2-24a105 105 0 0 1 181-72c24-4 47-13 67-25-8 24-25 45-46 58 21-3 41-8 60-17-14 21-32 40-53 55z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://www.linkedin.com/shareArticle?mini=true&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&summary=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&source=https://a-chacon.com"
|
||||
aria-label="Share on Linkedin">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Linkedin</title>
|
||||
<path
|
||||
d="M136 183v283H42V183h94zm6-88c1 27-20 49-53 49-32 0-52-22-52-49 0-28 21-49 53-49s52 21 52 49zm333 208v163h-94V314c0-38-13-64-47-64-26 0-42 18-49 35-2 6-3 14-3 23v158h-94V183h94v41c12-20 34-48 85-48 62 0 108 41 108 127z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://pinterest.com/pin/create/button/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&media=https://a-chacon.com&description=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Pinterest" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Pinterest</title>
|
||||
<path
|
||||
d="M268 6C165 6 64 75 64 186c0 70 40 110 64 110 9 0 15-28 15-35 0-10-24-30-24-68 0-81 62-138 141-138 68 0 118 39 118 110 0 53-21 153-90 153-25 0-46-18-46-44 0-38 26-74 26-113 0-67-94-55-94 25 0 17 2 36 10 51-14 60-42 148-42 209 0 19 3 38 4 57 4 3 2 3 7 1 51-69 49-82 72-173 12 24 44 36 69 36 106 0 154-103 154-196C448 71 362 6 268 6z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://reddit.com/submit/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&resubmit=true&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
|
||||
aria-label="Share on Reddit" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Reddit</title>
|
||||
<path
|
||||
d="M440 204c-15 0-28 6-38 15-35-24-83-40-137-42l28-125 88 20c0 22 18 39 39 39 22 0 40-18 40-39s-17-40-40-40c-15 0-28 9-35 22l-97-22c-5-1-10 3-11 7l-31 138c-53 2-100 18-136 43a53 53 0 0 0-38-16c-56 0-74 74-23 100l-3 24c0 84 95 152 210 152 117 0 211-68 211-152 0-8-1-17-3-25 50-25 32-99-24-99zM129 309a40 40 0 1 1 80 0 40 40 0 0 1-80 0zm215 93c-37 37-139 37-176 0-4-3-4-9 0-13s10-4 13 0c28 28 120 29 149 0 4-4 10-4 14 0s4 10 0 13zm-1-54c-22 0-39-17-39-39a39 39 0 1 1 39 39z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://wa.me/?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.%20https://a-chacon.com"
|
||||
aria-label="Share on Whatsapp" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Whatsapp</title>
|
||||
<path
|
||||
d="M413 97A222 222 0 0 0 64 365L31 480l118-31a224 224 0 0 0 330-195c0-59-25-115-67-157zM256 439c-33 0-66-9-94-26l-7-4-70 18 19-68-4-7a185 185 0 0 1 287-229c34 36 56 82 55 131 1 102-84 185-186 185zm101-138c-5-3-33-17-38-18-5-2-9-3-12 2l-18 22c-3 4-6 4-12 2-32-17-54-30-75-66-6-10 5-10 16-31 2-4 1-7-1-10l-17-41c-4-10-9-9-12-9h-11c-4 0-9 1-15 7-5 5-19 19-19 46s20 54 23 57c2 4 39 60 94 84 36 15 49 17 67 14 11-2 33-14 37-27s5-24 4-26c-2-2-5-4-11-6z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://telegram.me/share/url?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
|
||||
aria-label="Share on Telegram" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Telegram</title>
|
||||
<path
|
||||
d="M256 8a248 248 0 1 0 0 496 248 248 0 0 0 0-496zm115 169c-4 39-20 134-28 178-4 19-10 25-17 25-14 2-25-9-39-18l-56-37c-24-17-8-25 6-40 3-4 67-61 68-67l-1-4-5-1q-4 1-105 70-15 10-27 9c-9 0-26-5-38-9-16-5-28-7-27-16q1-7 18-14l145-62c69-29 83-34 92-34 2 0 7 1 10 3l4 7a43 43 0 0 1 0 10z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700" target="_blank" rel="noopener" href="/cdn-cgi/l/email-protection#79460a0c1b131c1a0d4429163a435c4b492c0a18171d165c4b491c155c4b493e1c171c0b181d160b5c4b491d1c5c4b49380c0d1c170d101a181a105c3a4a5c3b4a175c4b491d1c5c4b492b1810150a5c4b49415c4b49513b1c0d18505c4b493c175c4b4934161d165c4b493829305436171500575f1b161d0044110d0d090a43565618541a11181a1617571a16145616175c4b490b1810150a564b494b4d56484956484f5609161a540c0a10171e540b1810150a544154180c0d11540a000a0d1c1454101754180910541617150057110d1415" aria-label="Share by Email" draggable="false">
|
||||
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
|
||||
class="w-5 h-5">
|
||||
<title>Email</title>
|
||||
<path
|
||||
d="M464 64a48 48 0 0 1 29 86L275 314c-11 8-27 8-38 0L19 150a48 48 0 0 1 29-86h416zM218 339c22 17 54 17 76 0l218-163v208c0 35-29 64-64 64H64c-35 0-64-29-64-64V176l218 163z">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="font-mulish flex justify-center mb-10">
|
||||
|
||||
<a class="pr-2" href="/docker/2024/09/16/run-llm-locally.html">« LLM en local: Corriendo Ollama y Open WebUI con Docker Compose.</a>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- <div class="mx-auto py-8"> -->
|
||||
<!-- <script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" -->
|
||||
<!-- data-slug="achacon" data-color="#FFDD00" data-emoji="" data-font="Lato" data-text="Buy me a coffee" -->
|
||||
<!-- data-outline-color="#000000" data-font-color="#000000" data-coffee-color="#ffffff"></script> -->
|
||||
<!-- </div> -->
|
||||
<!---->
|
||||
<!-- <div class="my-6"> -->
|
||||
<!-- ¡Hola a todos! 👋 ¿Disfrutaron leyendo el artículo? ¡Me encantaría conocer sus opiniones! 💬 No duden en dejar un -->
|
||||
<!-- comentario abajo, ya sea para compartir sus comentarios, preguntas o simplemente saludar. ¡No es necesario -->
|
||||
<!-- registrarse, solo compartan algo valioso! 😊 -->
|
||||
<!-- </div> -->
|
||||
<!-- <div class="my-6"> -->
|
||||
<!-- Hey there! 👋 Enjoyed reading the post? I'd love to hear your thoughts! 💬 Feel free to drop a comment -->
|
||||
<!-- below—whether it's feedback, questions, or just saying hi. No need to sign up, just share something valuable! 😊 -->
|
||||
<!-- </div> -->
|
||||
<!---->
|
||||
<!-- <div id="embedContainer" style="height: fit-content;" data-identifier="/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" -->
|
||||
<!-- data-site-key="80dce74b8e1af5839a6f"></div> -->
|
||||
<!-- <script src="https://opina.fly.dev/embed.js"></script> -->
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<footer class="w-full bottom-0">
|
||||
<hr class="my-8 border-zinc-200" />
|
||||
<div class="container mx-auto">
|
||||
<div class="flex flex-wrap text-left">
|
||||
<div class="w-full md:w-6/12 md:px-4">
|
||||
<p class="text-3xl font-semibold">
|
||||
Mantengamosnos en contacto!
|
||||
</p>
|
||||
<p class="font-mulish text-lg dark:text-zinc-300 mt-2 mb-2">
|
||||
Encuéntrame en cualquiera de estas plataformas:
|
||||
</p>
|
||||
<div class="flex justify-center md:justify-start pt-2 gap-6">
|
||||
|
||||
<a class="transition hover:scale-110 duration-300" href="/cdn-cgi/l/email-protection#b7d6d9d3c5d2c499d4dff7c7c5d8c3d8d9dad6dedb99d4d8da">
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/email.svg"
|
||||
alt="Email Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="transition hover:scale-110 duration-300"
|
||||
href="https://github.com/a-chacon"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/github-mark.svg"
|
||||
alt="Github Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="transition hover:scale-110 duration-300"
|
||||
href="https://t.me/a_chacon"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/telegram.svg"
|
||||
alt="Telegram Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="transition hover:scale-110 duration-300"
|
||||
href="https://stackoverflow.com/users/16847024/andr%c3%a9s"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/stack-overflow.svg"
|
||||
alt="StackOverflow Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="transition hover:scale-110 duration-300"
|
||||
href="https://discord.com/users/673943171369140252"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/discord.svg"
|
||||
alt="Discord Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="transition hover:scale-110 duration-300"
|
||||
rel="me"
|
||||
href="https://lile.cl/@achacon"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="h-6 w-6"
|
||||
src="/assets/images/contact_channels/mastodon.svg"
|
||||
alt="Mastodon Icon"
|
||||
/>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="w-full md:w-6/12 md:text-right py-4 md:py-0">
|
||||
<div class="flex flex-wrap items-top mb-6">
|
||||
<div class="w-full lg:w-4/12 md:px-4 ml-auto">
|
||||
<span class="text-lg block text-gray-800 mb-2">
|
||||
Páginas
|
||||
</span>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
|
||||
href="/blog.html">Blog</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
|
||||
href="/">Casa</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
|
||||
href="/projects">Proyectos</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-mulish flex flex-wrap items-center md:justify-between justify-center my-8">
|
||||
<div class="w-full md:w-4/12 px-4 mx-auto text-center">
|
||||
|
||||
<a href="/feed.xml" class="p-2">
|
||||
<svg fill="#000000" viewBox="-3 0 19 19" xmlns="http://www.w3.org/2000/svg" class="w-10 mx-auto">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<path
|
||||
d="M.926 12.818a1.403 1.403 0 1 1 0 1.984 1.402 1.402 0 0 1 0-1.984zm10.531 2.357a1.03 1.03 0 0 1-1.029-1.03 8.775 8.775 0 0 0-.694-3.438A8.826 8.826 0 0 0 1.591 5.31a1.03 1.03 0 1 1 0-2.059 10.817 10.817 0 0 1 4.24.857 10.893 10.893 0 0 1 3.463 2.334 10.867 10.867 0 0 1 3.19 7.703 1.027 1.027 0 0 1-1.027 1.029zm-4.538 0a1.03 1.03 0 0 1-1.029-1.03 4.297 4.297 0 0 0-4.299-4.298 1.03 1.03 0 0 1 0-2.059 6.362 6.362 0 0 1 5.857 3.883 6.298 6.298 0 0 1 .5 2.475 1.03 1.03 0 0 1-1.029 1.029z">
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<div class="text-sm text-blueGray-500 font-semibold py-1">
|
||||
© <span id="get-current-year">2024</span>
|
||||
<a href="https://www.creative-tim.com/product/notus-js" class="text-blueGray-500 hover:text-gray-800"
|
||||
target="_blank" aria-label="Creative C">a-chacon.</a>
|
||||
All rights reserved.
|
||||
<p class="text-xs pt-4">
|
||||
Built with ❤️ using the
|
||||
<a class="hover:text-sky-400" href="https://github.com/a-chacon/awesome-jekyll-theme">Awesome Jekyll
|
||||
Theme</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>
|
||||
document.querySelectorAll("a").forEach(function (link) {
|
||||
link.addEventListener("click", function (event) {
|
||||
event.preventDefault(); // Prevent the default link action temporarily
|
||||
link.classList.add("gentle-clicked");
|
||||
|
||||
setTimeout(function () {
|
||||
link.classList.remove("gentle-clicked");
|
||||
window.location.href = link.href; // Navigate to the link after the animation
|
||||
}, 300); // Duration of the gentle bounce animation
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'8dc35b4edefb4223',t:'MTczMDU0MjQ1Ni4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,7 @@ use std::collections::HashSet;
|
|||
use once_cell::sync::Lazy;
|
||||
use regex::{Regex, RegexBuilder};
|
||||
|
||||
pub const UNKNOWN_CONTENT_SIZE_LIMIT: usize = 5 * 1024 * 1024;
|
||||
pub const DEFAULT_CHAR_THRESHOLD: usize = 500;
|
||||
pub static IS_IMAGE: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(r#"\.(jpg|jpeg|png|webp)"#)
|
||||
|
@ -140,6 +141,14 @@ pub static DIV_TO_P_ELEMS: Lazy<HashSet<&str>> = Lazy::new(|| {
|
|||
pub static VALID_EMPTY_TAGS: Lazy<HashSet<&str>> = Lazy::new(|| {
|
||||
HashSet::from([
|
||||
"AREA", "BASE", "BR", "COL", "EMBED", "HR", "IMG", "LINK", "META", "SOURCE", "TRACK",
|
||||
"IFRAME",
|
||||
])
|
||||
});
|
||||
|
||||
pub static VALID_SELF_CLOSING_TAGS: Lazy<HashSet<&str>> = Lazy::new(|| {
|
||||
HashSet::from([
|
||||
"AREA", "BASE", "BR", "COL", "EMBED", "HR", "IMG", "INPUT", "LINK", "META", "PARAM",
|
||||
"SOURCE", "TRACK", "WBR",
|
||||
])
|
||||
});
|
||||
|
||||
|
@ -156,3 +165,71 @@ pub const PHRASING_ELEMS: &[&str] = &[
|
|||
"OUTPUT", "PROGRESS", "Q", "RUBY", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG",
|
||||
"SUB", "SUP", "TEXTAREA", "TIME", "VAR", "WBR",
|
||||
];
|
||||
|
||||
pub const LEAD_IMAGE_URL_XPATH: &str = "//link[@rel='image_src']";
|
||||
|
||||
pub const POSITIVE_LEAD_IMAGE_URL_HINTS: &[&str] =
|
||||
&["upload", "wp-content", "large", "photo", "wp-image"];
|
||||
|
||||
pub static POSITIVE_LEAD_IMAGE_URL_HINTS_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(&POSITIVE_LEAD_IMAGE_URL_HINTS.join("|"))
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.expect("POSITIVE_LEAD_IMAGE_URL_HINTS regex")
|
||||
});
|
||||
|
||||
pub const NEGATIVE_LEAD_IMAGE_URL_HINTS: &[&str] = &[
|
||||
"spacer",
|
||||
"sprite",
|
||||
"blank",
|
||||
"throbber",
|
||||
"gradient",
|
||||
"tile",
|
||||
"bg",
|
||||
"background",
|
||||
"icon",
|
||||
"social",
|
||||
"header",
|
||||
"hdr",
|
||||
"advert",
|
||||
"spinner",
|
||||
"loader",
|
||||
"loading",
|
||||
"default",
|
||||
"rating",
|
||||
"share",
|
||||
"facebook",
|
||||
"twitter",
|
||||
"theme",
|
||||
"promo",
|
||||
"ads",
|
||||
"wp-includes",
|
||||
];
|
||||
|
||||
pub static NEGATIVE_LEAD_IMAGE_URL_HINTS_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(&NEGATIVE_LEAD_IMAGE_URL_HINTS.join("|"))
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.expect("NEGATIVE_LEAD_IMAGE_URL_HINTS regex")
|
||||
});
|
||||
|
||||
pub const PHOTO_HINTS: &[&str] = &["figure", "photo", "image", "caption"];
|
||||
pub static PHOTO_HINTS_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(&PHOTO_HINTS.join("|"))
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.expect("PHOTO_HINTS_REGEX regex")
|
||||
});
|
||||
|
||||
pub static GIF_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(r#"\.gif(\?.*)?$"#)
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.expect("GIF_REGEX")
|
||||
});
|
||||
pub static JPG_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(r#"\.jpe?g(\?.*)?$"#)
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.expect("JPG_REGEX")
|
||||
});
|
||||
|
|
|
@ -6,10 +6,10 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ScraperError {
|
||||
#[error("")]
|
||||
#[error("Configerror {0}")]
|
||||
Config(#[from] ConfigError),
|
||||
#[error("")]
|
||||
#[error("ImageDownloadError {0}")]
|
||||
Image(#[from] ImageDownloadError),
|
||||
#[error("")]
|
||||
#[error("FullTextParserError {0}")]
|
||||
Scrap(#[from] FullTextParserError),
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use libxml::tree::{Document, Node, NodeType};
|
|||
use libxml::xpath::Context;
|
||||
use reqwest::header::HeaderMap;
|
||||
use reqwest::{Client, Response, Url};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::Path;
|
||||
use std::str::from_utf8;
|
||||
|
||||
|
@ -69,6 +69,11 @@ impl FullTextParser {
|
|||
|
||||
let html = Self::get_body(response).await?;
|
||||
|
||||
if html.is_empty() {
|
||||
log::error!("Empty response body");
|
||||
return Err(FullTextParserError::Http);
|
||||
}
|
||||
|
||||
// check for fingerprints
|
||||
let config = if config.is_none() {
|
||||
if let Some(url) = Fingerprints::detect(&html) {
|
||||
|
@ -122,8 +127,6 @@ impl FullTextParser {
|
|||
Node::new("article", None, &document).map_err(|()| FullTextParserError::Xml)?;
|
||||
document.set_root_element(&root);
|
||||
|
||||
Self::generate_head(&mut root, &document)?;
|
||||
|
||||
for page_html in pages {
|
||||
self.parse_page(&mut article, &page_html, &mut root, config, global_config)?;
|
||||
}
|
||||
|
@ -224,7 +227,7 @@ impl FullTextParser {
|
|||
metadata::extract(&xpath_ctx, config, Some(global_config), article);
|
||||
|
||||
if article.thumbnail_url.is_none() {
|
||||
Self::check_for_thumbnail(&xpath_ctx, article);
|
||||
article.thumbnail_url = Self::check_for_thumbnail(&xpath_ctx);
|
||||
}
|
||||
Self::prep_content(
|
||||
&xpath_ctx,
|
||||
|
@ -266,11 +269,83 @@ impl FullTextParser {
|
|||
}
|
||||
|
||||
// parse html
|
||||
let parser = Parser::default_html();
|
||||
parser.parse_string(html.as_str()).map_err(|err| {
|
||||
let document = Self::parse_html_string_patched(html.as_str()).map_err(|err| {
|
||||
log::error!("Parsing HTML failed for downloaded HTML {:?}", err);
|
||||
FullTextParserError::Xml
|
||||
})
|
||||
})?;
|
||||
|
||||
if document.get_root_element().is_none() {
|
||||
log::error!("document without root");
|
||||
Err(FullTextParserError::Xml)
|
||||
} else {
|
||||
Ok(document)
|
||||
}
|
||||
}
|
||||
|
||||
/// FIXME: Here are some patched functions of libxml crate.
|
||||
/// Started from libxml 2.11.1+, we have some encoding issue.
|
||||
/// See:
|
||||
/// - <https://github.com/KWARC/rust-libxml/issues/111>
|
||||
/// - <https://github.com/Orange-OpenSource/hurl/issues/1535>
|
||||
/// These two functions should be removed when the issue is fixed in libxml crate.
|
||||
fn try_usize_to_i32(value: usize) -> Result<i32, libxml::parser::XmlParseError> {
|
||||
if cfg!(target_pointer_width = "16") || (value < i32::MAX as usize) {
|
||||
// Cannot safely use our value comparison, but the conversion if always safe.
|
||||
// Or, if the value can be safely represented as a 32-bit signed integer.
|
||||
Ok(value as i32)
|
||||
} else {
|
||||
// Document too large, cannot parse using libxml2.
|
||||
Err(libxml::parser::XmlParseError::DocumentTooLarge)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_html_string_patched(
|
||||
input: &str,
|
||||
) -> Result<Document, libxml::parser::XmlParseError> {
|
||||
unsafe {
|
||||
// https://gitlab.gnome.org/GNOME/libxml2/-/wikis/Thread-safety
|
||||
libxml::bindings::xmlInitParser();
|
||||
}
|
||||
let parser = Parser::default_html();
|
||||
let input_bytes: &[u8] = input.as_ref();
|
||||
let input_ptr = input_bytes.as_ptr() as *const std::os::raw::c_char;
|
||||
let input_len = Self::try_usize_to_i32(input_bytes.len())?;
|
||||
let encoding = std::ffi::CString::new("utf-8").unwrap();
|
||||
let encoding_ptr = encoding.as_ptr();
|
||||
let url_ptr = std::ptr::null();
|
||||
|
||||
// HTML_PARSE_RECOVER | HTML_PARSE_NOERROR
|
||||
let options = 1 + 32;
|
||||
match parser.format {
|
||||
libxml::parser::ParseFormat::XML => unsafe {
|
||||
let doc_ptr = libxml::bindings::xmlReadMemory(
|
||||
input_ptr,
|
||||
input_len,
|
||||
url_ptr,
|
||||
encoding_ptr,
|
||||
options,
|
||||
);
|
||||
if doc_ptr.is_null() {
|
||||
Err(libxml::parser::XmlParseError::GotNullPointer)
|
||||
} else {
|
||||
Ok(Document::new_ptr(doc_ptr))
|
||||
}
|
||||
},
|
||||
libxml::parser::ParseFormat::HTML => unsafe {
|
||||
let docptr = libxml::bindings::htmlReadMemory(
|
||||
input_ptr,
|
||||
input_len,
|
||||
url_ptr,
|
||||
encoding_ptr,
|
||||
options,
|
||||
);
|
||||
if docptr.is_null() {
|
||||
Err(libxml::parser::XmlParseError::GotNullPointer)
|
||||
} else {
|
||||
Ok(Document::new_ptr(docptr))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_xpath_ctx(doc: &Document) -> Result<Context, FullTextParserError> {
|
||||
|
@ -291,63 +366,73 @@ impl FullTextParser {
|
|||
.send()
|
||||
.await
|
||||
.map_err(|err| {
|
||||
log::error!(
|
||||
"Downloading HTML failed: GET '{}' - '{}'",
|
||||
url.as_str(),
|
||||
err
|
||||
);
|
||||
log::error!("Downloading HTML failed: GET '{url}' - '{err}'");
|
||||
FullTextParserError::Http
|
||||
})?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
async fn get_body(response: Response) -> Result<String, FullTextParserError> {
|
||||
if response.status().is_success() {
|
||||
let headers = response.headers().clone();
|
||||
let bytes = response
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|_| FullTextParserError::Http)?;
|
||||
|
||||
match from_utf8(&bytes) {
|
||||
Ok(utf8_str) => {
|
||||
log::debug!("Valid utf-8 string");
|
||||
return Ok(utf8_str.into());
|
||||
}
|
||||
Err(error) => {
|
||||
log::debug!("Invalid utf-8 string");
|
||||
let lossy_string = std::string::String::from_utf8_lossy(&bytes);
|
||||
|
||||
if let Some(encoding) = Self::get_encoding_from_html(&lossy_string) {
|
||||
log::debug!("Encoding extracted from HTML: '{}'", encoding);
|
||||
if let Some(decoded_html) = Self::decode_html(&bytes, encoding) {
|
||||
let decoded_html = decoded_html.replacen(
|
||||
&format!("charset=\"{encoding}\""),
|
||||
"charset=\"utf-8\"",
|
||||
1,
|
||||
);
|
||||
return Ok(decoded_html);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(encoding) = Self::get_encoding_from_http_header(&headers) {
|
||||
log::debug!("Encoding extracted from headers: '{}'", encoding);
|
||||
if let Some(decoded_html) = Self::decode_html(&bytes, encoding) {
|
||||
let decoded_html = decoded_html.replacen(
|
||||
&format!("charset=\"{encoding}\""),
|
||||
"charset=\"utf-8\"",
|
||||
1,
|
||||
);
|
||||
return Ok(decoded_html);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(FullTextParserError::Utf8(error));
|
||||
}
|
||||
}
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
log::error!("status code: {status}");
|
||||
return Err(FullTextParserError::Http);
|
||||
}
|
||||
|
||||
Err(FullTextParserError::Http)
|
||||
let headers = response.headers().clone();
|
||||
|
||||
if headers
|
||||
.get(reqwest::header::CONTENT_LENGTH)
|
||||
.and_then(|hv| hv.to_str().ok())
|
||||
.and_then(|str| str.parse::<i64>().ok())
|
||||
.map(|content_length| content_length == 0)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
log::error!("Empty response body");
|
||||
return Err(FullTextParserError::Http);
|
||||
}
|
||||
|
||||
let bytes = response
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|_| FullTextParserError::Http)?;
|
||||
|
||||
match from_utf8(&bytes) {
|
||||
Ok(utf8_str) => {
|
||||
log::debug!("Valid utf-8 string");
|
||||
Ok(utf8_str.into())
|
||||
}
|
||||
Err(error) => {
|
||||
log::debug!("Invalid utf-8 string");
|
||||
let lossy_string = std::string::String::from_utf8_lossy(&bytes);
|
||||
|
||||
if let Some(encoding) = Self::get_encoding_from_html(&lossy_string) {
|
||||
log::debug!("Encoding extracted from HTML: '{encoding}'");
|
||||
if let Some(decoded_html) = Self::decode_html(&bytes, encoding) {
|
||||
let decoded_html = decoded_html.replacen(
|
||||
&format!("charset=\"{encoding}\""),
|
||||
"charset=\"utf-8\"",
|
||||
1,
|
||||
);
|
||||
return Ok(decoded_html);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(encoding) = Self::get_encoding_from_http_header(&headers) {
|
||||
log::debug!("Encoding extracted from headers: '{encoding}'");
|
||||
if let Some(decoded_html) = Self::decode_html(&bytes, encoding) {
|
||||
let decoded_html = decoded_html.replacen(
|
||||
&format!("charset=\"{encoding}\""),
|
||||
"charset=\"utf-8\"",
|
||||
1,
|
||||
);
|
||||
return Ok(decoded_html);
|
||||
}
|
||||
}
|
||||
|
||||
Err(FullTextParserError::Utf8(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download(
|
||||
|
@ -359,7 +444,12 @@ impl FullTextParser {
|
|||
let headers = Util::generate_headers(config, global_config)?;
|
||||
let response = Self::get_response(url, client, headers).await?;
|
||||
let body = Self::get_body(response).await?;
|
||||
Ok(body)
|
||||
if body.is_empty() {
|
||||
log::error!("Empty response body");
|
||||
Err(FullTextParserError::Http)
|
||||
} else {
|
||||
Ok(body)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_encoding_from_http_header(headers: &reqwest::header::HeaderMap) -> Option<&str> {
|
||||
|
@ -427,28 +517,115 @@ impl FullTextParser {
|
|||
conf
|
||||
}
|
||||
|
||||
fn check_for_thumbnail(context: &Context, article: &mut Article) {
|
||||
pub fn thumbnail_from_html(html: &str) -> Option<String> {
|
||||
if let Ok(doc) = Self::parse_html_string_patched(html) {
|
||||
if let Ok(ctx) = Self::get_xpath_ctx(&doc) {
|
||||
return Self::check_for_thumbnail(&ctx);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn check_for_thumbnail(context: &Context) -> Option<String> {
|
||||
if let Ok(thumb) = Util::get_attribute(
|
||||
context,
|
||||
"//meta[contains(@name, 'twitter:image')]",
|
||||
"content",
|
||||
) {
|
||||
article.thumbnail_url = Some(thumb);
|
||||
return;
|
||||
return Some(thumb);
|
||||
}
|
||||
|
||||
if let Ok(thumb) =
|
||||
Util::get_attribute(context, "//meta[contains(@name, 'og:image')]", "content")
|
||||
{
|
||||
article.thumbnail_url = Some(thumb);
|
||||
return;
|
||||
return Some(thumb);
|
||||
}
|
||||
|
||||
if let Ok(thumb) = Util::get_attribute(
|
||||
context,
|
||||
"//meta[contains(@property, 'twitter:image')]",
|
||||
"content",
|
||||
) {
|
||||
return Some(thumb);
|
||||
}
|
||||
|
||||
if let Ok(thumb) = Util::get_attribute(
|
||||
context,
|
||||
"//meta[contains(@property, 'og:image')]",
|
||||
"content",
|
||||
) {
|
||||
return Some(thumb);
|
||||
}
|
||||
|
||||
if let Ok(thumb) =
|
||||
Util::get_attribute(context, "//link[contains(@rel, 'image_src')]", "href")
|
||||
{
|
||||
article.thumbnail_url = Some(thumb);
|
||||
return Some(thumb);
|
||||
}
|
||||
|
||||
if let Ok(img_nodes) = Util::evaluate_xpath(context, "//img", true) {
|
||||
let mut scores: HashMap<String, i32> = HashMap::new();
|
||||
let len = img_nodes.len();
|
||||
for (index, img_node) in img_nodes.into_iter().enumerate() {
|
||||
let src = if let Some(src) = img_node.get_attribute("src") {
|
||||
src
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let score = Util::score_image_url(&src);
|
||||
let score = score + Util::score_img_attr(&img_node);
|
||||
let score = score + Util::score_by_parents(&img_node);
|
||||
let score = score + Util::score_by_sibling(&img_node);
|
||||
let score = score + Util::score_by_dimensions(&img_node);
|
||||
let score = score + Util::score_by_position(len, index);
|
||||
let score = score + Util::score_by_alt(&img_node);
|
||||
|
||||
scores.insert(src, score);
|
||||
}
|
||||
|
||||
if let Some((top_src, top_score)) =
|
||||
scores.into_iter().max_by_key(|(_src, score)| *score)
|
||||
{
|
||||
if top_score > 0 {
|
||||
let top_url = top_src.trim().into();
|
||||
if Url::parse(top_src.trim()).is_ok() {
|
||||
return Some(top_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing else worked, check to see if there are any really
|
||||
// probable nodes in the doc, like <link rel="image_src" />.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if let Ok(link_nodes) = Util::evaluate_xpath(context, constants::LEAD_IMAGE_URL_XPATH, true)
|
||||
{
|
||||
if let Some(first_link_node) = link_nodes.first() {
|
||||
if let Some(src) = first_link_node.get_attribute("src") {
|
||||
let src = src.trim().to_string();
|
||||
if Url::parse(&src).is_ok() {
|
||||
return Some(src);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(href) = first_link_node.get_attribute("href") {
|
||||
let href = href.trim().to_string();
|
||||
if Url::parse(&href).is_ok() {
|
||||
return Some(href);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(val) = first_link_node.get_attribute("value") {
|
||||
let val = val.trim().to_string();
|
||||
if Url::parse(&val).is_ok() {
|
||||
return Some(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn fix_lazy_images(context: &Context, doc: &Document) -> Result<(), FullTextParserError> {
|
||||
|
@ -548,6 +725,10 @@ impl FullTextParser {
|
|||
let xpath = &format!("//iframe[contains(@src, '{}')]", site_name);
|
||||
let node_vec = Util::evaluate_xpath(context, xpath, false)?;
|
||||
for mut node in node_vec {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let video_wrapper = node
|
||||
.get_parent()
|
||||
.and_then(|mut parent| parent.new_child(None, "div").ok());
|
||||
|
@ -555,15 +736,16 @@ impl FullTextParser {
|
|||
let success = video_wrapper
|
||||
.set_property("class", "videoWrapper")
|
||||
.ok()
|
||||
.and_then(|()| node.set_property("width", "100%").ok())
|
||||
.and_then(|()| node.set_property("height", "100%").ok())
|
||||
.and_then(|()| node.set_property("width", "480").ok())
|
||||
.and_then(|()| node.set_property("height", "360").ok())
|
||||
.and_then(|()| node.set_property("aspect-ratio", "auto").ok())
|
||||
.ok_or_else(|| {
|
||||
node.unlink();
|
||||
video_wrapper.add_child(&mut node)
|
||||
})
|
||||
.is_err();
|
||||
if !success {
|
||||
log::warn!("Failed to add iframe as child of video wrapper <div>");
|
||||
log::debug!("Failed to add iframe as child of video wrapper <div>");
|
||||
}
|
||||
} else {
|
||||
log::warn!("Failed to get parent of iframe");
|
||||
|
@ -602,6 +784,10 @@ impl FullTextParser {
|
|||
) -> Result<(), FullTextParserError> {
|
||||
let node_vec = Util::evaluate_xpath(context, xpath, false)?;
|
||||
for mut node in node_vec {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(url) = node.get_attribute(attribute) {
|
||||
let trimmed_url = url.trim();
|
||||
|
||||
|
@ -715,6 +901,10 @@ impl FullTextParser {
|
|||
|
||||
if let Ok(h2_nodes) = Util::evaluate_xpath(context, "//h2", false) {
|
||||
for mut h2_node in h2_nodes {
|
||||
if h2_node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if Util::header_duplicates_title(&h2_node, title) {
|
||||
h2_node.unlink();
|
||||
}
|
||||
|
@ -775,6 +965,8 @@ impl FullTextParser {
|
|||
_ = Self::fix_lazy_images(context, document);
|
||||
_ = Self::fix_iframe_size(context, "youtube.com");
|
||||
_ = Self::remove_attribute(context, Some("a"), "onclick");
|
||||
_ = Self::remove_attribute(context, Some("img"), "decoding");
|
||||
_ = Self::remove_attribute(context, Some("img"), "loading");
|
||||
|
||||
// strip elements using Readability.com and Instapaper.com ignore class names
|
||||
// .entry-unrelated and .instapaper_ignore
|
||||
|
@ -821,6 +1013,7 @@ impl FullTextParser {
|
|||
|
||||
if let Some(root) = document.get_root_element() {
|
||||
Util::replace_brs(&root, document);
|
||||
Util::replace_emoji_images(&root, document);
|
||||
}
|
||||
|
||||
Self::fix_urls(context, url, document);
|
||||
|
@ -837,6 +1030,10 @@ impl FullTextParser {
|
|||
// This is done to prevent a placeholder img is replaced by img from noscript in next step.
|
||||
let img_nodes = Util::evaluate_xpath(ctx, "//img", false)?;
|
||||
for mut img_node in img_nodes {
|
||||
if img_node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let attrs = img_node.get_attributes();
|
||||
|
||||
let keep = attrs.iter().any(|(name, value)| {
|
||||
|
@ -854,6 +1051,10 @@ impl FullTextParser {
|
|||
// Next find noscript and try to extract its image
|
||||
let noscript_nodes = Util::evaluate_xpath(ctx, "//noscript", false)?;
|
||||
for mut noscript_node in noscript_nodes {
|
||||
if noscript_node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse content of noscript and make sure it only contains image
|
||||
if !Util::is_single_image(&noscript_node) {
|
||||
continue;
|
||||
|
@ -959,6 +1160,10 @@ impl FullTextParser {
|
|||
{
|
||||
let node_vec = Util::evaluate_xpath(context, xpath, false)?;
|
||||
for mut node in node_vec {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if node.get_property("style").is_some() && node.remove_property("style").is_err() {
|
||||
return Err(FullTextParserError::Xml);
|
||||
}
|
||||
|
@ -1019,29 +1224,15 @@ impl FullTextParser {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_head(root: &mut Node, document: &Document) -> Result<(), FullTextParserError> {
|
||||
if let Ok(mut head_node) = Node::new("head", None, document) {
|
||||
if let Ok(()) = root.add_prev_sibling(&mut head_node) {
|
||||
if let Ok(mut meta) = head_node.new_child(None, "meta") {
|
||||
if meta.set_property("charset", "utf-8").is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(FullTextParserError::Xml)
|
||||
}
|
||||
|
||||
fn prevent_self_closing_tags(context: &Context) -> Result<(), FullTextParserError> {
|
||||
pub(crate) fn prevent_self_closing_tags(context: &Context) -> Result<(), FullTextParserError> {
|
||||
// search document for empty tags and add a empty text node as child
|
||||
// this prevents libxml from self closing non void elements such as iframe
|
||||
|
||||
let xpath = "//*[not(node())]";
|
||||
let node_vec = Util::evaluate_xpath(context, xpath, false)?;
|
||||
for mut node in node_vec {
|
||||
let name = node.get_name().to_lowercase();
|
||||
if name == "meta" || name == "img" || name == "br" {
|
||||
let name = node.get_name().to_uppercase();
|
||||
if constants::VALID_SELF_CLOSING_TAGS.contains(name.as_str()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,14 +102,7 @@ impl Readability {
|
|||
continue;
|
||||
}
|
||||
|
||||
let match_string = node_ref
|
||||
.get_class_names()
|
||||
.iter()
|
||||
.fold(String::new(), |a, b| format!("{a} {b}"));
|
||||
let match_string = match node_ref.get_property("id") {
|
||||
Some(id) => format!("{match_string} {id}"),
|
||||
None => match_string,
|
||||
};
|
||||
let match_string = Util::get_signature(node_ref);
|
||||
|
||||
if !Util::is_probably_visible(node_ref) {
|
||||
log::debug!("removing hidden node {match_string}");
|
||||
|
@ -186,6 +179,10 @@ impl Readability {
|
|||
// Put phrasing content into paragraphs.
|
||||
let mut p: Option<Node> = None;
|
||||
for mut child in node_ref.get_child_nodes().into_iter() {
|
||||
if child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if Util::is_phrasing_content(&child) {
|
||||
if let Some(p) = p.as_mut() {
|
||||
child.unlink();
|
||||
|
@ -212,6 +209,10 @@ impl Readability {
|
|||
} else if p.is_some() {
|
||||
if let Some(p) = p.as_mut() {
|
||||
for mut r_node in p.get_child_nodes().into_iter().rev() {
|
||||
if r_node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if Util::is_whitespace(&r_node) {
|
||||
r_node.unlink();
|
||||
continue;
|
||||
|
@ -373,6 +374,10 @@ impl Readability {
|
|||
Node::new("DIV", None, &document).expect("can't create new node");
|
||||
|
||||
for mut child in root.get_child_elements().drain(..) {
|
||||
if child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
child.unlink();
|
||||
new_top_candidate.add_child(&mut child).unwrap();
|
||||
}
|
||||
|
@ -517,6 +522,10 @@ impl Readability {
|
|||
|
||||
if let Some(mut siblings) = siblings {
|
||||
for mut sibling in siblings.drain(..) {
|
||||
if sibling.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut append = false;
|
||||
|
||||
let score = Self::get_content_score(&sibling).unwrap_or(0.0);
|
||||
|
@ -621,6 +630,10 @@ impl Readability {
|
|||
})?;
|
||||
|
||||
for mut child in article_content.get_child_nodes() {
|
||||
if child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
child.unlink();
|
||||
div.add_child(&mut child).map_err(|error| {
|
||||
log::error!("{error}");
|
||||
|
@ -664,6 +677,10 @@ impl Readability {
|
|||
// But first check if we actually have something
|
||||
if let Some((best_attempt, _len, _document)) = attempts.pop() {
|
||||
for mut child in best_attempt.get_child_nodes() {
|
||||
if child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
child.unlink();
|
||||
root.add_child(&mut child).map_err(|error| {
|
||||
log::error!("{error}");
|
||||
|
@ -681,6 +698,10 @@ impl Readability {
|
|||
.map_err(|()| FullTextParserError::Readability)?;
|
||||
} else {
|
||||
for mut child in article_content.get_child_nodes() {
|
||||
if child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
child.unlink();
|
||||
root.add_child(&mut child).map_err(|error| {
|
||||
log::error!("{error}");
|
||||
|
|
|
@ -39,6 +39,10 @@ async fn run_test(name: &str) {
|
|||
|
||||
metadata::extract(&xpath_ctx, None, None, &mut article);
|
||||
super::Readability::extract_body(document, &mut root, article.title.as_deref()).unwrap();
|
||||
|
||||
let article_ctx = crate::FullTextParser::get_xpath_ctx(&article_document).unwrap();
|
||||
|
||||
crate::FullTextParser::prevent_self_closing_tags(&article_ctx).unwrap();
|
||||
crate::FullTextParser::post_process_document(&article_document).unwrap();
|
||||
|
||||
let html = Util::serialize_node(&article_document, &root);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{config::ConfigEntry, FullTextParser};
|
||||
use libxml::tree::SaveOptions;
|
||||
use libxml::{tree::SaveOptions, xpath::Context};
|
||||
use reqwest::{Client, Url};
|
||||
|
||||
async fn run_test(name: &str, url: &str, title: Option<&str>, author: Option<&str>) {
|
||||
|
@ -74,11 +74,15 @@ async fn hardwareluxx() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "waiting on clarification for https://github.com/fivefilters/ftr-site-config/pull/1081"]
|
||||
async fn heise_1() {
|
||||
run_test("heise-1", "https://www.heise.de/", None, None).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn spiegel_1() {
|
||||
run_test("spiegel-1", "https://www.spiegel.de/", None, None).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "downloads content from the web"]
|
||||
async fn encoding_windows_1252() {
|
||||
|
@ -180,3 +184,111 @@ async fn unwrap_noscript_images_2() {
|
|||
|
||||
assert_eq!(res, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_thumbnail_golem() {
|
||||
let html = r#"
|
||||
<img src="https://www.golem.de/2306/175204-387164-387163_rc.jpg" width="140" height="140" loading="lazy" />Im staubigen
|
||||
Utah sind die Fossilien eines urzeitlichen Meeresreptils entdeckt worden. Nun haben Forscher eine Studie dazu
|
||||
herausgebracht. (<a href="https://www.golem.de/specials/fortschritt/" rel="noopener noreferrer" target="_blank"
|
||||
referrerpolicy="no-referrer">Fortschritt</a>, <a href="https://www.golem.de/specials/wissenschaft/"
|
||||
rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">Wissenschaft</a>)
|
||||
"#;
|
||||
let doc = FullTextParser::parse_html_string_patched(html).unwrap();
|
||||
let ctx = Context::new(&doc).unwrap();
|
||||
|
||||
let thumb = FullTextParser::check_for_thumbnail(&ctx).unwrap();
|
||||
assert_eq!(
|
||||
thumb,
|
||||
"https://www.golem.de/2306/175204-387164-387163_rc.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_thumbnail_spiegel() {
|
||||
let html = r#"
|
||||
<article><section data-article-el="body">
|
||||
<div data-area="top_element>image">
|
||||
<figure>
|
||||
<div data-sara-component="{"id":"a4573666-f15e-4290-8c73-a0c6cd4ad3b2","name":"image","title":"\u003cp\u003eGrünenpolitiker Hofreiter: »Unternehmen werden in großem Umfang erpresst, unter Wert ihre Betriebe zu verkaufen«\u003c/p\u003e","type":"media"}">
|
||||
<picture>
|
||||
<source srcset="https://cdn.prod.www.spiegel.de/images/a4573666-f15e-4290-8c73-a0c6cd4ad3b2_w948_r1.778_fpx29.99_fpy44.98.webp 948w, https://cdn.prod.www.spiegel.de/images/a4573666-f15e-4290-8c73-a0c6cd4ad3b2_w520_r1.778_fpx29.99_fpy44.98.webp 520w" sizes="(max-width: 519px) 100vw, (min-width: 520px) and (max-width: 719px) 520px, (min-width: 720px) and (max-width: 919px) 100vw, (min-width: 920px) and (max-width: 1011px) 920px, (min-width: 1012px) 948px" type="image/webp">
|
||||
<img data-image-el="img" src="https://cdn.prod.www.spiegel.de/images/a4573666-f15e-4290-8c73-a0c6cd4ad3b2_w948_r1.778_fpx29.99_fpy44.98.jpg" width="948" height="533" title="Grünenpolitiker Hofreiter: »Unternehmen werden in großem Umfang erpresst, unter Wert ihre Betriebe zu verkaufen«" alt="Grünenpolitiker Hofreiter: »Unternehmen werden in großem Umfang erpresst, unter Wert ihre Betriebe zu verkaufen«" data-image-animation-origin="91086ec8-2db6-4a72-be06-66c9e5db9058"/>
|
||||
</source></picture>
|
||||
</div>
|
||||
<figcaption>
|
||||
<p>Grünenpolitiker Hofreiter: »Unternehmen werden in großem Umfang erpresst, unter Wert ihre Betriebe zu verkaufen«</p>
|
||||
<span>
|
||||
Foto: IMAGO / IMAGO/Political-Moments
|
||||
</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div data-area="body">
|
||||
<div data-pos="1" data-sara-click-el="body_element" data-area="text">
|
||||
<p>Der Töne aus Berlin in Richtung Budapest werden giftiger. Der Grünen-Europapolitiker <a href="https://www.spiegel.de/thema/anton_hofreiter/" data-link-flag="spon" target="_blank">Anton Hofreiter</a> wirft der ungarischen Regierung vor, deutsche Unternehmen mit »Mafiamethoden« zum Verkauf ihres <a href="https://www.spiegel.de/thema/ungarn/" data-link-flag="spon" target="_blank">Ungarn</a>-Geschäfts zu bringen. »Ungarn bewegt sich von einer autoritären Herrschaft in Richtung eines Mafiastaats«, sagte Hofreiter in Brüssel. »Unternehmen werden in großem Umfang erpresst, unter Wert ihre Betriebe zu verkaufen.«</p>
|
||||
</div>
|
||||
|
||||
<div data-area="text" data-sara-click-el="body_element" data-pos="3">
|
||||
<p>Aus der deutschen Wirtschaft gebe es Klagen über zahlreiche Fälle, in denen Firmen »mit illegalen Methoden« vom Markt gedrängt worden seien oder entsprechende Versuche stattgefunden hätten.</p><p>Während Ungarns Regierungschef <a href="https://www.spiegel.de/thema/viktor_orban/" data-link-flag="spon" target="_blank">Viktor Orbán</a> deutsche Autohersteller weiterhin mit niedrigen Steuern und wenig Bürokratie verwöhne, bekämen andere Firmen die Folgen von Orbáns Strategie der Nationalisierung von als strategisch wichtig geltenden Branchen zu spüren. Selbst Großunternehmen wie Lidl oder die Telekom würden inzwischen »massiv unter Druck gesetzt«, so Hofreiter.</p>
|
||||
</div>
|
||||
|
||||
<div data-sara-click-el="body_element" data-area="image" data-pos="5">
|
||||
<figure>
|
||||
<div data-sara-component="{"id":"cce7cbb0-2a7e-449d-a24e-6a24a73108b2","name":"image","title":"Ungarns Regierungschef Viktor Orbán","type":"media"}">
|
||||
<picture>
|
||||
<source data-srcset="https://cdn.prod.www.spiegel.de/images/cce7cbb0-2a7e-449d-a24e-6a24a73108b2_w718_r1.5001583782071588_fpx53.97_fpy44.98.jpg 718w, https://cdn.prod.www.spiegel.de/images/cce7cbb0-2a7e-449d-a24e-6a24a73108b2_w488_r1.5001583782071588_fpx53.97_fpy44.98.jpg 488w, https://cdn.prod.www.spiegel.de/images/cce7cbb0-2a7e-449d-a24e-6a24a73108b2_w616_r1.5001583782071588_fpx53.97_fpy44.98.jpg 616w" data-sizes="(max-width: 487px) 100vw, (min-width: 488px) and (max-width: 719px) 488px, (min-width: 720px) and (max-width: 1011px) 718px, (min-width: 1012px) 616px">
|
||||
<img data-image-el="img" data-src-disabled="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 718 479' width='718' height='479' %3E%3C/svg%3E" src="https://cdn.prod.www.spiegel.de/images/cce7cbb0-2a7e-449d-a24e-6a24a73108b2_w718_r1.5001583782071588_fpx53.97_fpy44.98.jpg" width="718" height="479" title="Ungarns Regierungschef Viktor Orbán" alt="Ungarns Regierungschef Viktor Orbán" data-image-animation-origin="38ca0348-88da-4a3b-8a9d-f1c059e79c77"/>
|
||||
</source></picture>
|
||||
|
||||
</div>
|
||||
</figure>
|
||||
<figcaption>
|
||||
<p>Ungarns Regierungschef Viktor Orbán</p>
|
||||
<span>
|
||||
Foto: IMAGO/Vaclav Salek / IMAGO/CTK Photo
|
||||
</span>
|
||||
</figcaption></div>
|
||||
<div data-pos="6" data-sara-click-el="body_element" data-area="text">
|
||||
<p>Die Masche des Systems Orbán ist die immer gleiche, wie Unternehmen und Politiker <a href="https://www.spiegel.de/wirtschaft/ungarn-wie-viktor-orban-deutsche-unternehmen-aus-dem-land-mobbt-a-2b345c3e-5223-4ae6-97bc-ba1718f20907" target="_blank">schon seit Monaten beklagen</a>: Die Regierung macht die Unternehmen erst Schikanen mürbe und unterbreitet dann wieder und wieder Kaufangebote. Die Firmen würden so gedrängt, ihre ungarischen Aktivitäten an Günstlinge Orbáns zu verkaufen – zwar nicht zu ruinösen Schleuderpreisen, aber üblicherweise für nur etwa 70 bis 80 Prozent des Marktwerts, sagt Hofreiter.</p>
|
||||
</div>
|
||||
|
||||
<div data-pos="8" data-sara-click-el="body_element" data-area="text">
|
||||
<p>In Ungarn gehe es nicht mehr nur um die bereits weit fortgeschrittene Zerstörung des Rechtsstaats – »sondern inzwischen auch eindeutig um das Funktionieren des Binnenmarkts« der EU. »Der klassische ökonomische Teil des Binnenmarkts wird angegriffen.«</p><p>Die Kommission hat wegen Ungarns Rechtsstaatsverstößen bereits <a rel="noopener noreferrer" href="https://www.spiegel.de/ausland/eu-friert-saemtliche-strukturfoerdermittel-fuer-ungarn-ein-a-739da28a-243a-4fe1-af8c-a515fb8bf967" target="_blank">Milliardenzahlungen an das Land eingefroren</a>. Das aber genüge nicht mehr, sagt Hofreiter – und fordert von der Kommission deshalb, neue Sanktionsinstrumente zu entwickeln: »Man muss sich Mechanismen zum Schutz des Binnenmarkts überlegen.«</p><h3>Ungarns Außenminister beklagt »politisch motivierte Kampagne«</h3><p>Der grüne Europaabgeordnete Daniel Freund verlangt außerdem eine Beschleunigung laufender und künftiger Verfahren gegen Ungarn wegen der Verletzung der EU-Verträge. »Wenn eine Firma wegen eines Regierungsdekrets Monat für Monat Millionen an Steuern bezahlen muss, kann sie nicht Jahre warten, ehe ein solches Verfahren abgeschlossen ist.«</p>
|
||||
</div>
|
||||
|
||||
<div data-pos="10" data-area="text" data-sara-click-el="body_element">
|
||||
<p>Ungarns Außen- und Handelsminister Péter Szijjártó <a href="https://abouthungary.hu/news-in-brief/fm-a-politically-motivated-campaign-is-underway-against-hungary-over-german-investments" target="_blank">bezeichnete </a> die Vorwürfe kürzlich als »politisch motivierte Kampagne« und »emotionale Erpressung«. Seit 2014 habe Budapest 183 deutsche Unternehmen gefördert. Insgesamt würden rund 6000 deutsche Firmen in Ungarn etwa 300.000 Menschen beschäftigen.</p>
|
||||
</div>
|
||||
|
||||
<div data-sara-click-el="body_element" data-pos="12" data-area="text">
|
||||
<p>Orbáns Politik stößt nicht nur bei den Grünen auf Kritik, sondern auch bei den deutschen Unionsparteien. Bis März 2021 waren sie gemeinsam mit Orbáns Fidesz-Partei in der Europäischen Volkspartei; jahrelang hofierten sie den Autokraten aus Budapest.</p><p><a href="https://www.spiegel.de/thema/monika_hohlmeier/" data-link-flag="spon" target="_blank">Monika Hohlmeier</a> (CSU) etwa, Vorsitzende des Haushaltskontrollausschusses im EU-Parlament, sieht in Orbán mittlerweile »einen Mann mit kleptokratischen Zügen«, in dessen System »rechtsstaatliche Prinzipien mit Füßen getreten werden«. Erfolgreiche ausländische Unternehmer müssten in Ungarn damit rechnen, »dass ein Oligarch auftaucht, der sich deine Firma unter den Nagel reißen will«.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section></article>
|
||||
"#;
|
||||
|
||||
let doc = FullTextParser::parse_html_string_patched(html).unwrap();
|
||||
let ctx = Context::new(&doc).unwrap();
|
||||
|
||||
let thumb = FullTextParser::check_for_thumbnail(&ctx).unwrap();
|
||||
assert_eq!(
|
||||
thumb,
|
||||
"https://cdn.prod.www.spiegel.de/images/a4573666-f15e-4290-8c73-a0c6cd4ad3b2_w948_r1.778_fpx29.99_fpy44.98.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_thumbnail_a_chacon() {
|
||||
let html = std::fs::read_to_string("./resources/tests/thumbnails/a-chacon.html")
|
||||
.expect("Failed to read source HTML");
|
||||
let doc = FullTextParser::parse_html_string_patched(&html).unwrap();
|
||||
let ctx = Context::new(&doc).unwrap();
|
||||
|
||||
let thumb = FullTextParser::check_for_thumbnail(&ctx).unwrap();
|
||||
assert_eq!(
|
||||
thumb,
|
||||
"https://a-chacon.com/assets/images/rails8-poc-api-auth.webp"
|
||||
)
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ impl ImageObject {
|
|||
}
|
||||
|
||||
pub fn replace(&self, node: &mut Node) -> Result<(), FullTextParserError> {
|
||||
if node.is_null() {
|
||||
return Err(FullTextParserError::Xml);
|
||||
}
|
||||
|
||||
let mut parent = node.get_parent().ok_or(FullTextParserError::Xml)?;
|
||||
|
||||
if parent.get_name().to_uppercase() == "A" {
|
||||
|
|
|
@ -23,3 +23,9 @@ pub enum ImageDownloadError {
|
|||
#[error("Unknown Error")]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for ImageDownloadError {
|
||||
fn from(_value: reqwest::Error) -> Self {
|
||||
Self::Http
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
pub struct ImageData {
|
||||
pub url: String,
|
||||
pub data: Vec<u8>,
|
||||
pub content_length: usize,
|
||||
pub content_type: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@ use self::image_data::ImageDataBase64;
|
|||
use self::pair::Pair;
|
||||
use self::request::ImageRequest;
|
||||
use crate::util::Util;
|
||||
use crate::{constants, FullTextParser};
|
||||
use base64::Engine;
|
||||
use image::ImageOutputFormat;
|
||||
use libxml::parser::Parser;
|
||||
use futures::StreamExt;
|
||||
use image::ImageFormat;
|
||||
use libxml::tree::{Node, SaveOptions};
|
||||
use libxml::xpath::Context;
|
||||
pub use progress::Progress;
|
||||
|
@ -28,6 +29,51 @@ impl ImageDownloader {
|
|||
ImageDownloader { max_size }
|
||||
}
|
||||
|
||||
pub async fn single_from_url(
|
||||
url: &str,
|
||||
client: &Client,
|
||||
progress: Option<Sender<Progress>>,
|
||||
) -> Result<Vec<u8>, ImageDownloadError> {
|
||||
let response = client.get(url).send().await?;
|
||||
|
||||
let content_type = Util::get_content_type(&response);
|
||||
let content_length = Util::get_content_length(&response);
|
||||
|
||||
if let (Err(_), Ok(content_length)) = (&content_type, &content_length) {
|
||||
if *content_length > constants::UNKNOWN_CONTENT_SIZE_LIMIT {
|
||||
return Err(ImageDownloadError::ContentType);
|
||||
}
|
||||
} else if !content_type?.contains("image") {
|
||||
return Err(ImageDownloadError::ContentType);
|
||||
}
|
||||
|
||||
let content_length = content_length.unwrap_or(0);
|
||||
|
||||
let mut stream = response.bytes_stream();
|
||||
let mut downloaded_bytes = 0;
|
||||
|
||||
let mut result = Vec::with_capacity(content_length);
|
||||
while let Some(item) = stream.next().await {
|
||||
let chunk = item?;
|
||||
downloaded_bytes += chunk.len();
|
||||
|
||||
if let Some(sender) = progress.as_ref() {
|
||||
_ = sender
|
||||
.send(Progress {
|
||||
total_size: content_length,
|
||||
downloaded: downloaded_bytes,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
for byte in chunk {
|
||||
result.push(byte);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn download_images_from_string(
|
||||
&self,
|
||||
html: &str,
|
||||
|
@ -115,9 +161,7 @@ impl ImageDownloader {
|
|||
html: &str,
|
||||
downloaded_images: Vec<Pair<ImageDataBase64>>,
|
||||
) -> Result<String, ImageDownloadError> {
|
||||
let parser = Parser::default_html();
|
||||
let doc = parser
|
||||
.parse_string(html)
|
||||
let doc = FullTextParser::parse_html_string_patched(html)
|
||||
.map_err(|_| ImageDownloadError::HtmlParse)?;
|
||||
|
||||
let xpath_ctx = Context::new(&doc).map_err(|()| {
|
||||
|
@ -160,9 +204,7 @@ impl ImageDownloader {
|
|||
}
|
||||
|
||||
fn harvest_image_urls_from_html(html: &str) -> Result<Vec<Pair<String>>, ImageDownloadError> {
|
||||
let parser = Parser::default_html();
|
||||
let doc = parser
|
||||
.parse_string(html)
|
||||
let doc = FullTextParser::parse_html_string_patched(html)
|
||||
.map_err(|_| ImageDownloadError::HtmlParse)?;
|
||||
|
||||
let xpath_ctx = Context::new(&doc).map_err(|()| {
|
||||
|
@ -177,7 +219,9 @@ impl ImageDownloader {
|
|||
let mut image_urls = Vec::new();
|
||||
|
||||
for node in node_vec {
|
||||
image_urls.push(Self::harvest_image_urls_from_node(node)?);
|
||||
if let Ok(url) = Self::harvest_image_urls_from_node(node) {
|
||||
image_urls.push(url);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(image_urls)
|
||||
|
@ -277,8 +321,7 @@ impl ImageDownloader {
|
|||
image::imageops::FilterType::Lanczos3,
|
||||
);
|
||||
let mut resized_buf: Vec<u8> = Vec::new();
|
||||
if let Err(error) =
|
||||
image.write_to(&mut Cursor::new(&mut resized_buf), ImageOutputFormat::Png)
|
||||
if let Err(error) = image.write_to(&mut Cursor::new(&mut resized_buf), ImageFormat::Png)
|
||||
{
|
||||
log::error!("Failed to save resized image to resize: {}", error);
|
||||
return None;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use futures::StreamExt;
|
||||
use reqwest::{header::CONTENT_TYPE, Client, Response};
|
||||
use reqwest::{Client, Response};
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use crate::util::Util;
|
||||
|
||||
use super::{image_data::ImageData, ImageDownloadError};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -14,14 +16,10 @@ pub struct ImageRequest {
|
|||
|
||||
impl ImageRequest {
|
||||
pub async fn new(url: String, client: &Client) -> Result<Self, ImageDownloadError> {
|
||||
let response = client
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|_| ImageDownloadError::Http)?;
|
||||
let response = client.get(&url).send().await?;
|
||||
|
||||
let content_type = Self::get_content_type(&response)?;
|
||||
let content_length = Self::get_content_length(&response)?;
|
||||
let content_type = Util::get_content_type(&response)?;
|
||||
let content_length = Util::get_content_length(&response)?;
|
||||
|
||||
if !content_type.contains("image") {
|
||||
return Err(ImageDownloadError::ContentType);
|
||||
|
@ -40,7 +38,7 @@ impl ImageRequest {
|
|||
|
||||
let mut result = Vec::with_capacity(self.content_length);
|
||||
while let Some(item) = stream.next().await {
|
||||
let chunk = item.map_err(|_| ImageDownloadError::Http)?;
|
||||
let chunk = item?;
|
||||
_ = tx.send(chunk.len()).await;
|
||||
for byte in chunk {
|
||||
result.push(byte);
|
||||
|
@ -50,7 +48,6 @@ impl ImageRequest {
|
|||
Ok(ImageData {
|
||||
url: self.url,
|
||||
data: result,
|
||||
content_length: self.content_length,
|
||||
content_type: self.content_type,
|
||||
})
|
||||
}
|
||||
|
@ -62,33 +59,4 @@ impl ImageRequest {
|
|||
pub fn content_length(&self) -> usize {
|
||||
self.content_length
|
||||
}
|
||||
|
||||
fn get_content_length(response: &Response) -> Result<usize, ImageDownloadError> {
|
||||
let status_code = response.status();
|
||||
|
||||
if !status_code.is_success() {
|
||||
log::warn!("response: {status_code}");
|
||||
return Err(ImageDownloadError::Http);
|
||||
}
|
||||
|
||||
response
|
||||
.headers()
|
||||
.get(reqwest::header::CONTENT_LENGTH)
|
||||
.and_then(|content_length| content_length.to_str().ok())
|
||||
.and_then(|content_length| content_length.parse::<usize>().ok())
|
||||
.ok_or(ImageDownloadError::ContentLength)
|
||||
}
|
||||
|
||||
fn get_content_type(response: &Response) -> Result<String, ImageDownloadError> {
|
||||
if response.status().is_success() {
|
||||
response
|
||||
.headers()
|
||||
.get(CONTENT_TYPE)
|
||||
.and_then(|val| val.to_str().ok())
|
||||
.map(|val| val.to_string())
|
||||
.ok_or(ImageDownloadError::ContentType)
|
||||
} else {
|
||||
Err(ImageDownloadError::ContentType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ mod util;
|
|||
mod video_object;
|
||||
|
||||
use crate::images::Progress;
|
||||
use article::Article;
|
||||
pub use article::Article;
|
||||
use error::ScraperError;
|
||||
#[doc(hidden)]
|
||||
pub use full_text_parser::config::ConfigEntry as FtrConfigEntry;
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use libxml::{
|
||||
tree::{Document, Node, NodeType, SaveOptions},
|
||||
xpath::Context,
|
||||
};
|
||||
use reqwest::{
|
||||
header::{HeaderMap, HeaderName, HeaderValue},
|
||||
header::{HeaderMap, HeaderName, HeaderValue, CONTENT_LENGTH, CONTENT_TYPE},
|
||||
Response,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
use tokio::fs::DirEntry;
|
||||
|
||||
use crate::{
|
||||
constants,
|
||||
constants::{self, NEGATIVE_LEAD_IMAGE_URL_HINTS_REGEX},
|
||||
full_text_parser::{config::ConfigEntry, error::FullTextParserError},
|
||||
image_object::ImageObject,
|
||||
images::ImageDownloadError,
|
||||
video_object::VideoObject,
|
||||
};
|
||||
|
||||
|
@ -189,7 +190,7 @@ impl Util {
|
|||
|
||||
pub fn extract_value(context: &Context, xpath: &str) -> Result<String, FullTextParserError> {
|
||||
let node_vec = Util::evaluate_xpath(context, xpath, false)?;
|
||||
if let Some(val) = node_vec.get(0) {
|
||||
if let Some(val) = node_vec.first() {
|
||||
return Ok(val.get_content());
|
||||
}
|
||||
|
||||
|
@ -203,11 +204,13 @@ impl Util {
|
|||
let node_vec = Util::evaluate_xpath(context, xpath, true)?;
|
||||
let mut val = String::new();
|
||||
for node in node_vec {
|
||||
let part = node
|
||||
.get_content()
|
||||
.split_whitespace()
|
||||
.map(|s| format!("{} ", s))
|
||||
.collect::<String>();
|
||||
let part =
|
||||
node.get_content()
|
||||
.split_whitespace()
|
||||
.fold(String::new(), |mut output, s| {
|
||||
let _ = write!(output, " {s}");
|
||||
output
|
||||
});
|
||||
val.push_str(&part);
|
||||
val.push(' ');
|
||||
}
|
||||
|
@ -220,6 +223,10 @@ impl Util {
|
|||
let node_vec_clone = node_vec.clone();
|
||||
|
||||
for mut node in node_vec {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let tag_name = node.get_name();
|
||||
if constants::EMBED_TAG_NAMES.contains(tag_name.to_uppercase().as_str())
|
||||
&& node
|
||||
|
@ -270,11 +277,26 @@ impl Util {
|
|||
let query = &format!("{}[not(ancestor::{})]", xpath, ancestor);
|
||||
let node_vec = Util::evaluate_xpath(context, query, false)?;
|
||||
for mut node in node_vec {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
node.unlink();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_signature(node: &Node) -> String {
|
||||
let match_string = node
|
||||
.get_class_names()
|
||||
.iter()
|
||||
.fold(String::new(), |a, b| format!("{a} {b}"));
|
||||
match node.get_property("id") {
|
||||
Some(id) => format!("{match_string} {id}"),
|
||||
None => match_string,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_probably_visible(node: &Node) -> bool {
|
||||
let is_hidden = node.has_attribute("hidden");
|
||||
let aria_hidden = node
|
||||
|
@ -306,6 +328,10 @@ impl Util {
|
|||
}
|
||||
|
||||
pub fn remove_and_next(node: &mut Node) -> Option<Node> {
|
||||
if node.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let next_node = Self::next_node(node, true);
|
||||
node.unlink();
|
||||
next_node
|
||||
|
@ -536,6 +562,24 @@ impl Util {
|
|||
vec
|
||||
}
|
||||
|
||||
pub fn get_first_element_by_tag_name(node: &Node, tag: &str) -> Option<Node> {
|
||||
let tag = tag.to_uppercase();
|
||||
|
||||
fn get_elems(node: &Node, tag: &str) -> Option<Node> {
|
||||
for child in node.get_child_elements() {
|
||||
if child.get_name().to_uppercase() == tag {
|
||||
return Some(child);
|
||||
} else if let Some(node) = get_elems(&child, tag) {
|
||||
return Some(node);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
get_elems(node, &tag)
|
||||
}
|
||||
|
||||
pub fn get_link_density(node: &Node) -> f64 {
|
||||
let text_length = Util::get_inner_text(node, true).len();
|
||||
if text_length == 0 {
|
||||
|
@ -611,6 +655,10 @@ impl Util {
|
|||
nodes.append(&mut Util::get_elements_by_tag_name(root, "h2"));
|
||||
|
||||
for mut node in nodes.into_iter().rev() {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if Util::get_class_weight(&node) < 0 {
|
||||
log::debug!(
|
||||
"Removing header with low class weight: {} {}",
|
||||
|
@ -634,6 +682,33 @@ impl Util {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn replace_emoji_images(root: &Node, document: &Document) {
|
||||
let img_nodes = Util::get_elements_by_tag_name(root, "img");
|
||||
|
||||
for img_node in img_nodes {
|
||||
if let Some(img_alt) = img_node.get_attribute("alt") {
|
||||
if Self::is_emoji(&img_alt) {
|
||||
if let Some(mut parent) = img_node.get_parent() {
|
||||
let emoji_text_node = Node::new_text(&img_alt, document).unwrap();
|
||||
_ = parent.replace_child_node(emoji_text_node, img_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_emoji(text: &str) -> bool {
|
||||
let mut alt_chars = text.chars();
|
||||
let first_char = alt_chars.next();
|
||||
let second_char = alt_chars.next();
|
||||
|
||||
if let (Some(char), None) = (first_char, second_char) {
|
||||
unic_emoji_char::is_emoji(char)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Clean an element of all tags of type "tag" if they look fishy.
|
||||
// "Fishy" is an algorithm based on content length, classnames, link density, number of images & embeds, etc.
|
||||
pub fn clean_conditionally(root: &mut Node, tag: &str) {
|
||||
|
@ -645,6 +720,10 @@ impl Util {
|
|||
let nodes = Util::get_elements_by_tag_name(root, tag);
|
||||
|
||||
for mut node in nodes.into_iter().rev() {
|
||||
if node.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if Self::should_remove(&node, tag) {
|
||||
node.unlink();
|
||||
}
|
||||
|
@ -708,11 +787,6 @@ impl Util {
|
|||
}
|
||||
}
|
||||
|
||||
// For embed with <object> tag, check inner HTML as well.
|
||||
// if embed_node.get_name().to_lowercase() == "object" && constants::VIDEOS.is_match(embed_node.innerHTML) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
embed_count += 1;
|
||||
}
|
||||
}
|
||||
|
@ -725,8 +799,9 @@ impl Util {
|
|||
|
||||
let image_obj_count = Util::get_elements_by_tag_name(node, "imageobject").len();
|
||||
let video_obj_count = Util::get_elements_by_tag_name(node, "videoobject").len();
|
||||
let video_tag_count = Util::get_elements_by_tag_name(node, "video").len();
|
||||
|
||||
if image_obj_count > 0 || video_obj_count > 0 {
|
||||
if image_obj_count > 0 || video_obj_count > 0 || video_tag_count > 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -946,6 +1021,10 @@ impl Util {
|
|||
// or non-whitespace. This leaves behind the first <br> in the chain
|
||||
// (which will be replaced with a <p> later).
|
||||
while let Some(mut n) = next {
|
||||
if n.is_null() {
|
||||
break;
|
||||
}
|
||||
|
||||
let is_text_whitespace = n
|
||||
.get_type()
|
||||
.map(|t| t == NodeType::TextNode)
|
||||
|
@ -986,6 +1065,10 @@ impl Util {
|
|||
next = p.get_next_sibling();
|
||||
|
||||
while let Some(mut next_node) = next {
|
||||
if next_node.is_null() {
|
||||
break;
|
||||
}
|
||||
|
||||
// If we've hit another <br><br>, we're done adding children to this <p>.
|
||||
if next_node.get_name().to_uppercase() == "BR" {
|
||||
if let Some(next_elem) = next_node.get_next_element_sibling() {
|
||||
|
@ -1013,6 +1096,10 @@ impl Util {
|
|||
}
|
||||
|
||||
while let Some(mut last_child) = p.get_last_child() {
|
||||
if last_child.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let is_text_node = last_child
|
||||
.get_type()
|
||||
.map(|t| t == NodeType::TextNode)
|
||||
|
@ -1033,19 +1120,190 @@ impl Util {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn score_image_url(url: &str) -> i32 {
|
||||
let url = url.trim();
|
||||
let mut score = 0;
|
||||
|
||||
if constants::POSITIVE_LEAD_IMAGE_URL_HINTS_REGEX.is_match(url) {
|
||||
score += 20;
|
||||
}
|
||||
|
||||
if NEGATIVE_LEAD_IMAGE_URL_HINTS_REGEX.is_match(url) {
|
||||
score -= 20;
|
||||
}
|
||||
|
||||
// TODO: We might want to consider removing this as
|
||||
// gifs are much more common/popular than they once were
|
||||
if constants::GIF_REGEX.is_match(url) {
|
||||
score -= 10;
|
||||
}
|
||||
|
||||
if constants::JPG_REGEX.is_match(url) {
|
||||
score += 10;
|
||||
}
|
||||
|
||||
// PNGs are neutral.
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
// Alt attribute usually means non-presentational image.
|
||||
pub fn score_img_attr(img: &Node) -> i32 {
|
||||
if img.get_attribute("alt").is_some() {
|
||||
5
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// Look through our parent and grandparent for figure-like
|
||||
// container elements, give a bonus if we find them
|
||||
pub fn score_by_parents(img: &Node) -> i32 {
|
||||
let mut score = 0;
|
||||
let parent = img.get_parent();
|
||||
let grand_parent = parent.as_ref().and_then(|n| n.get_parent());
|
||||
if Self::has_tag_name(parent.as_ref(), "figure")
|
||||
|| Self::has_tag_name(grand_parent.as_ref(), "figure")
|
||||
{
|
||||
score += 25;
|
||||
}
|
||||
|
||||
if let Some(parent) = parent.as_ref() {
|
||||
let signature = Util::get_signature(parent);
|
||||
if constants::PHOTO_HINTS_REGEX.is_match(&signature) {
|
||||
score += 15;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(grand_parent) = grand_parent.as_ref() {
|
||||
let signature = Util::get_signature(grand_parent);
|
||||
if constants::PHOTO_HINTS_REGEX.is_match(&signature) {
|
||||
score += 15;
|
||||
}
|
||||
}
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
// Look at our immediate sibling and see if it looks like it's a
|
||||
// caption. Bonus if so.
|
||||
pub fn score_by_sibling(img: &Node) -> i32 {
|
||||
let mut score = 0;
|
||||
let sibling = img.get_next_element_sibling();
|
||||
|
||||
if let Some(sibling) = sibling.as_ref() {
|
||||
if sibling.get_name().to_lowercase() == "figcaption" {
|
||||
score += 25;
|
||||
}
|
||||
|
||||
let signature = Util::get_signature(sibling);
|
||||
if constants::PHOTO_HINTS_REGEX.is_match(&signature) {
|
||||
score += 15;
|
||||
}
|
||||
}
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
pub fn score_by_dimensions(img: &Node) -> i32 {
|
||||
let mut score = 0;
|
||||
|
||||
let width = img
|
||||
.get_attribute("width")
|
||||
.and_then(|w| w.parse::<f32>().ok());
|
||||
let height = img
|
||||
.get_attribute("height")
|
||||
.and_then(|w| w.parse::<f32>().ok());
|
||||
let src = img.get_attribute("src").unwrap_or_default();
|
||||
|
||||
// Penalty for skinny images
|
||||
if let Some(width) = width {
|
||||
if width <= 50.0 {
|
||||
score -= 50;
|
||||
}
|
||||
}
|
||||
|
||||
// Penalty for short images
|
||||
if let Some(height) = height {
|
||||
if height <= 50.0 {
|
||||
score -= 50;
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(width), Some(height)) = (width, height) {
|
||||
if !src.contains("sprite") {
|
||||
let area = width * height;
|
||||
if area < 5000.0 {
|
||||
// Smaller than 50 x 100
|
||||
score -= 100;
|
||||
} else {
|
||||
score += f32::round(area / 1000.0) as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
pub fn score_by_position(len: usize, index: usize) -> i32 {
|
||||
((len as f32 / 2.0) - index as f32) as i32
|
||||
}
|
||||
|
||||
pub fn score_by_alt(node: &Node) -> i32 {
|
||||
if let Some(alt) = node.get_attribute("alt") {
|
||||
if Self::is_emoji(&alt) {
|
||||
-100
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_content_length(response: &Response) -> Result<usize, ImageDownloadError> {
|
||||
let status_code = response.status();
|
||||
|
||||
if !status_code.is_success() {
|
||||
log::warn!("response: {status_code} ({})", response.url());
|
||||
return Err(ImageDownloadError::Http);
|
||||
}
|
||||
|
||||
response
|
||||
.headers()
|
||||
.get(CONTENT_LENGTH)
|
||||
.and_then(|content_length| content_length.to_str().ok())
|
||||
.and_then(|content_length| content_length.parse::<usize>().ok())
|
||||
.ok_or(ImageDownloadError::ContentLength)
|
||||
}
|
||||
|
||||
pub fn get_content_type(response: &Response) -> Result<String, ImageDownloadError> {
|
||||
let status_code = response.status();
|
||||
|
||||
if !status_code.is_success() {
|
||||
log::warn!("response: {status_code} ({})", response.url());
|
||||
return Err(ImageDownloadError::Http);
|
||||
}
|
||||
|
||||
response
|
||||
.headers()
|
||||
.get(CONTENT_TYPE)
|
||||
.and_then(|val| val.to_str().ok())
|
||||
.map(|val| val.to_string())
|
||||
.ok_or(ImageDownloadError::ContentType)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use libxml::parser::Parser;
|
||||
|
||||
use super::Util;
|
||||
use crate::FullTextParser;
|
||||
|
||||
fn replace_brs(source: &str, expected: &str) {
|
||||
libxml::tree::node::set_node_rc_guard(10);
|
||||
|
||||
let parser = Parser::default_html();
|
||||
let document = parser.parse_string(source).unwrap();
|
||||
let document = FullTextParser::parse_html_string_patched(source).unwrap();
|
||||
let root = document.get_root_element().unwrap();
|
||||
let body = root.get_first_child().unwrap();
|
||||
let div = body.get_first_child().unwrap();
|
||||
|
@ -1082,4 +1340,35 @@ mod tests {
|
|||
"#;
|
||||
replace_brs(source, source.trim())
|
||||
}
|
||||
|
||||
fn replace_emojis(source: &str, expected: &str) {
|
||||
libxml::tree::node::set_node_rc_guard(10);
|
||||
|
||||
let document = FullTextParser::parse_html_string_patched(source).unwrap();
|
||||
let root = document.get_root_element().unwrap();
|
||||
let body = root.get_first_child().unwrap();
|
||||
let p = body.get_first_child().unwrap();
|
||||
|
||||
Util::replace_emoji_images(&root, &document);
|
||||
|
||||
let result = document.node_to_string(&p);
|
||||
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_emojis_1() {
|
||||
replace_emojis(
|
||||
"<p>Let’s see if I did a better job of it this time by telling him he was using Arch wrong. <img src=\"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f600.png\" alt=\"😀\"/></p>",
|
||||
"<p>Let’s see if I did a better job of it this time by telling him he was using Arch wrong. 😀</p>",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_emojis_2() {
|
||||
replace_emojis(
|
||||
"<p><img src=\"https://abc.com/img.jpeg\"/><img src=\"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f600.png\" alt=\"😀\"/> Abc</p>",
|
||||
"<p><img src=\"https://abc.com/img.jpeg\"/>😀 Abc</p>",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,10 @@ impl VideoObject {
|
|||
}
|
||||
|
||||
pub fn replace(&self, node: &mut Node) -> Result<(), FullTextParserError> {
|
||||
if node.is_null() {
|
||||
return Err(FullTextParserError::Xml);
|
||||
}
|
||||
|
||||
let mut parent = node.get_parent().ok_or(FullTextParserError::Xml)?;
|
||||
node.unlink();
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
[package]
|
||||
name = "article_scraper_cli"
|
||||
version = "2.0.0-alpha.0"
|
||||
authors = ["Jan Lukas Gernert <jangernert@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later"
|
||||
description = "Cli to use the article_scraper lib"
|
||||
repository = "https://gitlab.com/news-flash/article_scraper"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
|
||||
[dependencies]
|
||||
article_scraper = { path = "../article_scraper/" }
|
||||
clap = { version = "4.2", features = [ "derive" ] }
|
||||
clap = { version = "4.5", features = [ "derive" ] }
|
||||
simplelog = "0.12"
|
||||
log = "0.4"
|
||||
url = "2.3"
|
||||
reqwest = { version = "0.11", features = ["json", "native-tls", "gzip", "brotli", "stream"] }
|
||||
tokio = { version = "1.27", features = ["macros", "fs", "io-util", "rt-multi-thread" ] }
|
||||
url = "2.5"
|
||||
reqwest = { version = "0.12", features = ["json", "native-tls", "gzip", "brotli", "stream"] }
|
||||
tokio = { version = "1", features = ["macros", "fs", "io-util", "rt-multi-thread" ] }
|
||||
indicatif = "0.17"
|
Loading…
Add table
Add a link
Reference in a new issue