BeautifulSoup,CSS选择器

BeautifulSoup

数据解析原理:
1.标签定位
2.提取标签、标签属性中存储的数据
from bs4 import BeautifulSoup
import lxml
1.将本地的html文件中的数据加载
	fp=open(filename,'r',encoding='utf-8')
	res=BeautifulSoup(fp,'lxml') 						#返回BeautifulSoup对象
2.将互联网上获取的页面源码加载
	page_text=response.text
	res=BeautifulSoup(page_text,'lxml')

BS对象的一些方法属性

节点选择器res.tagName 核心就是先选择节点得到Tag类型的数据,然后调用一系列属性提取信息。

url = 'https://www.baidu.com/'
r = requests.get(url, headers=header)
res = BeautifulSoup(r.text, 'lxml')
print(res.p)  				# res.tagName  返回html中第一个tagName标签  tagName可以是(div,a,b,li,p等任意标签),是tag类型数据

#print(res.p.string)    	# res.tagName 是一个tag类型的数据,可以调用其string属性来获取tagName节点内的文本。
#print(res.p.attrs)			# 可以用tag类的 attrs属性来获取节点的所有属性(class,href,id等等),返回一个由属性名和属性值构成的字典。

#print(res.p.a)				# 返回第一个p标签下面的第一个a标签。html中<p>节点内包含<a>节点,如果<a>还包含别的节点,还可以继续选择,这就是所谓的嵌套选择。
#print(res.p['class'])


运行结果:
<p class="lh"><a class="text-color" href="//home.baidu.com" target="_blank">关于百度</a></p>
关于百度								# p标签中的文本信息
{'class': ['lh']}					# p标签的所有属性
<a class="text-color" href="//home.baidu.com" target="_blank">关于百度</a>
['lh']

方法选择器

print(res.find('p'))  # .find('tagName')等同于.tagName 也是第一个
print(res.find('p', class_='article container'))  #找到属性值class为article container的p标签,也可用别的属性值如:id,attr来定位。
print(res.find_all('p'))   # 返回所有的p标签  返回的是一个列表,列表中每一个元素均是一个Tag类型, 也可以做属性定位。
print(res.find_all(class_="lh"))          # 返回所有属性值class为lh的标签
print(res.find_all(class_="lh")[1].a['href'])  # p标签下的 a标签的属性值 href

运行结果:
<p class="lh"><a class="text-color" href="//home.baidu.com" target="_blank">关于百度</a></p>
None
[<p class="lh"><a class="text-color" href="//home.baidu.com" target="_blank">关于百度</a></p>, 
<p class="lh"><a class="text-color" href="http://ir.baidu.com" target="_blank">About Baidu</a></p>, 
<p class="lh"><a class="text-color" href="//www.baidu.com/duty" target="_blank">使用百度前必读</a></p>, 
<p class="lh"><a class="text-color" href="//help.baidu.com" target="_blank">帮助中心</a></p>, 
<p class="lh"><a class="text-color" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11000002000001" target="_blank">京公网安备11000002000001</a></p>, 
<p class="lh"><a class="text-color" href="https://beian.miit.gov.cn" target="_blank">京ICP证030173</a></p>, 
<p class="lh"><span class="text-color">©2021 Baidu </span></p>, 
<p class="lh"><span class="text-color">互联网药品信息服务资格证书 ()-经营性-2017-0020</span></p>, 
<p class="lh"><a class="text-color" href="//www.baidu.com/licence/" target="_blank">信息网络传播视听节目许可证 0110516</a></p>]

[<p class="lh"><a class="text-color" href="//home.baidu.com" target="_blank">关于百度</a></p>, 
<p class="lh"><a class="text-color" href="http://ir.baidu.com" target="_blank">About Baidu</a></p>, 
<p class="lh"><a class="text-color" href="//www.baidu.com/duty" target="_blank">使用百度前必读</a></p>, 
<p class="lh"><a class="text-color" href="//help.baidu.com" target="_blank">帮助中心</a></p>, 
<p class="lh"><a class="text-color" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11000002000001" target="_blank">京公网安备11000002000001</a></p>, 
<p class="lh"><a class="text-color" href="https://beian.miit.gov.cn" target="_blank">京ICP证030173</a></p>, 
<p class="lh"><span class="text-color">©2021 Baidu </span></p>, 
<p class="lh"><span class="text-color">互联网药品信息服务资格证书 ()-经营性-2017-0020</span></p>, 
<p class="lh"><a class="text-color" href="//www.baidu.com/licence/" target="_blank">信息网络传播视听节目许可证 0110516</a></p>]

http://ir.baidu.com
r = requests.get(url, headers=header)
res = BeautifulSoup(r.text, 'lxml')
print(res.div.text)							# text和 get_text()可以获取某一标签下的所有文本内容, string只可以获取该标签下直系的文本内容

CSS选择器

CSS选择器可以精确的定位到节点树中的每一个节点,从而我们在对数据进行筛选的时候可能会用到CSS选择器。

CSS选择器最常用的三种筛选方式分别为id、class(属性)和标签名筛选。
#开头代表选择id,(.)开头代表选择class。
>表示一个层级, 空格表示多个层级。

选择class = home 的<a>标签:a.home
选择id = game的<a>标签:a#game
res.select('.tang')   				#返回的是列表,返回属性值class为tang的标签
res.select('.tang > ul a')[0]       #和 ul标签相邻,ul标签和 a标签之间有其他标签,并不相邻。

爬豆瓣top电影

要爬取的网页为:https://movie.douban.com/top250

得到正则提取来的数据后,由于每部电影的数据 information[2] 都含有一些不相关的字符以及 各个电影在这块儿的数据格式问题也都有所差异,在这块儿的数据会遇见几种不同的问题,所以要进行专门的处理。

要爬取的数据的网页结构(源码):

在这里插入图片描述

代码

def get_html(url):
    try:
        html = requests.get(url, headers=header)
        return html.text
    except requests.exceptions.RequestException:   			#包含了所有的 requests 请求异常
        print(url, '请求失败')


def parse_html(html):
    # 进行解析提取
    pattern = '''<li>.*?<em class="">(.*?)</em>.*?<span class="title">(.*?)</span>.*?<p class="">(.*?) </p>.*?<div class="star">.*?property="v:average">(.*?)</span>.*?<span>(.*?)</span>.*?<span class="inq">(.*?)</span>.*?</li>'''
    informations = re.findall(pattern, html, re.S)  		#informations列表每一个元素是一个元组,是一部电影的全部信息
    datas = []												#datas里每一个元素是一个字典,一个元素里是一部电影的全部信息
    #对提取的数据进行一些处理
    for information in informations:
        info = re.sub('\s', '', information[2])				# 去除空白
        info = re.sub('&nbsp;', '', info)                   # 去除字符串 '&nbsp'
        info = re.sub('...<br>', '', info)
        infos = info.split('/')                				# infos装的是导演主演,时间,国家,电影类别
        if len(infos) == 3:
            infos.append(infos[2])
            infos[2] = infos[1]
        infos[1] = re.sub('\D', '', infos[1])               #infos[1]里是上映时间,所以把非数字删除
        if infos[1] == '':
            infos[1] = infos[0][-4:-1] + infos[0][-1]
            infos[0] = re.sub('\d', '', infos[0])
        while (len(infos) > 4):                             # 处理像电影 无间道 那样的数据
            del infos[1]
        data = {
            '电影排名': information[0],
            '电影名称': information[1],
            '导演及主演': infos[0],
            '上映时间': infos[1],
            '上映地点': infos[2],
            '电影类型': infos[3],
            '评分': information[3],
            '评价人数': information[4],
            '推荐语': information[5]
        }
        datas.append(data)
    return datas


if __name__ == '__main__':
    url = 'https://movie.douban.com/top250?start=0&filter='     # start参数可以修改一次递增25
    html = get_html(url)
    datas = parse_html(html)
    for data in datas:
        for key, value in zip(data.keys(), data.values()):
            print(key + ':' + value)
        print('\n')

运行结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对程序作几点说明:

def parse_html(html):
    '''Parse the HTML and extract the information you need'''

    pattern = '''<li>.*?<em class="">(.*?)</em>.*?<span class="title">(.*?)</span>.*?<p class="">(.*?) </p>.*?<div class="star">.*?property="v:average">(.*?)</span>.*?<span>(.*?)</span>.*?<span class="inq">(.*?)</span>.*?</li>'''
    informations = re.findall(pattern, html, re.S)
    for information in informations:
        fir_=re.sub('\s','',information[2])
        sec_=re.sub('&nbsp;','',fir_)
        thi_=re.sub('...<br>','',sec_)
        this_=thi_.split('/')
        print(this_)


if __name__ == '__main__':
    url = 'https://movie.douban.com/top250?start=0&filter='
    html = get_html(url)
    parse_html(html)

运行结果:
在这里插入图片描述

我们可以发现,在对 information[2] 作了一些处理后,仍存在一些问题,红线和红圈的数据都是有一些问题的,需要进行进一步处理,所以需要继续解决问题。

		if len(infos) == 3:
            infos.append(infos[2])
            infos[2] = infos[1]
        infos[1] = re.sub('\D', '', infos[1])               #infos[1]里是上映时间,所以把非数字删除
        if infos[1] == '':
            infos[1] = infos[0][-4:-1] + infos[0][-1]
            infos[0] = re.sub('\d', '', infos[0])
        while (len(infos) > 4):                             # 处理像电影 无间道 那样的数据
            del infos[1]
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值