爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 15777|回复: 5

[参考资料] 爬虫之<网页节点定位方法>的整理

[复制链接]

新浪微博达人勋

发表于 2020-12-15 15:51:01 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
做爬虫,就是要读懂网页内容,获取需要的信息;
网页文档,本质是个树形结构,跟我们电脑里,大文件夹里有中文件夹,中文件夹里又有小文件夹这样
如何定位网页文档的节点,是个基本问题。
最原始的手段是用urllib2请求网得到结果,然后用re取得内容,
当然,这很傻!
scrapy提取数据使用选择器(selectors),选择器有2个:XPath,CSS


那这2个有啥区别呢?
1、CSS更简洁,速度快,效率高
2,CSS不支持文本搜索,XPATH支持
3,xpath支持的函数特别多,CSS比较少,所以在复杂元素查找时候,xpath反而更加简洁
所以,当查找元素比较简单,用css;如果复杂,用xpath比较好

xpath更为强大些,
它是处理xml的,自然也能处理html
XPath含100多个函数,用于处理字符串,数值,日期,时间,节点,QName,序列,逻辑值等。
XPath有7种节点:元素,属性,文本,命名空间,处理指令,注释,文档节点/根节点
xml文档被作为[节点树]对待,树根被称为文档节点/根节点(网页文档的根节点就是<html>)
节点有父子关系,同级的叫“同胞节点”

以下是3种定位方法及其基本语法:

方法1:XPath使用[路径表达式]在xml文档中选择节点
路径表达式
描述
nodeName
选择此节点的所有子节点
/
从根节点选取
//
从匹配选择的当前节点选择文档中的节点,不考虑位置
.
选择当前节点
..
选择当前节点的父节点
@
选取属性
*
匹配任何元素节点
@*
匹配任何属性节点
Node()
匹配任何类型的节点


方法2:css选择器
CSS选择器
说明
.class
.intro
选择class="intro"的所有元素
#id
#firstname
选择id="firstname"的所有元素
*
*
选择所有元素
element
p
选择所有<p>元素
element,element
div,p
选择所有<div>元素和所有<p>元素
element element
div p
选择<div>元素内的所有<p>元素
[attribute]
[target]
选择所有带有target属性的所有元素
[attribute=value]
[target=_blank]
选择target="_blank"的所有元素


方法3selenium自带的18个函数
find_element(self,by='id',value=None)
find_elements(self,by='id',value=None)
find_element_by_class_name(self,name)
find_elements_by_class_name(self,name)
find_element_by_css_selector(self,css_selector)
find_elements_by_css_selector(self,css_selector)
find_element_by_id(self,id_)
find_elements_by_id(self,id_)
find_element_by_link_text(self,link_text)
find_elements_by_link_text(self,text)
find_element_by_name(self,name)
find_elements_by_name(self,name)
find_element_by_partial_link_text(self,link_text)
find_elements_by_partial_link_text(self,link_text)
find_element_by_tag_name(self,name)
find_elements_by_tag_name(self,name)
find_element_by_xpath(self,xpath)
find_elements_by_xpath(self,xpath)

selenium定位函数的说明:
左侧和右侧的区别仅在于element的单复数;
左侧9个返回第一个符合要求的element,
右侧9个返回一个列表,包含所有符合要求的element;
第一行2个函数配合参数可以取代其他函数,例如:
find_element(by='id',value=’abc’) 等效于 find_element_by_id(‘abc’)
如果仅仅是为了获取信息的位置,还是以下2个函数比较方便:
find_element_by_xpath
find_element_by_css_selector

定位网页中的信息,还可使用BeautifulSoup4,这个我还没学,暂不表
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2020-12-15 16:25:59 | 显示全部楼层
节点示意图:

xml节点.jpg

密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-12-15 16:52:36 | 显示全部楼层
学习了!感谢楼主分享
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2020-12-16 15:25:45 | 显示全部楼层
本帖最后由 15195775117 于 2020-12-16 15:35 编辑

XPath使用示例

数据文件 superHero.xml 见附件

xpath语法规则见一楼

from scrapy.selector import Selector
with open('./superHero.xml','r')as fp:
    body=fp.read()

# x=Selector(text=body).xpath('/*').extract()
# print('全部内容:\n',x[0])

#说明:
#对于非html文档,xpath会添加html,body标签
#返回值是包括了转义字符的单元素字符串数组,例如['abcd\t\nefg']
#如果想显示出文本结构,打印x[0]即可

x=Selector(text=body).xpath('/html/body/superhero/class[1]').extract()
print('第一个class:\n',x[0],'\n')

x=Selector(text=body).xpath('/html/body/superhero/class[last()]').extract()
print('最后一个class:\n',x[0],'\n')

x=Selector(text=body).xpath('//name[@lang="en"]').extract()
print('name属性为en的数据',x[0],'\n')

x=Selector(text=body).xpath('/html/body/superhero/class[last()-1]/name/text()').extract()
print('倒数第2个class的name节点的文本:\n',x[0],'\n')

#嵌套使用:
x=Selector(text=body).xpath('/html/body/superhero/class[last()-1]').extract()
x2=Selector(text=x[0]).xpath('/html/body/class/gender/text()').extract()
x3=Selector(text=x[0]).xpath('//class/gender/text()').extract()
print('嵌套结果:',x2[0],x3[0])

输出:


第一个class:
<class>
<name lang="en">Tony Stark </name>
<alias>Iron Man </alias>
<gender>male </gender>
<birthday>1969 </birthday>
<age>47 </age>
</class>


最后一个class:
<class>
<name lang="en">Steven Rogers </name>
<alias>Captain America </alias>
<gender>male </gender>
<birthday>19200704 </birthday>
<age>96 </age>
</class>


name属性为en的数据
<name lang="en">Tony Stark </name>


倒数第2个class的name节点的文本:
Peter Benjamin Parker


嵌套结果: male  male



superHero.xml

500 Bytes, 下载次数: 0, 下载积分: 金钱 -5

密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2020-12-16 15:51:28 | 显示全部楼层
CSS选择器示例


from scrapy.selector import Selector
with open('./superHero.xml','r')as fp:
    body=fp.read()

x=Selector(text=body).css('class name').extract()
print('
<class>内的所有<name>:\n',x)
print('
<class>内第一个<name>:\n',x[0])

x=Selector(text=body).css('[lang="en"]').extract()
print('
所有属性lang="en"的节点:\n',x)

x=Selector(text=body).css('[lang]').extract()[0]
print('
第1个带[lang]属性的节点:\n',x)


结果:


<class>内的所有<name>: ['<name lang="en">Tony Stark </name>',
'<name lang="en">Peter Benjamin Parker </name>',
'<name lang="en">Steven Rogers </name>']


<class>内第一个<name>:
<name lang="en">Tony Stark </name>


所有属性lang="en"的节点:
['<name lang="en">Tony Stark </name>',
'<name lang="en">Peter Benjamin Parker </name>',
'<name lang="en">Steven Rogers </name>']


第1个带[lang]属性的节点:
<name lang="en">Tony Stark </name>


密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2021-1-13 11:10:47 | 显示全部楼层
BeautifulSoup


# -*- coding: utf-8 -*-

"""
bs4比scrapy,在接收数据和进行过滤之间,多了一道解析的过程
解析器不同,处理的数据也不同,bs官网推荐lxml作为解析器
加上这一步的优点是:可以根据输入数据的不同,进行针对式的解析
scrapy使用XPath当过滤器,BeautifulSoup查找方式更加灵活
"""
from bs4 import BeautifulSoup
import requests,chardet
from urllib import request


#获取网页编码的函数:
def getCode(url):
    response = request.urlopen(url)
    html = response.read()#返回值是网页文档的加密形式
    charset = chardet.detect(html)#对该html进行编码的获取
    #charset是一个字典
    print('网页编码是:',charset['encoding'])
    return charset['encoding']


url='https://www.dytt8.net/index.htm' #电影天堂
response = request.urlopen(url)
#设置解析器lxml,设置编码:
# soup=BeautifulSoup(response.read(),'lxml',from_encoding=getCode(url))
#response.read()与requests.get(url).text区别在于:前者是encoding,后者是decoding
#BS可以自动识别编码,默认使用lxml,以上语句可简化为:
soup=BeautifulSoup(response.read())  #获得网页的soup对象
print(soup.prettify)  #网页的decoding内容
#网页节点被解析成很多Tag,以属性、顺序、父标签的不同来区别

print(soup.ul)#第一次出现的ul标签
print(soup.title)#第一次出现的title标签
print(soup.find('li'))#第一次出现的li标签,效果与soup.li同

print(soup.find_all('li'))#所有li标签
print(soup.find_all('li')[2])#第3个li标签

print(soup.find_all('a',attrs={'href':'#'}))#输出属性href是'#'的a标签


tag=soup.ul
print('完整标签:\n\t',tag.li.a)#嵌套定位
print('href属性的内容:\n\t',tag.li.a.get('href'))
print('标签内容:\n\t',tag.li.a.get_text())



密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表