這似乎與XPathSelectors的錯誤。我創建了一個快速測試蜘蛛並遇到了同樣的問題。我相信這與頁面上的非標準字符有關。
我不相信問題是'param-more'div與任何javascript事件或CSS隱藏相關聯。我禁用了JavaScript,並更改了我的用戶代理(和位置),以查看這是否影響了頁面上的數據。它沒有。
我,但是,能夠解析「PARAM-更」 DIV使用beautifulsoup:
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問題,但暫時,你可以保存HTML通過beautifulsoup發現一件物品並將其傳入管道。
這裏是鏈接到最新版本beautifulsoup:http://www.crummy.com/software/BeautifulSoup/#Download
UPDATE
我相信我發現的具體問題。正在討論的網頁在meta標籤中指定它使用GB 2312 charset。從GB 2312到unicode的轉換是有問題的,因爲有些字符沒有unicode equivalent。除了UnicodeDammit,beautifulsoup的編碼檢測模塊實際確定編碼爲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中,在scrapy/select/lxmlsel.py模塊中設置了HTMLXPathSelectors編碼。該模塊使用response.encoding屬性將響應主體傳遞給lxml解析器,該屬性最終在scrapy/http/response/test.py模塊中設置。
@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都將最終體現在報頭中的meta標籤聲明的編碼:
,處理設置response.encoding屬性的代碼如下實際上使用諸如UnicodeDammit或chardet來確定文檔編碼。因此,如果文檔包含指定的編碼中包含無效字符的情況,我相信Scrapy會忽略它,最終導致我們今天看到的問題。
請你告訴你具體的代碼使用,返回不正確的結果。 –
剛剛添加了代碼片段:) – flyer