gpt4 book ai didi

python - Scrapy 无法正确解析某些 html 文件

转载 作者:太空宇宙 更新时间:2023-11-04 01:33:25 24 4
gpt4 key购买 nike

我已经使用了几个星期的 Scrapy,最近,我发现 HtmlXPathSelector 无法正确解析一些 html 文件。

在网页中http://detail.zol.com.cn/series/268/10227_1.html ,只有一个标签名为

`div id='param-more' class='mod_param  '`. 

当我使用 xpath "//div[@id='param-more']" 选择标签时,它返回了 []

我试过 scrapy shell 并得到了相同的结果。

当使用wget获取网页时,我还可以在html中找到标签"div id='param-more' class='mod_param '"源文件,我认为不是触发 Action 显示标签的原因。

请给我一些关于如何解决这个问题的提示。

以下是关于该问题的代码片段。处理上述 url 时,len(nodes_product) 始终为 0

def parse_series(self, response):
hxs = HtmlXPathSelector(response)

xpath_product = "//div[@id='param-normal']/table//td[@class='name']/a | "\
"//div[@id='param-more']/table//td[@class='name']/a"
nodes_product = hxs.select(xpath_product)
if len(nodes_product) == 0:
# there's only the title, no other products in the series
.......
else:
.......

最佳答案

这似乎是 XPathSelectors 的错误。我创建了一个快速测试蜘蛛并遇到了同样的问题。我相信这与页面上的非标准字符有关。

我不认为问题是“param-more”div 与任何 javascript 事件或 CSS 隐藏相关联。我禁用了 javascript 并更改了我的用户代理(和位置)以查看这是否影响了页面上的数据。它没有。

但是,我能够使用 beautifulsoup 解析“param-more”div:

from scrapy.selector import HtmlXPathSelector
from scrapy.spider import BaseSpider
from bs4 import BeautifulSoup

class TestSpider(BaseSpider):
name = "Test"

start_urls = [
"http://detail.zol.com.cn/series/268/10227_1.html"
]

def parse(self, response):
hxs = HtmlXPathSelector(response)

#data = hxs.select("//div[@id='param-more']").extract()

data = response.body
soup = BeautifulSoup(data)
print soup.find(id='param-more')

其他人可能对 XPathSelect 问题了解更多,但是暂时,您可以将 beautifulsoup 找到的 HTML 保存到一个项目中,然后将其传递到管道中。

这是最新的 beautifulsoup 版本的链接:http://www.crummy.com/software/BeautifulSoup/#Download

更新

我相信我找到了具体问题。正在讨论的网页在元标记中指定它使用 GB 2312 charset .从 GB 2312 到 unicode 的转换是有问题的,因为有些字符没有 unicode equivalent。 .这不是问题,除了 beautifulsoup 的编码检测模块 UnicodeDammit 实际上将编码确定为 ISO 8859-2。问题是 lxml 通过查看 charset specified in the meta tag of the header 来确定文档的编码.因此,lxml 和 scrapy 感知到的编码类型不匹配。

下面的代码演示了上述问题,并提供了一个替代必须依赖 BS4 库的方法:

from scrapy.selector import HtmlXPathSelector
from scrapy.spider import BaseSpider
from bs4 import BeautifulSoup
import chardet

class TestSpider(BaseSpider):
name = "Test"

start_urls = [
"http://detail.zol.com.cn/series/268/10227_1.html"
]

def parse(self, response):

encoding = chardet.detect(response.body)['encoding']
if encoding != 'utf-8':
response.body = response.body.decode(encoding, 'replace').encode('utf-8')

hxs = HtmlXPathSelector(response)
data = hxs.select("//div[@id='param-more']").extract()
#print encoding
print data

在这里,您看到通过强制 lxml 使用 utf-8 编码,它不会尝试从它认为的 GB 2312->utf-8 进行映射。

在scrapy中,HTMLXPathSelectors编码设置在scrapy/select/lxmlsel.py模块中。该模块使用 response.encoding 属性将响应主体传递给 lxml 解析器,该属性最终在 scrapy/http/response/test.py 模块中设置。

处理设置 response.encoding 属性的代码如下:

@property
def encoding(self):
return self._get_encoding(infer=True)

def _get_encoding(self, infer=False):
enc = self._declared_encoding()
if enc and not encoding_exists(enc):
enc = None
if not enc and infer:
enc = self._body_inferred_encoding()
if not enc:
enc = self._DEFAULT_ENCODING
return resolve_encoding(enc)

def _declared_encoding(self):
return self._encoding or self._headers_encoding() \
or self._body_declared_encoding()

这里要注意的重要一点是,_headers_encoding 和 _encoding 最终都将反射(reflect)在 header 中元标记中声明的编码,而不是实际使用诸如 UnicodeDammit 或 chardet 之类的东西来确定文档编码。因此,会出现文档包含其指定编码的无效字符的情况,我相信 Scrapy 会忽略这一点,最终导致我们今天看到的问题。

关于python - Scrapy 无法正确解析某些 html 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12084033/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com