网络爬虫之解析网页BeautifulSoup

BeautifulSoup的基本用法

安装bs4 和 lxml
bs4里面含有 BeautifulSoup

from  bs4 import BeautifulSoup

把官网的列子复制过来做案例

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

需要实列化BeautifulSoup对象

#需要实列化BeautifulSoup对象
soup = BeautifulSoup(html_doc, "lxml")

格式化输出(把HTML按照严格的缩进格式输出)

soup = BeautifulSoup(html_doc, "lxml")
 格式化输出(把HTML按照严格的缩进格式输出)
# print(soup)
# print(soup.prettify())

获取标签

#获取标签
# tag = soup.title
# print(tag)    <title>The Dormouse's story</title>

只拿到标签名

只拿到标签名
# name = tag.name
# print(name)  title

拿到正文的内容

拿到正文的内容
# str = tag.string
# print(str)    The Dormouse's story

在有多个相同的值的时候拿到第一条

在有多个相同的值的时候拿到第一条
tag = soup.p
# print(tag)  <p class="title"><b>The Dormouse's story</b></p>(重上往下)

找所有p

找所有p
tags = soup.find_all("p")
# print(len(tags))  3

指定所定的属性值 格式 属性名

# 指定所定的属性值  格式 属性名:属性值  attrs={"class": "story"}
tags = soup.find_all("p", attrs={"class": "story"})
# print(len(tags))  2

精确查找

# 精确查找 find 注: 此时要是有class 必定要改成class_ 因为与关键词重名了
tag = soup.find(class_="title")
# print(tag)   <p class="title"><b>The Dormouse's story</b></p>

查找它的上一节点

查找它的上一节点
tag = soup.title
# print(tag.parent)   <head><title>The Dormouse's story</title></head>

查找它的上一节点的标签名

# 查找它的上一节点的标签名
# print(tag.parent.name)

父节点的父节点

父亲的父亲
# print(tag.parent.parent.name)
# print(tag.parent.parent.parent.name)  [document]  最外面的是[document]所有类的父类

根据下标来 拿标签的值

# 根据下标来 拿标签的值
tag = soup.p
# ① 根据class 拿 标签值
str = tag.get("class")
# print(str)  ['title'] 数组表示有多个值


# ②
str = soup.p["class"]
# print(str)  ['title']
str = soup.a.get("id")
# print(str)  link1  id只有一个没有数组  默认第一个

获取a标签的所有属性值

# 获取a标签的所有属性值
strs = soup.a.attrs
# print(strs) {'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'} 以键值对的方式打印

三种拿去方式
1:

# 向下获取
# tag = soup.body
# print(tag)   <title>The Dormouse's story</title>
# print(tag.contents)   ["The Dormouse's story"]  获取下一级
# print(tag.children)    <list_iterator object at 0x0000022681D54088> 地址(遍历)获取下一级
# for c in tag.children:
#     print(c)  The Dormouse's story

# print(tag.descendants)   子孙节点
# for c in tag.descendants:
#     print(c)   #查询到所有子孙节点   空格逗号都是
#     print("*"*20)

2:

# 从下往上找上一节点
# print(soup.title.parent.name)  head

# print(soup.title.parents.name)
# 向上查找所有父节点
# for p in soup.title.parents:
#     print(p.name)
# head
# html
# [document]

3:


# 平行拿取
tag = soup.a
# print(tag.next_sibling.next_sibling.name)   a

BeautifulSoup综合案例:

爬取“猫眼电影的排行榜”

"""
BeautifulSoup综合案例:爬取“猫眼电影的排行榜”
"""

import requests
from bs4 import BeautifulSoup
import os

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}

response = requests.get("https://maoyan.com/board/4", headers=headers)
if response.status_code == 200:
    print(response.text)

# 解析网页
soup = BeautifulSoup(response.text, "lxml")
imgTag = soup.find_all("img", attrs={"class": "board-img"})


# 获取当前根目录
root = os.getcwd()

# 在根目录中创建文件夹"第一页"

os.mkdir("第一页")

# 改变但当前目录


for imgTags in imgTag:
    # print(imgTags)  注: 在这个时候可能打印的和原本的不一致 所有需要打印出来对印上
    name = imgTags.get("alt")
    src = imgTags.get("data-src")


    # 在次下载一次
    resp = requests.get(src,headers=headers)
    # 保存
    with open(f"{name}.png", "wb") as f:
        f.write(resp.content)
    print(f"{name}{src} 保存成功")

在这里插入图片描述

爬取"最好大学网"排行

"""
BeautifulSoup综合案例
爬取"最好大学网"排行
"""
import requests
from bs4 import BeautifulSoup
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}


response = requests.get("http://www.zuihaodaxue.com/zuihaodaxuepaiming2019.html", headers=headers)
response.encoding = "utf-8"
if response.status_code == 200:
  soup = BeautifulSoup(response.text, "lxml")
  trTags = soup.find_all("tr", attrs={"class": "alt"})
  for trTag in trTags:
      id = trTag.contents[0].string
      name = trTag.contents[1].string
      addr = trTag.contents[2].string
      sro = trTag.contents[3].string
      print(f"{id} {name} {addr} {sro}")


在这里插入图片描述

版权声明:本文为what_to原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/what_to/article/details/102980746

智能推荐

Android VIEW简单绘图

画布canvas 提供两个构造函数: Canvas():创建一个空的Canvas对象 Canvas(Bitmap bitmap):创建一个以bitmap位图为背景的Canvas 常用的Canvas方法: void drawBitmap(Bitmap bitmap,float left,float top,Paint paint):在指定坐标绘制位图 void drawLine(float star...

数据去重的各种方法汇总(三)

Pandas去重DataFrame 接上篇,这篇就剩最后的用Pandas对DataFrame里面的数据去重,这里也有两种方法,可以直接看官方文档(但是掌柜觉得其实就是一种方法,因为第一种只是显示哪些重复。。。): 使用duplicated方法,它会返回一个布尔向量,其长度为行数,表示行是否重复,但是并不会删除重复数据。来看实例: 然后会得到这样一个表格: 现在使用duplicated方法: 会得到...

Linux环境下RabbitMQ消息队列的安装和配置

一、什么是RabbitMQ? RabbitMQ就是一个在AMQP基础上实现的企业级消息系统,简单的说,就是一个消息队列系统。具体的介绍,可以网上去搜!目前只介绍RabbitMQ在Linux系统的安装。 二、RabbitMQ的安装 1、 RabbitMQ是基于Erlang开发,所以使用之前必须安装Erlang语言开发包。 wget http://www.erlang.org/download/otp...

train_test_split切分数据集工具

顾名思义,这是一个切分训练集与测试集的工具   如果我们不使用,而是手动进行划分,要么进行简单的操作——划去前80%为训练集,后20%为测试集,这样会带来很多的问题,因为这样做,我们切出来的会让训练集和测试集的分布很不一致,我们可以看一下简单粗暴方法切出来的分布图: 红色的训练集,蓝色是测试集(点击图片放大可以看得很清楚,直接看博客好像图片模糊)   然...

shell编程第一节 和shell

shell编程看的博客感觉写的挺好的:http://www.cnblogs.com/dongying/p/6262935.html 以及  https://www.cnblogs.com/clsn/p/8028337.html#auto_id_0 简单总结:shell编程就是对一堆Linux命令的逻辑化处理。 chmod +x hello_world.sh ./hello_world.s...

猜你喜欢

微信开发:js sdk 分享(java)

今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入。 1.需要绑定域名(注意:设置js安全域名的时候,需要设置微信ip白名单,ip白名单新出来的,非白名单内的ip无法获取access_token 更无法获取jsapi) 在设置js 安全域名在 设置–>公众号设置–>功能设置里边 appid appSercret 在开发–>...

js--HTML美术馆

前言 因为之前库房合作的时候交给我一个任务,就是在点击某一项物品的时候显示出几张相印的小图片,然后点击小图片之后显示出一张大图片,因为当时还没有接触JavaScript,所以这方面的知识不是很了解,一直拖着,大概有两天吧,是在是解决不了,于是将这个任务交给了老付和建华,今天在学习JavaScript的时候突然之后就看到了有这么一项功能,于是就有感而发。 内容 首先向大家展示代码。 这部分是HTML...

Jenkins持续集成环境部署(入门篇)

为什么要持续集成 持续集成是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。 价值: 1、减少风险 一天中进行多次的集成,并做了相应的测试,有利于检查缺陷,了解软件的健康状况,减少假定。 2、减少重复过程 节省时间、费用和工作量,通过自动化的持...

linux 下rabbitmq的安装以及设置远程用户访问

安装过程中会有提示,一路输入“y”即可。 完成后安装RabbitMQ: 3.自己建个文件夹 进行下载安装也可  直接执行也可 先下载rpm: 完成后启动服务: 可以查看服务状态: 这里可以看到log文件的位置,转到文件位置,打开文件: 这里显示的是没有找到配置文件,我们可以自己创建这个文件 编辑内容如下: 这里的意思是开放使用,rabbitmq默认创建的用户gue...

Java工程师成长修炼手册:01--Java基础特性和字符串

一.三大特性 1.封装 封装,把对象的属性封装起来(使用private修饰符),不被外部程序直接随意调用或修改成员变量。只能通过对象使用public修饰符的set 和 get 方法,来设置和获取成员变量的值。也可以把只在本类内部使用的方法使用 private。另外,还可以封装,隐藏一些方法,需要用的时候,就调用这些方法。这些就是封装。 封装的优点 良好的封装能够减少耦合,可以独立地开发、优化和修改...