XPath構文とlxmlのモジュール
XPathは何ですか?
XPathの(XML Path Language)は、XMLで、HTML文書の言語で情報を見つけ、XMLやHTML文書内の要素と属性を横断するために使用することができます。
XPathの開発ツール
- プラグインクロムのXPathヘルパー。
- Firefoxのプラグインは、XPathを試してみてください。
XPath構文
ノードを選択します。
XPathは、XML文書内のノードまたはノードのセットを選択するために、パス式を使用しています。私たちは、従来のコンピュータのファイルシステムに表示これらのパス式と式は非常に似ています。
表現 | 説明 | 例 | 結果 |
---|---|---|---|
ノード名 | このノードのすべての子ノードを選択します | 本屋 | すべての子ノードの書店を選択 |
/ | あなたが一番上にある場合は、ルートノードから代表者を選択します。それ以外の場合は、ノード内のノードを選択 | /書店 | ルート要素書店の下にあるすべてのノードを選択します |
// | グローバル・ノードからノードを選択し、どの位置にあるだけ | //本 | グローバル・ノードからすべての本ノードを探します |
@ | ノードの属性を選択 | //ブック[@price] | 選択してすべてのノードが価格表のプロパティを持っています |
。 | 現在のノード | ./a | 現在のノードでタグを選択 |
述語:
述語は、特定のノードを検索するために使用されるか、または指定されたノードが値を含んでいる、角括弧内に嵌め込まれています。
下の表では、述語といくつかのパス式、および式の結果を列挙されています:
パス式 | 説明 |
---|---|
/書店/書籍[1] | 選択書店下の最初の子要素 |
/書店/書籍〔最後の()] | 本屋の下で最後から二番目のbook要素を選択します。 |
書店/書籍[位置()<3] | 書店の前に二つのサブ要素を選択。 |
//ブック[@price] | 不動産価格を持っているbook要素を選択 |
//ブック[@価格= 10] | book要素10に等しいすべての属性の価格を選択 |
通配符
*ワイルドカード。
通配符 | 説明 | 例 | 結果 |
---|---|---|---|
* | 任意のノードに一致します | /本屋/ * | 本屋の下のすべての子要素を選択します。 |
@ * | すべての属性は、ノードを一致させます | //本[@*] | 属性を持つすべてのbook要素を選択します。 |
複数のパスを選択します:
パス式を使用することにより、「|」オペレータは、複数の経路を選択することができます。
例としては、次のとおりです:
//bookstore/book | //book/title
# 选取所有book元素以及book元素下所有的title元素
演算子:
lxmlのライブラリー
lxmlのは、主な機能は、HTML / XMLデータを解析して抽出することであるか、HTML / XMLパーサです。
lxmlのと定期的に、Cで実装されているように、高性能のPython HTML / XMLパーサである、我々はすぐに特定の要素およびノード情報を見つけるために、前に学ぶためにXPath構文を使用することができます。
lxmlのパイソンの公式文書:http://lxml.de/index.html
あなたはピップを使用してインストールすることができますC言語のライブラリをインストールする必要があります:lxmlのインストールPIP
基本的な使用:
私たちは、HTMLコードを解析するために彼を使用することができ、およびHTMLコードを解析するとき、非標準のHTMLコードならば、彼は自動的に完了となります。次のようにサンプル・コードは次のとおりです。
# 使用 lxml 的 etree 库
from lxml import etree
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a> # 注意,此处缺少一个 </li> 闭合标签
</ul>
</div>
'''
#利用etree.HTML,将字符串解析为HTML文档 html = etree.HTML(text) # 按字符串序列化HTML文档 result = etree.tostring(html) print(result)
以下の結果を入力します。
<html><body>
<div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li> </ul> </div> </body></html>
あなたは見ることができます。lxmlのは、自動的にHTMLコードを変更します。liタグを補完するだけでなく、体を追加し、HTMLタグの例ではないだけ。
HTMLコードは、ファイルから読み込ん:
直接文字列解析に加えて、lxmlのは、ファイルからの読み込みをサポートしています。Hello.html私たちは、新しいファイルを作成します。
<!-- hello.html -->
<div>
<ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li> </ul> </div>
次に使うetree.parse()
ファイルを読むための方法を。次のようにサンプル・コードは次のとおりです。
from lxml import etree
# 读取外部文件 hello.html
html = etree.parse('hello.html')
result = etree.tostring(html, pretty_print=True) print(result)
そして、その結果を入力する前と同じです。
でXPath構文のlxmlのを使用します:
-
すべてのliタグを取得します。
from lxml import etree html = etree.parse('hello.html') print type(html) # 显示etree.parse() 返回类型 result = html.xpath('//li') print(result) # 打印<li>标签的元素集合
-
すべてのli要素内のすべてのクラス属性の値を取得します:
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/@class') print(result)
-
次李取得するためのhrefタグ
www.baidu.com
ラベルのを:from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/a[@href="www.baidu.com"]') print(result)
-
李タグの下にあるすべてのspanタグを取得します。
from lxml import etree html = etree.parse('hello.html') #result = html.xpath('//li/span') #注意这么写是不对的: #因为 / 是用来获取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用双斜杠 result = html.xpath('//li//span') print(result)
-
liタグのすべてのクラスの下のラベルを取得します。
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li/a//@class') print(result)
-
に対応する値の最後のliのhref属性を取得します。
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()]/a/@href') # 谓语 [last()] 可以找到最后一个元素 print(result)
-
コンテンツ最後から二番目のLI要素を取得します。
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()-1]/a') # text 方法可以获取元素内容 print(result[0].text)
-
第二のアプローチの内容最後から二番目のLI要素を取得します。
from lxml import etree html = etree.parse('hello.html') result = html.xpath('//li[last()-1]/a/text()') print(result)
XPathの要求を使用して映画天国をクロール
次のようにサンプル・コードは次のとおりです。
import requests
from lxml import etree
BASE_DOMAIN = 'http://www.dytt8.net'
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36', 'Referer': 'http://www.dytt8.net/html/gndy/dyzz/list_23_2.html' } def spider(): url = 'http://www.dytt8.net/html/gndy/dyzz/list_23_1.html' resp = requests.get(url,headers=HEADERS) # resp.content:经过编码后的字符串 # resp.text:没有经过编码,也就是unicode字符串 # text:相当于是网页中的源代码了 text = resp.content.decode('gbk') # tree:经过lxml解析后的一个对象,以后使用这个对象的xpath方法,就可以 # 提取一些想要的数据了 tree = etree.HTML(text) # xpath/beautifulsou4 all_a = tree.xpath("//div[@class='co_content8']//a") for a in all_a: title = a.xpath("text()")[0] href = a.xpath("@href")[0] if href.startswith('/'): detail_url = BASE_DOMAIN + href crawl_detail(detail_url) break def crawl_detail(url): resp = requests.get(url,headers=HEADERS) text = resp.content.decode('gbk') tree = etree.HTML(text) create_time = tree.xpath("//div[@class='co_content8']/ul/text()")[0].strip() imgs = tree.xpath("//div[@id='Zoom']//img/@src") # 电影海报 cover = imgs[0] # 电影截图 screenshoot = imgs[1] # 获取span标签下所有的文本 infos = tree.xpath("//div[@id='Zoom']//text()") for index,info in enumerate(infos): if info.startswith("◎年 代"): year = info.replace("◎年 代","").strip() if info.startswith("◎豆瓣评分"): douban_rating = info.replace("◎豆瓣评分",'').strip() print(douban_rating) if info.startswith("◎主 演"): # 从当前位置,一直往下面遍历 actors = [info] for x in range(index+1,len(infos)): actor = infos[x] if actor.startswith("◎"): break actors.append(actor.strip()) print(",".join(actors)) if __name__ == '__main__': spider()
クローム関連の問題:
62版(最新)では、バグではなく、ページ302リダイレクトに記録されているFormDataデータがあります。これは、このバージョンのバグです。詳細については、以下のリンクを参照してください。https://stackoverflow.com/questions/34015735/http-post-payload-not-visible-in-chrome-debuggerを。
この問題を解決したカナリアのバージョンでは、このバージョンをダウンロードすることができ、以下のリンクで継続:https://www.google.com/chrome/browser/canary.html