この記事では、lxml を使用して HTML を解析する方法を紹介します
まず、ページ リンクを取得するコード例を示します:
#coding=utf-8 from lxml import etree html = ''' <html> <head> <meta name="content-type" content="text/html; charset=utf-8" /> <title>友情链接查询 - 站长工具</title> <!-- uRj0Ak8VLEPhjWhg3m9z4EjXJwc --> <meta name="Keywords" content="友情链接查询" /> <meta name="Description" content="友情链接查询" /> </head> <body> <h1 class="heading">Top News</h1> <p style="font-size: 200%">World News only on this page</p> Ah, and here's some more text, by the way. <p>... and this is a parsed fragment ...</p> <a href="http://www.cydf.org.cn/" rel="nofollow" target="_blank">青少年发展基金会</a> <a href="http://www.4399.com/flash/32979.htm" target="_blank">洛克王国</a> <a href="http://www.4399.com/flash/35538.htm" target="_blank">奥拉星</a> <a href="http://game.3533.com/game/" target="_blank">手机游戏</a> <a href="http://game.3533.com/tupian/" target="_blank">手机壁纸</a> <a href="http://www.4399.com/" target="_blank">4399小游戏</a> <a href="http://www.91wan.com/" target="_blank">91wan游戏</a> </body> </html> ''' page = etree.HTML(html.lower().decode('utf-8')) hrefs = page.xpath(u"//a") for href in hrefs: print href.attrib
出力される結果は次のとおりです:
{'href': 'http:// www.cydf.org.cn/', 'target': '_blank', 'rel': 'nofollow'}
{'href': 'http://www.4399.com/flash/32979.htm', 'ターゲット ': '_blank'}
{'href': 'http://www.4399.com/flash/35538.htm', 'ターゲット': '_blank'}
{'href': 'http:/ /game .3533.com/game/', 'target': '_blank'}
{'href': 'http://game.3533.com/tupian/', 'target': '_blank'}
{ 'href ': 'http://www.4399.com/', 'target': '_blank'}
{'href': 'http://www.91wan.com/', 'target': '_blank '}
for href in hrefs:
print href.text
結果は次のようになります:
青少年育成財団
ロックキングダム
Ola Star
モバイルゲーム
モバイル壁紙
4399 ミニゲーム
91wan ゲーム
lxml を使用する前に注意すべきこと: まず、HTML が utf-8 でデコードされていること、つまり code = html.decode(' utf-8', 'ignore') 、それ以外の場合は解析エラーが発生します。中国語は utf-8 にエンコードされて「/u2541」のような形式になるため、lxml は「/」に遭遇したときにタグが終了するとみなします。
XPATHは基本的にディレクトリツリーのような方法を使ってXML文書内のパスを記述します。たとえば、上位レベルと下位レベルの区切りとして「/」を使用します。最初の「/」はドキュメントのルート ノードを表します (ドキュメントの最も外側のタグ ノードを指すのではなく、ドキュメント自体を指すことに注意してください)。たとえば、HTML ファイルの場合、最も外側のノードは「/html」である必要があります。
特定の HTML タグを見つけるには、page.xpath(u"/html/body/p") などのファイル パスと同様の絶対パスを使用できます。これにより、body ノードの下にあるすべての p タグが検索されます; ファイル パスと同様の相対パスを使用して、次のように使用することもできます: page. %">このページのみの世界ニュース
ああ、ところで、ここにさらにテキストがあります。
...これは解析されたフラグメントです...
さらに範囲を絞り込んで、「
このページの世界ニュースのみ
」を直接ターゲットにしたい場合はどうすればよいでしょうか?これにはフィルター条件を追加する必要があります。フィルタリングの方法は、「[""]」を使用してフィルタ条件を追加することです。 lxml にはフィルタリング構文があります:p = page.xpath(u"/html/body/p[@style='font-size: 200%']")
または: p = page.xpath(u " //p[@style='font-size:200%']")
このようにして、本文の style font-size:200% を持つ p ノードが取り出されます。 注: この p
変数lxml.etree ._Elementオブジェクトリスト、p[0].textの結果はこのページのみのワールドニュース、つまり、p[0].values()の結果はフォントです。 -size: 200%、つまりすべての 属性 Value。このうち、@style は属性のスタイルを表します。同様に、@name、@id、@value、@href、@src、@class....タグに属性がない場合はどうなりますか。 ?次に、text()、
position()、およびその他の関数を使用してフィルタリングできます。関数 text() は、ノードに含まれるテキストを取得することを意味します。例:
hello
world
< /p> では、「p[text()='hello']」を使用して p を取得します。world は p の text() です。関数position()はノードの位置を取得することを意味します。たとえば、「li[position()=2]」は 2 番目の li ノードを取得することを意味します。これは「li[2]」と省略することもできます。 ただし、デジタルポジショニングとフィルター条件の順序に注意する必要があります。たとえば、「ul/li[5][@name='hello']」は、ul の下の 5 番目の項目 li を取得することを意味し、その名前は hello でなければなりません。それ以外の場合は空を返します。ただし、「ul/li[@name='hello'][5]」を使用すると、ul の下にある「hello」という名前の 5 番目の li ノードを見つけることを意味します。此外,“*”可以代替所有的节点名,比如用"/html/body/*/span"可以取出body下第二级的所有span,而不管它上一级是p还是p或是其它什么东东。
而 “descendant::”前缀可以指代任意多层的中间节点,它也可以被省略成一个“/”。比如在整个HTML文档中查找id为“leftmenu”的 p,可以用“/descendant::p[@id='leftmenu']”,也可以简单地使用“ //p[@id='leftmenu']”。
text = page.xpath(u"/descendant::*[text()]")表示任意多层的中间节点下任意标签之间的内容,也即实现蜘蛛抓取页面内容功能。以下内容使用text属性是取不到的:
<p class="news"> 1. <b>无流量站点清理公告</b> 2013-02-22<br /> 取不到的内容 </p> <p class="news"> 2. <strong>无流量站点清理公告</strong> 2013-02-22<br /> 取不到的内容 </p> <p class="news"> 3. <span>无流量站点清理公告</span> 2013-02-22<br /> 取不到的内容 </p> <p class="news"> 4. <u>无流量站点清理公告</u> 2013-02-22<br /> 取不到的内容 </p>
这些“取不到的内容”使用这个是取不到的。怎么办呢?别担心,lxml还有一个属性叫做“tail”,它的意思是结束节点前面的内容,也就是说在“
”与“
至于“following-sibling::”前缀就如其名所说,表示同一层的下一个节点。"following-sibling::*"就是任意下一个节点,而“following-sibling::ul”就是下一个ul节点。
如果script与style标签之间的内容影响解析页面,或者页面很不规则,可以使用lxml.html.clean模块。模块 lxml.html.clean 提供 一个Cleaner 类来清理 HTML 页。它支持删除嵌入或脚本内容、 特殊标记、 CSS 样式注释或者更多。
cleaner = Cleaner(style=True, scripts=True,page_structure=False, safe_attrs_only=False)
print cleaner.clean_html(html)
注意,page_structure,safe_attrs_only为False时保证页面的完整性,否则,这个Cleaner会把你的html结构与标签里的属性都给清理了。使用Cleaner类要十分小心,小心擦枪走火。
忽略大小写可以:
page = etree.HTML(html)
keyword_tag = page.xpath("//meta[translate(@name,'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz')='keywords']")
以上がlxml を使用して HTML を解析する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。