准備工作
html示例:
<?xml version="1.0" encoding="UTF-8"?>
<html
<head>
<title>text</title>
</head>
<body>
<div class="cdiv">
<p class="cp1 section">test p1 <span>next p1</span></p>
<ul>
<li id="0">1</li>
<li id="1">2</li>
<li id="2">3</li>
</ul>
</div>
<div class="cdiv1">
<p class="cp2">test p2 <span>next p2</span></p>
<ul>
<li id="3">4</li>
<li id="4">5</li>
<li id="5">6</li>
</ul>
</div>
<p class="item">test in p </p>
<li id="6" class="item cli-1">7</li>
<li id="7" class="item cli-2">8</li>
</body>
</html>
把該示例保存到test.html中.
創建python文件,輸入代碼
from scrapy.selector import Selector
doc = ''
with open('./test.html', 'r') as f:
doc = f.read()
sel = Selector(text=doc)
后面所有的示例代碼都會添加到這個文件中
Selector的主要方法
得到選中節點的字符串
get(): 得到選中節點列表中的第一個中節點, 並轉換成字符串返回。
getall(): 得到選中節點列表中的所有節點,並轉換成字符串返回。
示例:
#得到選中節點字符串
res = sel.css('.cdiv').xpath(".//li").get()
print(res)
res = sel.css('.cdiv').xpath(".//li").getall()
print(res)
結果:
<li id="0">1</li>
['<li id="0">1</li>', '<li id="1">2</li>', '<li id="2">3</li>']
用正則表達式匹配
re(regex): 用正則表達式匹配節點,並返回匹配的字符串。
示例:
res = sel.css('body .item').re(r'cli\-\d+')
print(res)
結果:
['cli-1', 'cli-2']
使用xpath表達式選擇節點
xpath(query): 使用xpath表達式選擇節點, 並返包含選中節點的Selector對象.
使用css選擇器選中節點
css(query): 使用css選擇器表達式選擇節點, 並返包含選中節點的Selector對象
xpath 語法
選擇所有的子節點
//{node}: 選擇根節點下所有標簽為{node}的子節點.
//{node}//{node1}: 選擇根節點下所有標簽為{node1}且父節點包含標簽{node}的節點
示例1:
res = sel.xpath("//li")
print(res)
結果:
[<Selector xpath='//li' data='<li id="0">1</li>'>, <Selector xpath='//li' data='<li id="1">2</li>'>, <Selector xpath='//li' data='<li id="2">3</li>'>, <Selector xpath='//li' data='<li id="3">4</li>'>, <Selector xpath='//li' data='<li id="4">5</li>'>, <Selector xpath='//li' data='<li id="5">6</li>'>, <Selector xpath='//li' data='<li id="6" class="item cli-1">7</li>'>, <Selector xpath='//li' data='<li id="7" class="item cli-2">8</li>'>]
示例2
res = sel.xpath("//ul//li")
print(res)
結果
[
<Selector xpath='//ul//li' data='<li>1</li>'>,
<Selector xpath='//ul//li' data='<li>2</li>'>,
<Selector xpath='//ul//li' data='<li>3</li>'>,
<Selector xpath='//ul//li' data='<li>4</li>'>,
<Selector xpath='//ul//li' data='<li>5</li>'>,
<Selector xpath='//ul//li' data='<li>6</li>'>
]
選擇直接子節點
{node}/{node1}: 選擇從{node}的直接子節點中選擇標簽為{node1}節點.
示例1:
res = sel.xpath("//body/li")
print(res)
結果:
[<Selector xpath='//body/li' data='<li id="6" class="item cli-1">7</li>'>, <Selector xpath='//body/li' data='<li id="7" class="item cli-2">8</li>'>]
從選擇的子節點列表中選擇第n個子節點
//{node}[n]: 先把兄弟節點聚合在一個list變成[list_1, list_2, ...], 然后從每個list中選擇第n個, 如果list的長度不足n個則跳過.
(//{node})[n]: 把所有選擇的節點放在一條list, 然后從這個list中選擇第n個
示例1:
res = sel.xpath("//li[1]")
print(res)
res = sel.xpath("//li[3]")
print(res)
結果:
[<Selector xpath='//li[1]' data='<li id="0">1</li>'>, <Selector xpath='//li[1]' data='<li id="3">4</li>'>, <Selector xpath='//li[1]' data='<li id="6" class="item cli-1">7</li>'>]
[<Selector xpath='//li[3]' data='<li id="2">3</li>'>, <Selector xpath='//li[3]' data='<li id="5">6</li>'>]
示例2
res = sel.xpath("(//li)[1]")
print(res)
res = sel.xpath("(//li)[3]")
print(res)
結果:
[<Selector xpath='(//li)[1]' data='<li>1</li>'>]
[<Selector xpath='(//li)[3]' data='<li>3</li>'>]
使用節點屬性作為選擇條件
{node}[@{attr}='{val}']: 選中節點必須有名字為{attr}的屬性, 且這個屬性的值等於{val}.
{node}[contains(@{attr}, '{val}']: 選中節點必須有名字為'{attr}'的屬性, 且這個屬性的值包含{val}.
示例1
res = sel.xpath("//p[@class='cp1']")
print(res)
res = sel.xpath("//p[@class='cp2']")
print(res)
res = sel.xpath("//p[contains(@class, 'cp1')]")
print(res)
結果
[]
[<Selector xpath="//p[@class='cp2']" data='<p class="cp2">test p2 <span>next p2<...'>]
[<Selector xpath="//p[contains(@class, 'cp1')]" data='<p class="cp1 section">test p1 <span>...'>]
[<Selector xpath="descendant-or-self::p[@class and contains(concat(' ', normalize-space(@class), ' '), ' cp1 ')]" data='<p class="cp1 section">test p1 <span>...'>]
在包含條件中, 如果使用'class'屬性, 可以用css選擇器簡化:
示例2:
res = sel.css("p.cp1")
print(res)
結果:
[<Selector xpath="descendant-or-self::p[@class and contains(concat(' ', normalize-space(@class), ' '), ' cp1 ')]" data='<p class="cp1 section">test p1 <span>...'>]
提取節點屬性的值
{node}/@{attr}: 提取選擇節的點中屬性名為{attr}的值.
示例1:
res = sel.xpath("//p/@class")
print(res)
print("\n")
結果
[<Selector xpath='//p/@class' data='cp1 section'>, <Selector xpath='//p/@class' data='cp2'>]
提取節點中的文本內容
{node}/text(): 提取當前選擇節點的文本內容, 不包括子節點的文本.
{node}//text(): 提取選擇節點的文本內容, 包括子節點的文本.
示例1:
res = sel.xpath("//p//text()")
print(res)
res = sel.xpath("//p/text()")
print(res)
結果:
[<Selector xpath='//p//text()' data='test p1 '>, <Selector xpath='//p//text()' data='next p1'>, <Selector xpath='//p//text()' data='test p2 '>, <Selector xpath='//p//text()' data='next p2'>]
[<Selector xpath='//p/text()' data='test p1 '>, <Selector xpath='//p/text()' data='test p2 '>]
在xpath表達式中使用變量
在xpath表達式中是${varname}定義變量, 類似於bash
示例1:
#使用變量$val
res = sel.xpath("//li[@id=$val]", val='1')
print(res)
res = sel.xpath("//li[@id=$val]", val='3')
print(res)
res = sel.xpath("//li[@id=$val]", val='6')
print(res)
結果:
[<Selector xpath='//li[@id=$val]' data='<li id="1">2</li>'>]
[<Selector xpath='//li[@id=$val]' data='<li id="3">4</li>'>]
[<Selector xpath='//li[@id=$val]' data='<li id="6" class="item cli-1">7</li>'>]