Repository: scrapy/parsel

Issue:
LookupError: unknown encoding: 'b'utf8''
Installed using conda on Windows 11 machine.  Working through the tutorial and 

response.css("title")

Gives this error:

  File "src\\lxml\\parser.pxi", line 1806, in lxml.etree.HTMLParser.__init__
  File "src\\lxml\\parser.pxi", line 858, in lxml.etree._BaseParser.__init__
LookupError: unknown encoding: 'b'utf8''

scrapy                    2.12.0          py311h1ea47a8_1    conda-forge
twisted                   23.10.0         py311haa95532_0
lxml                      5.2.1           py311h395c83e_1


Discussion:

Patch:
diff --git a/parsel/selector.py b/parsel/selector.py
index b37adbd..8250e06 100644
--- a/parsel/selector.py
+++ b/parsel/selector.py
@@ -90,7 +90,7 @@ def create_root_node(
     base_url: Optional[str] = None,
     huge_tree: bool = LXML_SUPPORTS_HUGE_TREE,
     body: bytes = b"",
-    encoding: str = "utf8",
+    encoding: str = "utf-8",
 ) -> etree._Element:
     """Create root node for text using given parser class."""
     if not text:
@@ -318,7 +318,7 @@ def _get_root_and_type_from_bytes(
 ) -> Tuple[Any, str]:
     if input_type == "text":
         return body.decode(encoding), input_type
-    if encoding == "utf8":
+    if encoding == "utf-8":
         try:
             data = json.load(BytesIO(body))
         except ValueError:
@@ -445,7 +445,7 @@ class Selector:
         text: Optional[str] = None,
         type: Optional[str] = None,
         body: bytes = b"",
-        encoding: str = "utf8",
+        encoding: str = "utf-8",
         namespaces: Optional[Mapping[str, str]] = None,
         root: Optional[Any] = _NOT_SET,
         base_url: Optional[str] = None,
@@ -518,7 +518,7 @@ class Selector:
         huge_tree: bool = LXML_SUPPORTS_HUGE_TREE,
         type: Optional[str] = None,
         body: bytes = b"",
-        encoding: str = "utf8",
+        encoding: str = "utf-8",
     ) -> etree._Element:
         return create_root_node(
             text,


Test patch:
diff --git a/tests/test_selector.py b/tests/test_selector.py
index 96713f9..d2a1641 100644
--- a/tests/test_selector.py
+++ b/tests/test_selector.py
@@ -1346,7 +1346,7 @@ class SelectorBytesInput(Selector):
         text: Optional[str] = None,
         type: Optional[str] = None,
         body: bytes = b"",
-        encoding: str = "utf8",
+        encoding: str = "utf-8",
         namespaces: Optional[Mapping[str, str]] = None,
         root: Optional[Any] = _NOT_SET,
         base_url: Optional[str] = None,
diff --git a/tests/test_selector_csstranslator.py b/tests/test_selector_csstranslator.py
index 2adc2f5..93cc7ca 100644
--- a/tests/test_selector_csstranslator.py
+++ b/tests/test_selector_csstranslator.py
@@ -227,4 +227,4 @@ class CSSSelectorTest(unittest.TestCase):
 
 class CSSSelectorTestBytes(CSSSelectorTest):
     def setUp(self) -> None:
-        self.sel = self.sscls(body=bytes(HTMLBODY, encoding="utf8"))
+        self.sel = self.sscls(body=bytes(HTMLBODY, encoding="utf-8"))