Selector對象
從頁面上提取資料的核心是HTTP文本解析,在Python中常用以下子產品進行處理:
BeautifulSoup: 非常流行的HTTP解析庫,API簡潔易用,但解析速度較慢
lxml: 由C語言編寫的lxml解析庫,解析速度快,API相對比較複雜
Scrapy綜合上述兩者優點實作Selector類,基于lxml建構,簡化了API接口,在Scrapy中使用Selector對象提取頁面上的資料,使用時先通過Xpath或Css選擇器中頁面要提取的資料,然後進行提取。下面詳細介紹Selector對象的使用。
1:建立對象
Selector類基于scrapy.selector子產品,建立selector對象時,可将頁面的HTML文檔字元串傳遞給selector構造器方法的text參數
from scrapy.selector import Selector
text = """
<html>
<body>
<h1>Hello World</h1>
<h1>Hello Scrapy</h1>
<b>Hello Python</b>
<ul>
<li>C++</li>
<li>JAVA</li>
<li>Python</li>
</ul>
</body>
</html>
"""
selector = Selector(text=text)
print(selector) # <Selector xpath=None data='<html>\n\t<body>\n\t\t<h1>Hello World</h1>\n\t\t'>
也可以使用一個Response對象構造Selector對象,将其傳遞給Selector構造器方法的response參數
from scrapy.selector import Selector
from scrapy.http import HtmlResponse
body = """
<html>
<body>
<h1>Hello World</h1>
<h1>Hello Scrapy</h1>
<b>Hello Python</b>
<ul>
<li>C++</li>
<li>JAVA</li>
<li>Python</li>
</ul>
</body>
</html>
"""
response = HtmlResponse(url="http://www.example.com", body=body, encoding="utf-8")
selector = Selector(response=response)
print(selector) # <Selector xpath=None data='<html>\n\t<body>\n\t\t<h1>Hello World</h1>\n\t\t'>
2:選中資料
調用Selector對象的xpath或者css方法(傳入Xpath或CSS選擇器表達式),可以選中文檔中的一個或多個部分
selector_list = selector.xpath("//h1")
print(selector_list)
# [<Selector xpath='//h1' data='<h1>Hello World</h1>'>, <Selector xpath='//h1' data='<h1>Hello Scrapy</h1>'>]
xpath和css方法傳回一個selector_list對象,其中包含每個被選中部分對應的Selector對象,可以使用for語句進行疊代出每一個Selector對象
selector_list = selector.xpath("//h1")
for i in selector_list:
print(i.xpath("./text()"))
# [<Selector xpath='./text()' data='Hello World'>]
# [<Selector xpath='./text()' data='Hello Scrapy'>]
selector_list對象也有xpath和css方法,調用它們的辦法行為是:以接收到的參數分别調用其中每一個Selector對象的xpath或css對象方法。并将所有結果收集到一個新的selector_list對象傳回給使用者。請看下面的示例:
selector_list = selector.xpath("//h1")
for i in selector_list.xpath("./text()"):
print(i)
# <Selector xpath='./text()' data='Hello World'>
# <Selector xpath='./text()' data='Hello Scrapy'>
li = selector.xpath("//ul").css("li").xpath("./text()")
print(li)
# [<Selector xpath='./text()' data='C++'>, <Selector xpath='./text()' data='JAVA'>, <Selector xpath='./text()' data='Python'>]
3:提取資料
調用Selector或者Selector_list對象的已下方法可将選中的内容提取:
extract()
re()
extract_first()
re_first()
Selector對象的extract方法将傳回選中内容的Unicode字元串
sl = selector.xpath("//h1")
print(sl[0].extract()) # <h1>Hello World</h1>
print(sl[1].extract()) # <h1>Hello Scrapy</h1>
與Selector對象的xpath和css方法類似,SelectorList對象的extract方法内部會調用其中每一個Selector對象的extract方法,并将結果集以一個清單的形式傳回給使用者.
sl = selector.xpath(".//li/text()")
print(sl.extract()) # ['C++', 'JAVA', 'Python']
SelectorList對象還有一個extract_first方法,該方法傳回其中一個Selector對象調用extract方法的結果,直接取出Unicode字元串而不是清單
sl = selector.xpath(".//b/text()")
print(sl.extract_first()) # Hello Python
同樣我們也可以使用re正規表達式的方式擷取選中内容的部分
text = """
<ul>
<li>C++,<b>價格:99</b></li>
<li>java,<b>價格:89</b></li>
<li>python,<b>價格:90</b></li>
</ul>
"""
selector = Selector(text=text)
sl = selector.xpath(".//li/b/text()").re("\d+")
print(sl) # ['99', '89', '90']
re_first方法同樣傳回第一個Selector對象調用re方法的結果
sl = selector.xpath(".//li/b/text()").re_first("\d+")
print(sl) # 99