lxml是python语言里处理XML以及HTML工作的功能最丰富和最容易使用的库。当然scrapy框架里也是使用xpath来解析数据的。lxml的安装在这里就不用赘述了,下面列举的代码片段是没有使用scrapy框架。
1. xpath简介
xpath基本上是用一种类似目录树的方法来描述在XML文档中的路径。比如用“/”来作为上下层级间的分隔。
第一个“/”表示文档的根节点。比如对于一个HTML文件来说,最外层的节点应该是"/html"。定位某一个HTML标签,可以使用类似文件路径里的绝对路径,如page.xpath("/html/body/h1"),它会找到body这个节点下所有的h1标签;也可以使用类似文件路径里的相对路径,可以这样使用:page.xpath("//h1"),它会找到整个html代码里的所有h1标签。
'.'----选取当前节点
'..'----选取当前节点的父元素节点
'@'----选取属性
'*'----匹配任何元素
'@*'----匹配任何属性
xpath的返回结果会是一个列表,是某个节点下的所有子节点、子标签。
2. xpath使用
上面的两个例子可能是我们获取数据的一种手段,但是它并不能准确地定位我们需要的标签、属性或数据。
定位标签我们可以通过id、class或者其他属性来获得此标签。我们爬取页面以http://sports.sina.com.cn/g/premierleague/index.shtml作为例子。
根据class定位标签:
tree.xpath("//span[@class='sec_blk_title']")
tree.xpath("//div[@class='contest']")
其中'//'表示使用的是相对路径,其中可能从根节点到要查找的节点之间省略了很多其他节点,也可以使用'/descendant::'来代替。毕竟从根节点逐层往下来查找标签会使标签路径很长,不方面阅读。 '@class'表示选取标签中的class属性,class也可以替换成其他属性,比如:id,name,title,src等等
上面第一句的意思是获取属性class的值为'sec_blk_title'的span标签,虽然这样获取的标签可能不止一个,但是已经比'//span'方式好很多了(当然我们可以使用其他更多的过滤条件来精确获取数据,如下)。注意这里获取的是标签本身,不是标签的文本或其他数据。
tree.xpath("//span[@class='sec_blk_title']")[0] #这样就获取到了刚才列表中的第一个标签
tree.xpath("//div[@class='sec_blk mrg_b_30']/div[@class='sec_blk_top']")
tree.xpath("//div[@class='sec_blk mrg_b_30']//span[@class='sec_blk_title']")
tree.xpath("//div[@class='sec_blk mrg_b_30']/ul/li[1]")
获取到标签后我们可以获取标签中的属性值
tree.xpath("//div[@class='sec_blk mrg_b_30']/ul/li[1]/a/text()") #获取a的文本,li标号是从1开始,而不是从0开始
tree.xpath("//div[@class='sec_blk mrg_b_30']/ul/li[1]/a/@href") #获取a的链接地址
当然还有其他类似的xpath例子:
"//input[@id='city']/@value"
"//div[@class='venueDetal']/p/img[@class='img']/@src"
"//div[@class='detail_info_title']//a[@class='hotel_star']/@title"