diff --git a/scrapy/utils/url.py b/scrapy/utils/url.py
index c80fc6e70..406eb5843 100644
--- a/scrapy/utils/url.py
+++ b/scrapy/utils/url.py
@@ -41,9 +41,16 @@ def url_has_any_extension(url, extensions):
 
 
 def _safe_ParseResult(parts, encoding='utf8', path_encoding='utf8'):
+    # IDNA encoding can fail for too long labels (>63 characters)
+    # or missing labels (e.g. http://.example.com)
+    try:
+        netloc = parts.netloc.encode('idna')
+    except UnicodeError:
+        netloc = parts.netloc
+
     return (
         to_native_str(parts.scheme),
-        to_native_str(parts.netloc.encode('idna')),
+        to_native_str(netloc),
 
         # default encoding for path component SHOULD be UTF-8
         quote(to_bytes(parts.path, path_encoding), _safe_chars),

Unicode Link Extractor
When using the following to extract all of the links from a response:
```
self.link_extractor = LinkExtractor()
...
links = self.link_extractor.extract_links(response)
```

On rare occasions, the following error is thrown:

```
2016-05-25 12:13:55,432 [root] [ERROR]  Error on http://detroit.curbed.com/2016/5/5/11605132/tiny-house-designer-show, traceback: Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1203, in mainLoop
    self.runUntilCurrent()
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 825, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 393, in callback
    self._startRunCallbacks(result)
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 501, in _startRunCallbacks
    self._runCallbacks()
--- <exception caught here> ---
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "/var/www/html/DomainCrawler/DomainCrawler/spiders/hybrid_spider.py", line 223, in parse
    items.extend(self._extract_requests(response))
  File "/var/www/html/DomainCrawler/DomainCrawler/spiders/hybrid_spider.py", line 477, in _extract_requests
    links = self.link_extractor.extract_links(response)
  File "/usr/local/lib/python2.7/site-packages/scrapy/linkextractors/lxmlhtml.py", line 111, in extract_links
    all_links.extend(self._process_links(links))
  File "/usr/local/lib/python2.7/site-packages/scrapy/linkextractors/__init__.py", line 103, in _process_links
    link.url = canonicalize_url(urlparse(link.url))
  File "/usr/local/lib/python2.7/site-packages/scrapy/utils/url.py", line 85, in canonicalize_url
    parse_url(url), encoding=encoding)
  File "/usr/local/lib/python2.7/site-packages/scrapy/utils/url.py", line 46, in _safe_ParseResult
    to_native_str(parts.netloc.encode('idna')),
  File "/usr/local/lib/python2.7/encodings/idna.py", line 164, in encode
    result.append(ToASCII(label))
  File "/usr/local/lib/python2.7/encodings/idna.py", line 73, in ToASCII
    raise UnicodeError("label empty or too long")
exceptions.UnicodeError: label empty or too long
```

I was able to find some information concerning the error from [here](http://stackoverflow.com/questions/25103126/label-empty-or-too-long-python-urllib2).
My question is: What is the best way to handle this? Even if there is one bad link in the response, I'd want all of the other good links to be extracted.
diff --git a/tests/test_utils_url.py b/tests/test_utils_url.py
index 1fc3a3510..b4819874d 100644
--- a/tests/test_utils_url.py
+++ b/tests/test_utils_url.py
@@ -265,6 +265,20 @@ class CanonicalizeUrlTest(unittest.TestCase):
             # without encoding, already canonicalized URL is canonicalized identically
             self.assertEqual(canonicalize_url(canonicalized), canonicalized)
 
+    def test_canonicalize_url_idna_exceptions(self):
+        # missing DNS label
+        self.assertEqual(
+            canonicalize_url(u"http://.example.com/résumé?q=résumé"),
+            "http://.example.com/r%C3%A9sum%C3%A9?q=r%C3%A9sum%C3%A9")
+
+        # DNS label too long
+        self.assertEqual(
+            canonicalize_url(
+                u"http://www.{label}.com/résumé?q=résumé".format(
+                    label=u"example"*11)),
+            "http://www.{label}.com/r%C3%A9sum%C3%A9?q=r%C3%A9sum%C3%A9".format(
+                    label=u"example"*11))
+
 
 class AddHttpIfNoScheme(unittest.TestCase):
 

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
3.5
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
Automat==22.10.0
certifi==2021.5.30
cffi==1.15.1
constantly==15.1.0
cryptography==40.0.2
cssselect==1.1.0
hyperlink==21.0.0
idna==3.10
importlib-metadata==4.8.3
incremental==22.10.0
iniconfig==1.1.1
lxml==5.3.1
packaging==21.3
parsel==1.6.0
pluggy==1.0.0
py==1.11.0
pyasn1==0.5.1
pyasn1-modules==0.3.0
pycparser==2.21
PyDispatcher==2.0.7
pyOpenSSL==23.2.0
pyparsing==3.1.4
pytest==7.0.1
queuelib==1.6.2
-e git+https://github.com/scrapy/scrapy.git@b7925e42202d79d2ba9d00b6aded3a451c92fe81#egg=Scrapy
service-identity==21.1.0
six==1.17.0
tomli==1.2.3
Twisted==22.4.0
typing_extensions==4.1.1
w3lib==2.0.1
zipp==3.6.0
zope.interface==5.5.2

name: scrapy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - automat==22.10.0
      - cffi==1.15.1
      - constantly==15.1.0
      - cryptography==40.0.2
      - cssselect==1.1.0
      - hyperlink==21.0.0
      - idna==3.10
      - importlib-metadata==4.8.3
      - incremental==22.10.0
      - iniconfig==1.1.1
      - lxml==5.3.1
      - packaging==21.3
      - parsel==1.6.0
      - pluggy==1.0.0
      - py==1.11.0
      - pyasn1==0.5.1
      - pyasn1-modules==0.3.0
      - pycparser==2.21
      - pydispatcher==2.0.7
      - pyopenssl==23.2.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - queuelib==1.6.2
      - service-identity==21.1.0
      - six==1.17.0
      - tomli==1.2.3
      - twisted==22.4.0
      - typing-extensions==4.1.1
      - w3lib==2.0.1
      - zipp==3.6.0
      - zope-interface==5.5.2
prefix: /opt/conda/envs/scrapy

tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url_idna_exceptions
tests/test_utils_url.py::UrlUtilsTest::test_url_is_from_any_domain tests/test_utils_url.py::UrlUtilsTest::test_url_is_from_spider tests/test_utils_url.py::UrlUtilsTest::test_url_is_from_spider_class_attributes tests/test_utils_url.py::UrlUtilsTest::test_url_is_from_spider_with_allowed_domains tests/test_utils_url.py::UrlUtilsTest::test_url_is_from_spider_with_allowed_domains_class_attributes tests/test_utils_url.py::CanonicalizeUrlTest::test_append_missing_path tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_idns tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_parse_url tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url_idempotence tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url_unicode_path tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url_unicode_query_string tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_url_unicode_query_string_wrong_encoding tests/test_utils_url.py::CanonicalizeUrlTest::test_canonicalize_urlparsed tests/test_utils_url.py::CanonicalizeUrlTest::test_domains_are_case_insensitive tests/test_utils_url.py::CanonicalizeUrlTest::test_dont_convert_safe_characters tests/test_utils_url.py::CanonicalizeUrlTest::test_keep_blank_values tests/test_utils_url.py::CanonicalizeUrlTest::test_non_ascii_percent_encoding_in_paths tests/test_utils_url.py::CanonicalizeUrlTest::test_non_ascii_percent_encoding_in_query_arguments tests/test_utils_url.py::CanonicalizeUrlTest::test_normalize_percent_encoding_in_paths tests/test_utils_url.py::CanonicalizeUrlTest::test_normalize_percent_encoding_in_query_arguments tests/test_utils_url.py::CanonicalizeUrlTest::test_quoted_slash_and_question_sign tests/test_utils_url.py::CanonicalizeUrlTest::test_remove_fragments tests/test_utils_url.py::CanonicalizeUrlTest::test_return_str tests/test_utils_url.py::CanonicalizeUrlTest::test_safe_characters_unicode tests/test_utils_url.py::CanonicalizeUrlTest::test_sorting tests/test_utils_url.py::CanonicalizeUrlTest::test_spaces tests/test_utils_url.py::CanonicalizeUrlTest::test_typical_usage tests/test_utils_url.py::CanonicalizeUrlTest::test_urls_with_auth_and_ports tests/test_utils_url.py::AddHttpIfNoScheme::test_add_scheme tests/test_utils_url.py::AddHttpIfNoScheme::test_complete_url tests/test_utils_url.py::AddHttpIfNoScheme::test_fragment tests/test_utils_url.py::AddHttpIfNoScheme::test_path tests/test_utils_url.py::AddHttpIfNoScheme::test_port tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_ftp tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_complete_url tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_fragment tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_path tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_port tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_query tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_username_password tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_http_without_subdomain tests/test_utils_url.py::AddHttpIfNoScheme::test_preserve_https tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_complete_url tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_fragment tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_path tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_port tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_query tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_username_password tests/test_utils_url.py::AddHttpIfNoScheme::test_protocol_relative_without_subdomain tests/test_utils_url.py::AddHttpIfNoScheme::test_query tests/test_utils_url.py::AddHttpIfNoScheme::test_username_password tests/test_utils_url.py::AddHttpIfNoScheme::test_without_subdomain tests/test_utils_url.py::GuessSchemeTest::test_uri_001 tests/test_utils_url.py::GuessSchemeTest::test_uri_002 tests/test_utils_url.py::GuessSchemeTest::test_uri_003 tests/test_utils_url.py::GuessSchemeTest::test_uri_004 tests/test_utils_url.py::GuessSchemeTest::test_uri_005 tests/test_utils_url.py::GuessSchemeTest::test_uri_006 tests/test_utils_url.py::GuessSchemeTest::test_uri_007 tests/test_utils_url.py::GuessSchemeTest::test_uri_008 tests/test_utils_url.py::GuessSchemeTest::test_uri_009 tests/test_utils_url.py::GuessSchemeTest::test_uri_010 tests/test_utils_url.py::GuessSchemeTest::test_uri_011 tests/test_utils_url.py::GuessSchemeTest::test_uri_012 tests/test_utils_url.py::GuessSchemeTest::test_uri_013 tests/test_utils_url.py::GuessSchemeTest::test_uri_014 tests/test_utils_url.py::GuessSchemeTest::test_uri_015 tests/test_utils_url.py::GuessSchemeTest::test_uri_016 tests/test_utils_url.py::GuessSchemeTest::test_uri_017 tests/test_utils_url.py::GuessSchemeTest::test_uri_018 tests/test_utils_url.py::GuessSchemeTest::test_uri_019 tests/test_utils_url.py::GuessSchemeTest::test_uri_020
scrapy/utils/url.py
scrapy/utils/url.py