繁体   English   中英

从网络提取数据时如何去除特殊字符?

[英]How to get rid of special characters while extracting data from web?

我正在从网站提取数据,并且其中包含一个特殊字符的条目,即Comfort Inn And Suites ? Blazing Stump Comfort Inn And Suites ? Blazing Stump 当我尝试提取它时,它将引发错误:

    Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 824, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "C:\Python27\lib\site-packages\twisted\internet\task.py", line 638, in _tick
    taskObj._oneWorkUnit()
  File "C:\Python27\lib\site-packages\twisted\internet\task.py", line 484, in _oneWorkUnit
    result = next(self._iterator)
  File "C:\Python27\lib\site-packages\scrapy\utils\defer.py", line 57, in <genexpr>
    work = (callable(elem, *args, **named) for elem in iterable)
--- <exception caught here> ---
  File "C:\Python27\lib\site-packages\scrapy\utils\defer.py", line 96, in iter_errback
    yield it.next()
  File "C:\Python27\lib\site-packages\scrapy\contrib\spidermiddleware\offsite.py", line 24, in process_spider_output
    for x in result:
  File "C:\Python27\lib\site-packages\scrapy\contrib\spidermiddleware\referer.py", line 14, in <genexpr>
    return (_set_referer(r) for r in result or ())
  File "C:\Python27\lib\site-packages\scrapy\contrib\spidermiddleware\urllength.py", line 32, in <genexpr>
    return (r for r in result or () if _filter(r))
  File "C:\Python27\lib\site-packages\scrapy\contrib\spidermiddleware\depth.py", line 48, in <genexpr>
    return (r for r in result or () if _filter(r))
  File "E:\Scrapy projects\emedia\emedia\spiders\test_spider.py", line 46, in parse
    print repr(business.select('a[@class="name"]/text()').extract()[0])
  File "C:\Python27\lib\site-packages\scrapy\selector\lxmlsel.py", line 51, in select
    result = self.xpathev(xpath)
  File "xpath.pxi", line 318, in lxml.etree.XPathElementEvaluator.__call__ (src\lxml\lxml.etree.c:145954)

  File "xpath.pxi", line 241, in lxml.etree._XPathEvaluatorBase._handle_result (src\lxml\lxml.etree.c:144987)

  File "extensions.pxi", line 621, in lxml.etree._unwrapXPathObject (src\lxml\lxml.etree.c:139973)

  File "extensions.pxi", line 655, in lxml.etree._createNodeSetResult (src\lxml\lxml.etree.c:140328)

  File "extensions.pxi", line 676, in lxml.etree._unpackNodeSetEntry (src\lxml\lxml.etree.c:140524)

  File "extensions.pxi", line 784, in lxml.etree._buildElementStringResult (src\lxml\lxml.etree.c:141695)

  File "apihelpers.pxi", line 1373, in lxml.etree.funicode (src\lxml\lxml.etree.c:26255)

exceptions.UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 22: invalid continuation byte

在网上搜索后,我尝试了很多不同的操作,例如: decode('utf-8')unicodedata.normalize('NFC',business.select('a[@class="name"]/text()').extract()[0])但问题仍然存在吗?

源URL是“ http://www.truelocal.com.au/find/hotels/97/ ”,在此页面上,这是我正在谈论的第四项。

您在原始网页中的Mojibake不好,可能是由于某处数据条目中Unicode的处理不当所致。 当以十六进制表示时,源中的实际UTF-8字节为C3 3F C2 A0

认为它曾经是U + 00A0 NO-BREAK SPACE 编码以UTF-8变为C2 A0 ,解释作为 Latin-1的代替然后编码为UTF-8再次变得C3 82 C2 A0 ,但82是一个控制字符,如果解释为Latin-1的再次使得被取代的? 问号,编码时为3F十六进制。

当您Comfort Inn And Suites Blazing Stump 该场所详细信息页面的链接时,您会得到一个不同的Comfort Inn And Suites Blazing Stump ,名称相同: Comfort Inn And Suites Blazing Stump ,为我们提供Unicode字符U + 00C3,U + 201A,U + 00C2 a &nbsp; HTML实体,或者再次是Unicode字符U + 00A0。 将其编码为Windows Codepage 1252 (Latin-1的超集),您将再次获得C3 82 C2 A0

您只能通过直接在页面源中定位此目标来摆脱它

pagesource.replace('\xc3?\xc2\xa0', '\xc2\xa0')

通过用原始的预期UTF-8字节替换火车残骸来“修复”数据。

如果您的Response对象不清晰,请替换正文:

body = response.body.replace('\xc3?\xc2\xa0', '\xc2\xa0')
response = response.replace(body=body)

不要使用“替换”来修复Mojibake,不要修复导致Mojibake的数据库和代码。

但是首先您需要确定它是简单的Mojibake还是“双重编码”。 使用SELECT col, HEX(col) ...确定单个字符变为2-4个字节(Mojibake)还是4-6个字节(双编码)。 例子:

`é` (as utf8) should come back `C3A9`, but instead shows `C383C2A9`
The Emoji `👽` should come back `F09F91BD`, but comes back `C3B0C5B8E28098C2BD`

在此处查看“ Mojibake”和“双重编码”

然后在这里讨论数据库修复:

  • 字符集latin1,但其中有utf8字节; 修复字符集时,不留任何字节:

首先,假设您对tbl.col声明如下:

col VARCHAR(111) CHARACTER SET latin1 NOT NULL

然后通过此两步ALTER来转换列而不更改字节:

ALTER TABLE tbl MODIFY COLUMN col VARBINARY(111) NOT NULL;
ALTER TABLE tbl MODIFY COLUMN col VARCHAR(111) CHARACTER SET utf8mb4 NOT NULL;

注意:如果您以TEXT开头,请使用BLOB作为中间定义。 (这是“两步ALTER,如其他地方所讨论。)(请确保其他规格相同-VARCHAR,NOT NULL等)。

  • 具有双重编码的CHARACTER SET utf8mb4UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);

  • 具有双重编码的CHARACTER SET latin1 :执行两步ALTER,然后修复双重编码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM