Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the METAREFRESH_IGNORE_TAGS setting #3768

Merged
merged 1 commit into from Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/topics/downloader-middleware.rst
Expand Up @@ -805,6 +805,7 @@ The :class:`MetaRefreshMiddleware` can be configured through the following
settings (see the settings documentation for more info):

* :setting:`METAREFRESH_ENABLED`
* :setting:`METAREFRESH_IGNORE_TAGS`
* :setting:`METAREFRESH_MAXDELAY`

This middleware obey :setting:`REDIRECT_MAX_TIMES` setting, :reqmeta:`dont_redirect`,
Expand All @@ -826,6 +827,15 @@ Default: ``True``

Whether the Meta Refresh middleware will be enabled.

.. setting:: METAREFRESH_IGNORE_TAGS

METAREFRESH_IGNORE_TAGS
^^^^^^^^^^^^^^^^^^^^^^^

Default: ``['script', 'noscript']``

Meta tags within these tags are ignored.

.. setting:: METAREFRESH_MAXDELAY

METAREFRESH_MAXDELAY
Expand Down
4 changes: 3 additions & 1 deletion scrapy/downloadermiddlewares/redirect.py
Expand Up @@ -88,6 +88,7 @@ class MetaRefreshMiddleware(BaseRedirectMiddleware):

def __init__(self, settings):
super(MetaRefreshMiddleware, self).__init__(settings)
self._ignore_tags = settings.getlist('METAREFRESH_IGNORE_TAGS')
self._maxdelay = settings.getint('REDIRECT_MAX_METAREFRESH_DELAY',
settings.getint('METAREFRESH_MAXDELAY'))

Expand All @@ -96,7 +97,8 @@ def process_response(self, request, response, spider):
not isinstance(response, HtmlResponse):
return response

interval, url = get_meta_refresh(response)
interval, url = get_meta_refresh(response,
ignore_tags=self._ignore_tags)
if url and interval < self._maxdelay:
redirected = self._redirect_request_using_get(request, url)
return self._redirect(redirected, request, spider, 'meta refresh')
Expand Down
1 change: 1 addition & 0 deletions scrapy/settings/default_settings.py
Expand Up @@ -221,6 +221,7 @@
MEMUSAGE_WARNING_MB = 0

METAREFRESH_ENABLED = True
METAREFRESH_IGNORE_TAGS = ['script', 'noscript']
METAREFRESH_MAXDELAY = 100

NEWSPIDER_MODULE = ''
Expand Down
4 changes: 2 additions & 2 deletions scrapy/utils/response.py
Expand Up @@ -31,12 +31,12 @@ def get_base_url(response):


_metaref_cache = weakref.WeakKeyDictionary()
def get_meta_refresh(response):
def get_meta_refresh(response, ignore_tags=('script', 'noscript')):
"""Parse the http-equiv refrsh parameter from the given response"""
if response not in _metaref_cache:
text = response.text[0:4096]
_metaref_cache[response] = html.get_meta_refresh(text, response.url,
response.encoding, ignore_tags=('script', 'noscript'))
response.encoding, ignore_tags=ignore_tags)
return _metaref_cache[response]


Expand Down
19 changes: 19 additions & 0 deletions tests/test_downloadermiddleware_redirect.py
Expand Up @@ -279,5 +279,24 @@ def test_redirect_reasons(self):
self.assertEqual(req2.meta['redirect_reasons'], ['meta refresh'])
self.assertEqual(req3.meta['redirect_reasons'], ['meta refresh', 'meta refresh'])

def test_ignore_tags_default(self):
req = Request(url='http://example.org')
body = ('''<noscript><meta http-equiv="refresh" '''
'''content="0;URL='http://example.org/newpage'"></noscript>''')
rsp = HtmlResponse(req.url, body=body.encode())
response = self.mw.process_response(req, rsp, self.spider)
assert isinstance(response, Response)

def test_ignore_tags_empty_list(self):
crawler = get_crawler(Spider, {'METAREFRESH_IGNORE_TAGS': []})
mw = MetaRefreshMiddleware.from_crawler(crawler)
req = Request(url='http://example.org')
body = ('''<noscript><meta http-equiv="refresh" '''
'''content="0;URL='http://example.org/newpage'"></noscript>''')
rsp = HtmlResponse(req.url, body=body.encode())
req2 = mw.process_response(req, rsp, self.spider)
assert isinstance(req2, Request)
self.assertEqual(req2.url, 'http://example.org/newpage')

if __name__ == "__main__":
unittest.main()