이 기사에서는 lxml
먼저 페이지 링크를 가져오는 코드 예제를 보여줍니다.
#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/', '대상': '_blank'}
{' href': 'http://game.3533.com/tupian/', '대상': '_blank'}
{'href': 'http://www.4399.com/', ' target' : '_blank'}
{'href': 'http://www.91wan.com/', 'target': '_blank'}
3ed8bec1d105f4dcb8f1f75d1c6c2d63,
hrefs의 href에 대한
print href.text
결과는 다음과 같습니다.
Youth Development Foundation
Rock Kingdom
Aola Star
모바일 게임
모바일 배경화면
4399 미니 게임
91wan 게임
lxml을 사용하기 전에 주의할 사항: utf-8 디코딩 후 html, 즉 code = html.decode('utf-8', 'ignore')인지 확인하세요. 그렇지 않으면 구문 분석 오류가 발생합니다. 중국어는 utf-8로 인코딩된 후 '/u2541'과 같은 형식이 되기 때문에 lxml은 "/"를 만나면 해당 태그가 끝나는 것으로 생각합니다.
XPATH는 기본적으로 디렉토리 트리와 같은 방법을 사용하여 XML 문서의 경로를 설명합니다. 예를 들어 "/"를 사용하여 상위 수준과 하위 수준을 구분합니다. 첫 번째 "/"는 문서의 루트 노드를 나타냅니다. 이는 문서의 가장 바깥쪽 태그 노드를 나타내는 것이 아니라 문서 자체를 나타냅니다. 예를 들어 HTML 파일의 경우 가장 바깥쪽 노드는 "/html"이어야 합니다.
특정 HTML 태그를 찾으려면 파일 경로와 유사한 절대 경로(예: page.xpath(u"/html/body/p"))를 사용할 수 있습니다. 본문 노드 찾기 모든 p 태그 찾기; 파일 경로와 유사한 상대 경로를 사용할 수도 있습니다. 다음과 같이 사용할 수 있습니다: page.xpath(u"//p"), 전체에서 모든 p 태그를 찾습니다. html 코드:
90ce244b5a5321cadd932bf501f122e4이 페이지에만 있는 세계 뉴스94b3e26ee717c64999d7867364b1b4a3
아, 그런데 여기에 텍스트가 더 있습니다.
e388a4556c0f65e1904146cc1a846bee.. . 그리고 이것은 구문 분석된 조각입니다 ...94b3e26ee717c64999d7867364b1b4a3
참고: XPATH는 반드시 유일한 노드를 반환하는 것이 아니라 조건을 충족하는 모든 노드를 반환합니다. 위와 같이 본문에 p 태그만 있으면 본문의 첫 번째 수준 노드, 두 번째 수준, 세 번째 수준 노드인지 여부에 관계없이 제거됩니다.
범위를 더 좁혀서 "90ce244b5a5321cadd932bf501f122e4이 페이지에만 세계 뉴스94b3e26ee717c64999d7867364b1b4a3"를 직접 찾고 싶다면 어떻게 해야 할까요? 이를 위해서는 필터 조건을 추가해야 합니다. 필터링 방법은 "[""]"를 사용하여 필터 조건을 추가하는 것입니다. lxml에는 필터 구문이 있습니다:
p = page.xpath(u"/html/body/p[@style='font-size: 200%']")
또는 : p = page.xpath(u"//p[@style='font-size:200%']")
이런 식으로, 글꼴 크기:200% 스타일의 p 노드는 참고: 이 p 변수는 lxml.etree._Element 개체의 목록입니다. p[0].text의 결과는 이 페이지에만 있습니다. 즉, 태그 사이의 값입니다. p [0].values()의 결과는 글꼴 크기: 200%, 즉 모든 속성 값입니다. 그 중 @style은 속성 스타일을 나타냅니다. 마찬가지로 @name, @id, @value, @href, @src, @class....
를 사용할 수도 있습니다. 태그에는 그런 것이 없습니다. 속성은 어떻게 해야 하나요? 그런 다음 text(), position() 및 기타 함수 를 사용하여 필터링할 수 있습니다. text() 함수는 노드에 포함된 텍스트를 가져오는 것을 의미합니다. 예: e388a4556c0f65e1904146cc1a846beehelloe388a4556c0f65e1904146cc1a846beeworld94b3e26ee717c64999d7867364b1b4a36fb279ad3fd4344cbdd93aac6ad173ac, "p[text()='hello']"를 사용하여 p를 가져오고 world는 p의 text()입니다. position() 함수는 노드의 위치를 얻는 것을 의미합니다. 예를 들어, "li[position()=2]"는 두 번째 li 노드를 얻는다는 의미이며 "li[2]"로 생략할 수도 있습니다.
단, 수치 위치 지정 순서와 필터 조건에 주의해야 합니다. 예를 들어, "ul/li[5][@name='hello']"는 ul 아래의 다섯 번째 항목 li를 가져오고 해당 이름은 hello여야 함을 의미합니다. 그렇지 않으면 빈 값을 반환합니다. 하지만 "ul/li[@name='hello'][5]"를 사용하면 의미가 달라집니다. 이는 ul 아래에 이름이 "hello"인 다섯 번째 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”,它的意思是结束节点前面的内容,也就是说在“df250b2156c434f3390392d09b1c9563”与“94b3e26ee717c64999d7867364b1b4a3”之间的内容。它的源码里面的意思是“text after end tag”
至于“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 중국어 웹사이트의 기타 관련 기사를 참조하세요!