openeduhub / metalookup

Provide metadata about domains w.r.t accessibility, licencing, adds, etc.
GNU General Public License v3.0
5 stars 0 forks source link

Adblock based extractor does not consider the resource types. #165

Open MRuecklCC opened 2 years ago

MRuecklCC commented 2 years ago

Currently, the abblock based extractors use the following configuration for all links that are checked:

    self.adblock_parser_options = {
            "script": True,
            "image": True,
            "stylesheet": True,
            "object": True,
            "xmlhttprequest": True,
            "object-subrequest": True,
            "subdocument": True,
            "document": True,
            "elemhide": True,
            "other": True,
            "background": True,
            "xbl": True,
            "ping": True,
            "dtd": True,
            "media": True,
            "third-party": True,
            "match-case": True,
            "collapse": True,
            "donottrack": True,
            "websocket": True,
            # "domain" key must be populated on use
        }

This means, that the following content/filter combination results in wrong matches of the filter rules:

content = "<img href='https://some-domain.com/ads/123.jpg'></a>"
filters = ["/ads/*$script"]

I would expect this not to block the image, because the filter should only apply to script blocks. However, the current implementation throws all links into one bucket and via the configuration interprets them as "all different resource types at the same time".

Looking at the alternative adblock python package (based on rust implementation):

The filter engine API here expects the resource type (sort of a context in which the link appears) as additional argument.

MRuecklCC commented 2 years ago

See https://adblockplus.org/filter-cheatsheet for explanation of filter rule syntax

MRuecklCC commented 2 years ago

After a little bit of research... There are two different approaches:

In the second approach, it may also be possible to drastically reduce the playwright page load time (while still tracking which request were blocked) which would also be beneficial for the user - because extraction is potentially faster.

MRuecklCC commented 2 years ago

The current implementation should also allow a quick fix. It already tracks the issued requests:

 # from content.py
...
        async def _task():
            with runtime() as t:
                async with async_playwright() as p:
                    self._responses = []
                    self._requests = []
                    browser = await p.chromium.connect_over_cdp(endpoint_url=PLAYWRIGHT_WS_ENDPOINT)
                    page = await browser.new_page()

                    async def on_request(request: Request):
                        self._requests.append(request)
                        await request.all_headers()
...

This means, instead of analyzing the content.raw_links, we could also analyze the content.requests which each contain the requested url and the resource type. I.e. we could in hindsight decide whether the request should have been blocked.

MRuecklCC commented 2 years ago

See #166 for more discussion on the adblocking topic.