12.5 选择器
爬虫模块创建完成后,仅仅拥有了网页下载功能,下面进行网页数据的提取。Scrapy有自己的一套数据提取机制,称为选择器(selector),因为它们通过特定的XPath或者CSS表达式来选择HTML文件中的某个部分。Scrapy选择器构建于lxml库之上,这意味着它们在速度和解析准确性上非常相似,用法也和之前讲的lxml解析基本类似。当然也可以脱离这套机制,使用BeautifulSoup包进行解析。
12.5.1 Selector的用法
之前的章节我们已经讲过XPath和CSS,这里不再赘述。下面主要说一下Selector的用法,Selector对象有四个基本的方法:
1)xpath(query):传入XPath表达式query,返回该表达式所对应的所有节点的selector list列表。
2)css(query):传入CSS表达式query,返回该表达式所对应的所有节点的selector list列表。
3)extract():序列化该节点为Unicode字符串并返回list列表。
4)re(regex):根据传入的正则表达式对数据进行提取,返回Unicode字符串列表。regex可以是一个已编译的正则表达式,也可以是一个将被re.compile(regex)编译为正则表达式的字符串。
在CnblogsSpider类的parse()方法中,其中一个参数是response,将response传入Selector(response)中就可以构造出一个Selector对象,进而调用以上的四个方法。还有简写的方式,传入的Response直接可以调用xpath和css方法,形如response.xpath()或者response.css()。
方法的调用很简单,更多的时间是花费在XPath和CSS表达式的构造。Scrapy提供了一种简便的方式来查看表达式是否正确、是否真的起作用。另起一个命令行窗口,在其中输入scrapy shell“http://www.cnblogs.com/qiyeboy/default.htmlpage=1 ”,记得后面的URL加上双引号,效果如图12-7所示。
图12-7 scrapy shell
其中方框圈出来的response就是访问以上网址获得响应,直接在scrapy shell中输入response.xpath(“.//*[@class=’postTitle‘]/a/text()”).extract(),就可以抽取出当前网址的所有文章的标题,返回的是Unicode格式,如图12-8所示。
大家可以用这种方法来测试自己写的XPath或者CSS表达式。
可能有人会说,直接使用Firepath测试不是更简单对,使用Firepath来获取和测试表达式更直观和方便。但是大家有没有想过动态网站,HTML网页都是经过渲染的,很多时候浏览器上显示的网页结构和程序访问获取的结构是不一样的,就会导致在Firepath获取和调试成功的表达式在程序中不起作用,这种情况的解决办法是将scrapy shell和Firepath结合起来使用。在scrapy shell中有一个功能是查看响应,在shell中输入view(response),可以将获取的响应在浏览器中打开,然后就可以使用Firepath获取和调试真实的表达式了。如图12-9所示,响应被存成了一个本地的html文件。
图12-8 测试表达式
图12-9 scrapy shell和Firepath结合处理
12.5.2 HTML解析实现
讲解完Selector的用法,下面抽取博客文章的数据。通过分析网页的结构,XPath表达式如下:
·所有文章:.//*[@class=’day‘]
·文章发表时间:.//*[@class=’dayTitle‘]/a/text()
·文章标题内容:.//*[@class=’postTitle‘]/a/text()
·文章摘要内容:.//*[@class=’postCon‘]/div/text()
·文章链接:.//*[@class=’postTitle‘]/a/@href
parse()方法代码如下:
def parse(self, response): # 实现网页的解析 # 首先抽取所有的文章 papers = response.xpath(".// *[@class='day']") # 从每篇文章中抽取数据 for paper in papers: url = paper.xpath(".// *[@class='postTitle']/a/@href").extract()[0] title = paper.xpath(".// *[@class='postTitle']/a/text()").extract()[0] time = paper.xpath(".// *[@class='dayTitle']/a/text()").extract()[0] content = paper.xpath(".// *[@class='postTitle']/a/text()").extract()[0] print url, title,time,content
代码先抽取出当前网页中的所有文章,然后从每篇文章中抽取数据,抽取的数据以列表的格式返回,直接取第一个即可。在命令中输入scrapy crawl cnblogs再次启动爬虫就可以看到抽取出的数据,如图12-10所示。
图12-10 抽取效果
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论