爬虫:网页信息提取
网页信息提取常用的python工具包括正则表达式、CSS以及xpath.
正则表达式
Xpath(教程)
XML中的节点关系包括:父(parent)、子(children)、同胞(sibling)、先辈(ancestor)、后代(descendant).
常用的路径表达式:
/:表示从根节点开始
//:表示匹配当前节点下的所有节点
.:表示选取当前节点
..:表示选取当前节点的父节点
@:选取相关属性
常见的表达形式:
表示 | 描述 |
---|---|
bookstore | 选取bookstore元素的所有子节点 |
/bookstore | 选取根元素bookstore |
bookstore/book | 选取属于bookstore的所有book子元素 |
//book | 选取所有book子元素,而不管它们在文档中的位置 |
bookstore//book | 选取属于bookstore后代的所有book子元素(忽略位置限定) |
//@lang | 选取lang的所有属性 |
谓语用来查找某个特定的节点或者包含某一个特定的值的节点,被嵌在方括号中。
常见的表达式有:
表示 | 描述 |
---|---|
/bookstore/book[1] | 选取bookstore的第一个book子元素 |
/bookstore/book[last(i)] | 选取bookstore的最后i个book子元素 |
/bookstore/book[position()< 3] | 选取bookstore中book子元素最前面的两个 |
//title[@lang] | 选取所有拥有lang属性的title元素 |
//title[@lang="eng"] | 选取所有拥有lang属性,且属性值为eng的title元素 |
/bookstore/book[price>35.00] | 选取bookstore元素的所有book元素,且其中的price元素的值必须大于35.00 |
选取未知节点
通配符 | 描述 |
---|---|
* | 匹配任何元素 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
“|” | 或运算符,连接若干路径,如: //title|//price |
xpath的语法在应用的时候需要将Python抓取的网页转化为xml.
from lxml import etree
text="爬虫抓取的文本内容"
html=etree.HTML(text)#将字符串解析为HTML文档
result=etree.tostring(html)#为反向操作,即将HTNL转化为字符串
如果元素的名字过长,找不到其他较短的元素名,可以考虑正则表达式,或者使用contains,即:
html.xpath("元素节点名称[contains(@属性,"部分属性名")])
如: html.xpath("//div[contains(@id,'qiushi_tag')]")
注:单引号和双引号在混合表达式中一般要混合使用,如果始终采用同一种引号,会出现语法错误。
CSS选择器:BeautifulSoup4
Beautiful Soup 将复杂HTML文档转化成一个复杂的属性结构,每一个节点都是python对象,归纳为四类:Tag,NaviableString,BeautifulSoup,comment.
Tag是HTML中的标签。Tag的属性有name和attrs
.name是指标签本身的名字;attrs:对应于标签的所有属性
soup=BeautifulSoup(html)
soup.element.Tag :查找第一个符合要求的标签:
如:soup.p,soup.a
soup.p.attrs
soup.head.name
soup.p['class']#等价于soup.p.get('class')
NavigableString:用来获取标签内部的文字。
soup.p.string
BeautifulSoup对象表示一个文档的内容,大多数情况下,将它看作是Tag对象。
Comment是特殊的NavigableString对象,其输出的内容不包括注释符号。
遍历文档树:
- 直接遍历子节点:
.content :tag的content属性可以将tag的子节点以列表的方式输出
.children 返回一个list生成器
- 所有子孙节点:
.descendants
属性,对所有tag的子孙节点进行递归循环。 - 节点内容:
.string
:如果一个节点没有标签,则该属性会返回该节点里面的内容。如果只有唯一的一个标签,那么.string
将返回最里面的内容。
搜索文档树
find_all(name,attrs,recursive,text,**kwargs)
name:可以查找所有名字为name的tag,字符对象会被自动忽略掉
1)传字符串:BeautifulSoup将会匹配查找与字符串完整匹配的内容如soup.find_all('a')
2)传正则表达式。如果传入正则表达式作为参数,BeautifulSoup会通过正则表达式的match()
来匹配内容。
如:soup.find_all(re.compile("^b"))#^表示以什么开始
3)传列表。BeautifulSoup会将于列表中任一元素匹配的内容返回。
如:soup.find_all(["a","b"])#找到文档中所有的《a》和《b》标签
4)关键词参数:
soup.find_all(id="id")
soup.find_all(text="text")#text参数接受字符串,正则表达式,列表
soup.find_all(text="a")
soup.find_all(text=['a','b','c'])
soup.find_all(text=re.compile("text"))
css(教程)查找
标签名不加任何修饰,类名前加.,id名前加#.soup.select()
返回类型为list
1)通过标签名查找。如soup.select("title')
2)通过类名查找。如soup.selcet('.sister')
3)通过id查找。如soup.selcet("#link1")
4)组合查找。如soup.select('p #link1')
5)属性查找。如:soup.selcet('a[class="sisiter"]')
6)获取内容。如:get.text()
后续继续补充
参考:
清华学霸尹成的爬虫课件。
coder的爬虫系列博客