我們知道酗宋,Scrapy
最終給到我們的是response
對(duì)象,了解了response
的數(shù)據(jù)結(jié)構(gòu),我們就能更好的解析利用response
數(shù)據(jù)厚脉。
先來(lái)理解Response這個(gè)類
通過(guò)Response對(duì)象本身可以直接訪問(wèn)的對(duì)象或方法有:
def __init__(self, url, status=200, headers=None, body=b'', flags=None, request=None):
self.headers = Headers(headers or {})
self.status = int(status)
self._set_body(body)
self._set_url(url)
self.request = request
self.flags = [] if flags is None else list(flags)
@property
def meta(self):
try:
return self.request.meta
except AttributeError:
raise AttributeError(
"Response.meta not available, this response "
"is not tied to any request"
)
url = property(_get_url, obsolete_setter(_set_url, 'url'))
body = property(_get_body, obsolete_setter(_set_body, 'body'))
從上面的代碼可以知道,通過(guò)Response對(duì)象可以直接訪問(wèn)的屬性有headers
胶惰,status
傻工, request
, meta
,meta即是屬性也是方法中捆, url
鸯匹, body
,以上可以直接獲取內(nèi)容泄伪,還有一些方法比如text()
殴蓬,css()
,xpath()
蟋滴,在子類中實(shí)現(xiàn)可以使用染厅。
看看Response的子類
Response
----TextResponse
--------HtmlResponse
--------XmlResponse
HtmlResponse
,XmlResponse
兩個(gè)類本身只是簡(jiǎn)單的繼承了TextResponse
津函,沒(méi)有做任何實(shí)現(xiàn)肖粮,所以我們重點(diǎn)來(lái)看看TextResponse
類。
TextResponse
的主要是添加了一個(gè)新的構(gòu)造函數(shù)尔苦,encoding涩馆。這個(gè)暫時(shí)還不能細(xì)致的理解,事實(shí)上對(duì)這個(gè)Python體系的編碼都很暈允坚,先放放吧魂那。
TextResponse
對(duì)父類的一些未實(shí)現(xiàn)的方法做了實(shí)現(xiàn):
@property
def text(self):
""" Body as unicode """
# access self.encoding before _cached_ubody to make sure
# _body_inferred_encoding is called
benc = self.encoding
if self._cached_ubody is None:
charset = 'charset=%s' % benc
self._cached_ubody = html_to_unicode(charset, self.body)[1]
return self._cached_ubody
@property
def selector(self):
from scrapy.selector import Selector
if self._cached_selector is None:
self._cached_selector = Selector(self)
return self._cached_selector
def xpath(self, query, **kwargs):
return self.selector.xpath(query, **kwargs)
def css(self, query):
return self.selector.css(query)
一般情況下,我們爬取網(wǎng)頁(yè)獲取到的Response
對(duì)象是HtmlResponse
屋讶,從上面的源碼我們可以知道冰寻,Scrapy的數(shù)組組織結(jié)構(gòu)是Selector
。
從Html源解析數(shù)據(jù)一般有兩種方式:
-
BeautifulSoup
皿渗,這個(gè)類比較有名了斩芭,它對(duì)一些標(biāo)記不規(guī)范的HTML也有很好的適應(yīng)能力,但它最大的缺點(diǎn)就是--太慢了
乐疆。 -
lxml
划乖,這是一個(gè)xml解析庫(kù),當(dāng)然也能用來(lái)解析html挤土,lxml并不是Python的標(biāo)準(zhǔn)庫(kù)琴庵,但是它有基于ElementTree
的極具Python風(fēng)格的API。
Scrapy的Selector
是基于lxml構(gòu)建的仰美,所以在速度和解析精度上和lxml相似迷殿。
雖然lxml的語(yǔ)法很強(qiáng)大,能夠處理很多其它的任務(wù)咖杂,但是在這里庆寺,Selector的語(yǔ)法就很簡(jiǎn)單,這也決定了Selector的解析方式诉字。
Seelctor或者說(shuō)Scrapy的數(shù)據(jù)對(duì)象有以下三種解析方式
xpath
css
re
這個(gè)從Selector的源碼可以看出懦尝,不喜歡css
和re
(主要是太麻煩了知纷,記得東西太多,每次用還要現(xiàn)學(xué))陵霉,我們數(shù)據(jù)解析的話就專門使用xpath
琅轧,下一節(jié)就來(lái)好好學(xué)習(xí)學(xué)習(xí)xpath
的語(yǔ)法。
def css(self, query):
"""
Apply the given CSS selector and return a :class:`SelectorList` instance.
``query`` is a string containing the CSS selector to apply.
In the background, CSS queries are translated into XPath queries using
`cssselect`_ library and run ``.xpath()`` method.
"""
return self.xpath(self._css2xpath(query))
發(fā)現(xiàn)個(gè)比較變態(tài)的踊挠,css底層實(shí)現(xiàn)也是先將css轉(zhuǎn)成xpath乍桂。那就不需要多此一舉了。