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