Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions docs/supported_publishers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2766,6 +2766,44 @@
</table>


## SE-Publishers

<table class="publishers se">
<thead>
<tr>
<th>Class&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</th>
<th>Name&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</th>
<th>URL&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</th>
<th>Languages</th>
<th>Missing&#160;Attributes</th>
<th>Deprecated&#160;Attributes</th>
<th>Additional&#160;Attributes&#160;&#160;&#160;&#160;</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>Aftonbladet</code>
</td>
<td>
<div>Aftonbladet</div>
</td>
<td>
<a href="https://www.aftonbladet.se/">
<span>www.aftonbladet.se</span>
</a>
</td>
<td>
<code>se</code>
</td>
<td>&#160;</td>
<td>&#160;</td>
<td>&#160;</td>
</tr>
</tbody>
</table>


## TR-Publishers

<table class="publishers tr">
Expand Down
2 changes: 2 additions & 0 deletions src/fundus/publishers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from fundus.publishers.pt import PT
from fundus.publishers.py import PY
from fundus.publishers.ru import RU
from fundus.publishers.se import SE
from fundus.publishers.tr import TR
from fundus.publishers.tw import TW
from fundus.publishers.tz import TZ
Expand Down Expand Up @@ -101,6 +102,7 @@ class PublisherCollection(metaclass=PublisherCollectionMeta):
pt = PT
py = PY
ru = RU
se = SE
tr = TR
tw = TW
tz = TZ
Expand Down
22 changes: 22 additions & 0 deletions src/fundus/publishers/se/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from fundus.publishers.base_objects import Publisher, PublisherGroup
from fundus.scraping.filter import inverse, regex_filter
from fundus.scraping.url import Sitemap

from .aftonbladet import AftonbladetParser


class SE(metaclass=PublisherGroup):
default_language = "se"

Aftonbladet = Publisher(
name="Aftonbladet",
domain="https://www.aftonbladet.se/",
parser=AftonbladetParser,
sources=[
Sitemap(
"https://www.aftonbladet.se/sitemap.xml",
sitemap_filter=inverse(regex_filter("articles.xml")),
reverse=True,
),
],
)
49 changes: 49 additions & 0 deletions src/fundus/publishers/se/aftonbladet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from datetime import datetime
from typing import List, Optional

from lxml.etree import XPath

from fundus.parser import ArticleBody, BaseParser, Image, ParserProxy, attribute
from fundus.parser.utility import (
extract_article_body_with_selector,
generic_author_parsing,
generic_date_parsing,
generic_topic_parsing,
image_extraction,
)


class AftonbladetParser(ParserProxy):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're a bit in a special situation here. It seems as if the publisher did not implement the isAccessibleForFree attribute here, which is the default handling of the free_access attribute. You would need to find a custom implementation for this publisher. Example: https://www.aftonbladet.se/bil/a/bmRM95/privatleasade-audi-som-gick-sonder-far-betala-manadsavgift, this article is marked as free to access.

class V1(BaseParser):
_summary_selector = XPath("//p[contains(@data-test-tag,'lead-text')]")
_paragraph_selector = XPath(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"//p[starts-with(@class,'hyperion-css-') and not(contains(@data-test-tag,'lead-text'))]"
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


@attribute
def title(self) -> Optional[str]:
return self.precomputed.meta.get("og:title")

@attribute
def body(self) -> Optional[ArticleBody]:
return extract_article_body_with_selector(
self.precomputed.doc,
summary_selector=self._summary_selector,
paragraph_selector=self._paragraph_selector,
)

@attribute
def authors(self) -> List[str]:
return generic_author_parsing(self.precomputed.ld.bf_search("author"))

@attribute
def publishing_date(self) -> Optional[datetime]:
return generic_date_parsing(self.precomputed.meta["article:published_time"])

@attribute
def topics(self) -> List[str]:
return generic_topic_parsing(self.precomputed.ld.bf_search("keywords"))

@attribute
def images(self) -> List[Image]:
return image_extraction(doc=self.precomputed.doc, paragraph_selector=self._paragraph_selector)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

237 changes: 237 additions & 0 deletions tests/resources/parser/test_data/se/Aftonbladet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
{
"V1": {
"authors": [
"Peter Kadhammar"
],
"body": {
"summary": [],
"sections": [
{
"headline": [],
"paragraphs": [
"Centerpartiets ledare avgår med hänvisning till hot och hat och hela Sverige ropar med en röst:",
"Demokratin i fara!",
"Hatet får inte segra!",
"Aldrig är vi så nöjda som när det finns en enkel, svartvit fråga som alla kan enas om. Jag bläddrar i de digitala arkiven och finner en vulkan av harm och gråtmildhet:",
"Tragiskt för svensk demokrati",
"Det borde vara nog nu",
"Debattklimatet hotar vår demokrati",
"Hennes tårar är allas våra tårar",
"Något raseras just nu i vårt land",
"När hatet blir vardag dör demokratin",
"Dags att vara snälla mot varandra",
"Hundratusentals ord har redan ägnats Anna-Karin Hatts plötsliga avgång. Men ingen blir ett dyft klokare av alla dessa eruptioner som alla säger samma sak, att demokrati är bra och hat och hot är dåligt.",
"De närmaste dagarna och veckorna kommer nationens mediekonsumenter att tvångsmatas med fler honnörsord tills vi blir spyfärdiga.",
"Ulf Kristersson kommer att knata omkring och se sårad ut därför att Nooshi Dadgostar avbröt sin motståndare i en tv-debatt. Hon borde få mikrofonen avstängd, tycker han, och i den allmänna upprördheten geggas en hård partiledardebatt och en skenande vänsterledare ihop med hot, som är ett lagbrott.",
"Magdalena Andersson kommer även fortsättningsvis att vara bister och iklä sig rollen som blivande landsmoder.",
"Jimmie Åkesson kommer som vanligt att spela offer trots att hans eget parti förra året avslöjades med att driva trollfabrik på nätet och där hans egen kommunikationschef Joakim Wallerstein utfärdade order till de digitala trupperna att ge sig på kristdemokraten Alice Teodorescu Måwe:",
"”Det skulle vara bra om vi kan gå igenom vad man kan hitta för skit på Alice. Varför vi tycker att hon är en sopa.”",
"Den offentliga upprördheten är synnerligen berättigad. Det är skandal att en partiledare avgår efter hot. Det är verkligen fara för folkväldet att politiskt aktiva på alla nivåer drar sig för att ta förtroendeposter.",
"En skrämmande passivitet har brett ut sig. För 20 år sedan var 20 procent av väljarna medlemmar i riksdagspartierna, i dag 2,5 procent, skrev Olle Wästberg i sin bok ”Den hotade demokratin”. Han var ordförande i 2014 års statliga demokratiutredning.",
"Den överväldigande delen av förstagångsväljarna det året hade Facebook som främsta informationskälla.",
"Inför valet nästa år antar jag att Tiktok kommer att vara viktigaste nyhetskällan för unga vuxna.",
"Det groteska med Anna-Karin Hatts plötsliga avgång är att den på samma gång behandlas som av yttersta vikt för statens och samhällets framtid – och samtidigt som en privatsak för Hatt.",
"– Det är en samlad bedömning som jag gjort om den samlade situationen det innebär för mig att leva som partiledare i en väldigt hätsk samhällsdebatt med återkommande hat och hot, sa Hatt på sin presskonferens.",
"Partistyrelsen hade fått beskedet bara 45 minuter i förväg, skriver DN. Alla var chockade. Sedan chockades hela Sverige.",
"Men Anna-Karin Hatts snömos hjälper oss inte framåt. Vilka hot är det hon talar om?",
"Det är ju allvarliga brott som i det här fallet har fått extrema konsekvenser. Hot mot en partiledare är ingen privatsak, inte hatkampanjer heller.",
"Av Hatts sätt att uttrycka sig kan man ana att hennes familj blivit utsatt. Barn? Jag vet inte. Ingen kan begära att hon offentligt ska berätta om saker som berör de närmaste.",
"Men vi kan begära att partiledarna informeras, och Säpo.",
"Och vi kan begära att Säpo lämnar någon slags redovisning. Finns det kampanjer som kan spåras till främmande makt? Sverigedemokraternas trollfabrik? Privatpersoner? Vilka mönster kan man finna i haten och hoten?",
"Anna-Karin Hatts sorti är alldeles för viktig för att den ska rinna ut i den vanliga störtfloden av indignation och sentimentalitet, som strax torkar och glöms.",
"Verkligheten är konkret och därmed möjlig att hantera.",
"Det är dags att dra ut dem i ljuset – hatets och illviljans kolportörer. För att låna ett uttryck av Olof Palme."
]
}
]
},
"images": [
{
"versions": [
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=67&q=50&w=100&s=2ecbd3499150a9cfe829a3cd3cb3d1e92f3ec7a9",
"query_width": null,
"size": {
"width": 100,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=133&q=50&w=200&s=f880a2d28cbc7b0bda059a968079ca64a2a0750c",
"query_width": null,
"size": {
"width": 200,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=200&q=50&w=300&s=c25e2014360c555a203d26cee8552a458590ae8e",
"query_width": null,
"size": {
"width": 300,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=267&q=50&w=400&s=7079a9c5564a8906925e538759cf68975f365532",
"query_width": null,
"size": {
"width": 400,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=333&q=50&w=500&s=152690308773a12d9a0f0761607ad22fefffb757",
"query_width": null,
"size": {
"width": 500,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=400&q=50&w=600&s=6b17b4b6a56a0775feaebdca60c50af74c31b4e2",
"query_width": null,
"size": {
"width": 600,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=467&q=50&w=700&s=205565d26142ac703c83a4cb3fbab7d8b99db222",
"query_width": null,
"size": {
"width": 700,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=533&q=50&w=800&s=2f35d66a8f9274afaf9dbeeb070ef4c68dc7636d",
"query_width": null,
"size": {
"width": 800,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=600&q=50&w=900&s=d3e71bd233281b9018338dec52083f03b95fd0dc",
"query_width": null,
"size": {
"width": 900,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=667&q=50&w=1000&s=44187b1e958ec9f9f7e4619b788d29ff4a8abced",
"query_width": null,
"size": {
"width": 1000,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=733&q=50&w=1100&s=01f80b8cd95b82920d56c55b9822c015de19d511",
"query_width": null,
"size": {
"width": 1100,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=800&q=50&w=1200&s=e9ad385944ca048a88030d4171e06c36bd8ae854",
"query_width": null,
"size": {
"width": 1200,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=867&q=50&w=1300&s=1c19c9e97be4c71a36463b69b23ce6c760aa09db",
"query_width": null,
"size": {
"width": 1300,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=933&q=50&w=1400&s=97a956c7ecc1c97a4ea93908aa89e22f1066d4c4",
"query_width": null,
"size": {
"width": 1400,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=1000&q=50&w=1500&s=77e600666f53698924e5b09b9c647adde472ffa5",
"query_width": null,
"size": {
"width": 1500,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=1067&q=50&w=1600&s=a5240e4ef0c05e08c421b648214e9ad3e04cff68",
"query_width": null,
"size": {
"width": 1600,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=1133&q=50&w=1700&s=325fd45525b62a96cf5ac8df0b578aaf0956ffce",
"query_width": null,
"size": {
"width": 1700,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=1200&q=50&w=1800&s=c5934a43af7eabbc95620a3137201267ddc90806",
"query_width": null,
"size": {
"width": 1800,
"height": 0
},
"type": null
},
{
"url": "https://images.aftonbladet-cdn.se/v2/images/43ec0289-f486-4ffc-9d96-63b8c6421104?fit=crop&format=auto&h=1267&q=50&w=1900&s=5369685bd86f5171772bf815fac90cd571a0c0ae",
"query_width": null,
"size": {
"width": 1900,
"height": 0
},
"type": null
}
],
"is_cover": true,
"description": "Hundratusentals ord har redan ägnats Anna-Karin Hatts plötsliga avgång.",
"caption": "Hundratusentals ord har redan ägnats Anna-Karin Hatts plötsliga avgång. Foto: Lotte Fernvall",
"authors": [],
"position": 250
}
],
"publishing_date": "2025-10-22 03:54:49+00:00",
"title": "Hatt kan inte behandla hoten som sin privatsak",
"topics": [
"anna-karin hatt",
"ulf kristersson"
]
}
}
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/resources/parser/test_data/se/meta.info
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"Aftonbladet_2025_10_22.html.gz": {
"url": "https://www.aftonbladet.se/nyheter/kolumnister/a/QMny8A/hoten-mot-anna-karin-hatt-maste-ut-i-offentligheten",
"crawl_date": "2025-10-22 15:01:30.876352"
}
}