网络爬虫指南

news2024/12/28 5:03:50

一、定义

网络爬虫,是按照一定规则,自动抓取网页信息。爬虫的本质是模拟浏览器打开网页,从网页中获取我们想要的那部分数据。

二、Python为什么适合爬虫

Python相比与其他编程语言,如java,c#,C++,python抓取网页的接口更简洁;并且有丰富的网络抓取模块。

三、爬虫库beautifulsoup

1、Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。

2、Beautiful Soup抓取数据后得到一个文档对象(beautifulsoup对象),其实也是一个复杂的树形结构文档,因此还需要解析器来解析这段文档。可以使用Python自带的html.parser进行解析,也可以使用lxml进行解析(相对于其他几种来说要强大一些)。

说明:选择使用lxml解析器解析,需要安装lxml模块,但是使用时候无需import lxml

3、模块安装

pip install bs4
pip install lxml

4、模块导入

from bs4 import BeautifulSoup

5、BeautifulSoup方法

 BeautifulSoup(markup, features)接受两个参数:

 第一个参数(markup):文件对象或字符串对象

 第二个参数(features):解析器,未指定则使用python自带的标准解析器(html.parser),但会产警告

6、 Beautiful Soup对象

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: BeautifulSoup 、Tag 、NavigableString 、Comment 。

在这里插入图片描述

6.1 BeautifulSoup对象

BeautifulSoup对象对象表示的是一个文档的全部内容。

例如:

from bs4 import BeautifulSoup  # 导入BeautifulSoup4库

f1 = open(r'D:\Document\Workspace\pywokrspace\test1\urllib_test_runoob_search.html','r',encoding='utf-8')
soup1 = BeautifulSoup(f1,'lxml')#使用lxml解析器解析
print(soup1)
f1.close()

返回的内容为Beautiful Soup对象文档,其实和html页面很类似。

<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>Python 教程 的搜索結果</title>
<meta content="noindex, follow, max-image-preview:large" name="robots"/>
<link href="https://static.runoob.com/images/icon/mobile-icon.png" rel="apple-touch-icon"/>
<meta content="菜鸟教程" name="apple-mobile-web-app-title"/>
</head>
<body>
<!--  头部 -->
<div class="col search row-search-mobile">
<form action="index.php">
<input autocomplete="off" class="placeholder" name="s" placeholder="搜索……"/>
</form>
</div>
</body>
</html>

6.2 Tag对象

1、Tag即HTML或XML中的标签对:Tag对象与XML或HTML原生文档中的tag相同。

2、获取Tag对象

步骤一:从一个beautifulsoup对象中获取指定的Tag对象,可以使用:beautifulsoup对象.标签名,要获取哪个标签的Tag对象,就传入哪个标签的标签名,它返回的是一个标签。注:当存在多个标签名相同时,这种方法返回的Tag对象是所有内容中第一个符合要求的标签。

步骤二:获取tag对象的属性,返回属性内容字典

属性说明:

  • (1)、attrs属性:指的是一个标签的属性,一个标签的属性一般是由键值对组成,属性名=值

    (2)、一个标签可能有很多个属性

    (3)、获取一个Tag对象的attrs属性,可以使用:Tag对象.attrs

    (4)、使用Tag对象的attrs属性可以把标签对的属性以字典形式返回Tag对象无属性时返回的是一个空字典

步骤三:获取到Tag对象属性后,可以继续使用使用字典方法获取标签对中的具体数据

举例说明:

from bs4 import BeautifulSoup  # 导入bs4库

html = """<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>"""
soup = BeautifulSoup(html, "lxml")  # 指定解析器
a_tag = soup.a  # 获取a标签
print("a标签的tag对象为:", a_tag)
a_tag_attrs = soup.a.attrs # 获取a标签的属性,也可先获取a标签,再获取a属性,分2步
print("a标签的tag对象的属性为:", a_tag_attrs)
a_tag_attrs_href_dict = a_tag_attrs["href"]  # 使用字典的索引
print("通过字典索引获取到的tag对象的属性"+ a_tag_attrs_href_dict)

输出:

a标签的tag对象为: <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
a标签的tag对象的属性为: {'href': 'http://example.com/tillie', 'class': ['sister'], 'id': 'link3'}
通过字典索引获取到的tag对象的属性http://example.com/tillie

6.3、NavigableString对象

1、NavigableString对象:指的是标签对中的数据

2、获取一个Tag对象中的数据(NavigableString对象),可以使用:Tag对象.string

from bs4 import BeautifulSoup  # 导入bs4库

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story A</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">Tillie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3"><!-- Elsie --></a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""

soup = BeautifulSoup(html, "lxml")  # 指定解析器,创建beautifulsoup对象
head_string = soup.head.string
p_string = soup.p.string
a_tag = soup.a
a_tag_string = a_tag.string
print("header标签中的数据为:", head_string)
print("p标签中的数据为:", p_string)
print("a标签中的数据为:",a_tag_string)

6.4 Comment对象

Comment 对象是一个特殊类型的NavigableString对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。

举例说明:

from bs4 import BeautifulSoup  # 导入bs4库

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""

soup = BeautifulSoup(html, "lxml")  # 指定解析器,创建beautifulsoup对象
print("a标签的tag对象为:", soup.a)
print("a标签内的数据为:", soup.a.string)  # a标签内的数据为一个注释

输出:

a标签的tag对象为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
a标签内的数据为:  Elsie 

6.5 补充

获取Tag对象,上面提到:使用beautifulsoup对象.标签名获取标签的Tag对象,当存在多个标签名相同时,它返回的是所有内容中第一个符合要求的标签。

获取某个指定的tag有两种情况:一种是获取指定的第一个标签(这种实际中用得很少),另一种是获取指定的全部标签对

场景一:获取指定的第一个标签

获取指定的第一个标签就是使用前面介绍的"soup对象.标签名"

这种方法总计如下:

1、获取某个标签对可以使用:soup对象.标签名

2、这种方法:只能获得整个文档中第一个符合要求的标签(存在多个一样的标签对时只会返回第一个)

3、如果想要的标签对中镶嵌了其他标签对,那么也会把里面镶嵌的标签对一起返回

4、这种方法在实际运用中发现:不能把标签名定义成变量,就是不能通过变量来批量获得一些标签对,所以这种方法有比较大的局限性

场景二:获取指定的全部标签对

1、要获取一个文档中某个指定的所有标签,就需要使用find_all()方法:BeautifulSoup对象或Tag对象都可以使用find_all()方法来找其下面的子标签

2、其参数可以是很多类型,最常用的是:传入需要获取的标签的标签名

3、find_all()方法返回的是一个由所有符合要求的标签组成的列表

举例如下:

from bs4 import BeautifulSoup

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""

soup = BeautifulSoup(html, "lxml")

tag_body = soup.find_all("p")  # 获取所有p标签的tag对象
print("p标签对为:", tag_body)

tag_a = soup.find_all("a")  # 获取所有a标签的tag对象
print("a标签对为:", tag_a)

输出:

p标签对为: [<p class="title" name="dromouse"><b>The Dormouse's story</b></p>, <p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>, <p class="story">...</p>]
a标签对为: [<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

4、上面是使用find_all()方法获取所有符合要求的tag对象组成的列表,然后可以遍历出每一个tag对象,最后获得每一个tag对象的name、attrs属性以及string

举例如下:

from bs4 import BeautifulSoup

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<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>
"""

soup = BeautifulSoup(html, "lxml")


def parse_msg(tagName):
    tags = soup.find_all(tagName)  # find_all()返回的是一个由tag对象组成的列表,因此需要遍历
    for tag in tags:
        print("标签的tag对象为为:", tag)
        print("标签的属性为:", tag.attrs)
        print("标签的数据为:", tag.string)

parse_msg("a")
parse_msg("p")

输出:

标签的tag对象为为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
标签的属性为: {'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
标签的数据为:  Elsie 
标签的tag对象为为: <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
标签的属性为: {'href': 'http://example.com/lacie', 'class': ['sister'], 'id': 'link2'}
标签的数据为: Lacie
标签的tag对象为为: <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
标签的属性为: {'href': 'http://example.com/tillie', 'class': ['sister'], 'id': 'link3'}
标签的数据为: Tillie

标签的tag对象为为: <p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
标签的属性为: {'class': ['story']}
标签的数据为: None
标签的tag对象为为: <p class="story">...</p>
标签的属性为: {'class': ['story']}
标签的数据为: ...

也可以看出:这种嵌套在里面的标签对,如果返回的是外层的tag对象,那也只能获得外层tag对象的name和attrs属性

NavigableString对象同理tag对象:

1、获取标签对中的NavigableString对象,可以使用:soup对象.标签名.string的方法来获取(跟前面name或attrs一样,只是说这里的字符串属于另一个对象)。且这种方法只会返回第一个符合要求的标签对中的字符串

2、也可以先试用find_all()的方法先找出全部符合要求的标签对,然后遍历得到每一个标签对内的字符串

另外还有

1、find()方法,find()find_all() 用法一样,区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果(即找到了就不再找,只返第一个匹配的),find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None。

2、get_text()方法:只输出tag中的文本内容

from bs4 import BeautifulSoup

markup = '<a href="http://example.com/">I linked to <i>example.com</i>点我</a>'
soup = BeautifulSoup(markup, "lxml")
print(soup)
print(soup.get_text())

3、select()方法:可以按标签查找,用的多是按标签逐层查找筛选元素

Beautiful Soup支持大部分的CSS选择器,在 TagBeautifulSoup 对象的 .select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到tag。可以按标签逐层查找到我们需要的内容,这点特别方便,就是定位,避免了单一的标签无法定位到我们所需要的内容元素。

soup.select("html head title")  #标签层级查找
soup.select("td div a")         #标签路径 td-->div-->a
soup.select('td > div > a')        #note:推荐使用这种记法

选择谷歌浏览器,右键copy --copy selector,可以得到对应的CSS选择器。如下:

在这里插入图片描述

div > a > div > span (我运行的时候发现一个问题,> 前后一定要有空格,不然会报错的)

#coding=utf-8
from bs4 import BeautifulSoup
import requests
 
#使用requests抓取页面内容,并将响应赋值给page变量
html = requests.get('https://www.qiushibaike.com/text/')
 
#使用content属性获取页面的源页面
#使用BeautifulSoap解析,吧内容传递到BeautifulSoap类
soup = BeautifulSoup(html.content,'lxml')
#我是分隔符,下面就是select()方法咯~
links = soup.select('div > a >div >span')
for link in links:
    print(link.get_text())

四、网络请求

在使用Python爬虫时,需要模拟发起网络请求访问html页面(上面案例为了方便查阅,直接赋值了一个页面),主要用到的库有requests库和python内置的urllib库,一般建议使用requests,它是对urllib的再次封装。

requests的优势:Python爬虫时,更建议用requests库。因为requests比urllib更为便捷,requests可以直接构造get,post请求并发起,一步到位,而urllib.request只能先构造get,post请求,再发起,需要分2步完成。

requests模块的使用方法见文档《Python requests模块》

五、RE模块(标准库)

在html文档中获取到的内容,可能还不够细致,比如,我们取到的是不是我们想要的链接、不是我们需要提取的邮箱数据等等,为了提取细精确的数据,需要使用正则表达式。

RE模块的使用方法见文档《Python 正则表达式》

六、案例实践

#coding=utf-8
from bs4 import BeautifulSoup
import requests
 
#使用requests抓取页面内容,并将响应赋值给page变量
html = requests.get('https://www.qiushibaike.com/text/')
 
#使用content属性获取页面的源页面
#使用BeautifulSoap解析,吧内容传递到BeautifulSoap类
soup = BeautifulSoup(html.content,'lxml')
#我是分隔符,下面就是select()方法咯~
links = soup.select('div > a >div >span')
for link in links:
    print(link.get_text())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用百度“云一朵”来分析PDF文件

PDF 文件是一种常见的文件格式&#xff0c;用于存储文档、图像和其他内容。在许多情况下&#xff0c;我们需要对 PDF 文件进行分析&#xff0c;以提取其中的信息。百度“云一朵”提供了一个 PDF 分析 API&#xff0c;可以帮助我们轻松地对 PDF 文件进行分析。 在本博客文章中&…

第15届蓝桥STEMA测评真题剖析-2023年8月20日Scratch编程中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第155讲。 第15届蓝桥第1次STEMA测评&#xff0c;这是2023年8月20日举办的STEMA&#xff0c;比赛仍然采取线上形式。这…

Java基础---第十五篇

系列文章目录 文章目录 系列文章目录一、红黑树有哪几个特征?二、说说你平时是怎么处理 Java 异常的三、说说深拷贝和浅拷贝?一、红黑树有哪几个特征? 紧接上个问题,面试官很有可能会问红黑树,下面把红黑树的几个特征列出来: 二、说说你平时是怎么处理 Java 异常的 try…

Ubuntu22.04 交叉编译gcc9.5 for arm

一、准备 环境&#xff1a;ubuntu22.04为刚刚安装&#xff0c;未安装gcc等包 vi ~/.bashrc输入 export PATH$PATH:/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin 保存,reboot 安装&#xff1a; sudo apt install cmake sudo apt install gawk sudo apt instal…

【go语言】方法

go的方法是一种作用在接收者&#xff08;某种类型的变量&#xff0c;不能是接口和指针&#xff09;上的特殊函数 方法的声明 // 类型方法接收者是值类型 func (t TypeName) MethodName (ParamList ) (Returnlist) {//method body }// 类型方法接收者是指针 func (t *TypeName…

A股上市公司数字技术创新与企业高质量发展 企业全要素生产率-5种测算方法 2000-2022

数据简介&#xff1a;全要素生产率(TFP&#xff09;也可以称之为系统生产率。指生产单位&#xff08;主要为企业&#xff09;作为系统中的各个要素的综合生产率&#xff0c;以区别于要素生产率&#xff08;如技术生产率&#xff09;。测算公式为&#xff1a;全要素生产率产出总…

解决nvm切换node版本失败的终极办法-秒杀网上99%的水文

nvm是一款强大的node多版本管理器&#xff0c;可以轻易选择你需要的node版本&#xff0c;这对win7平台简直就是超好的福音&#xff1a;可以突破node 14.15以上的安装限制。 但是nvm安装有一个巨大的坑点&#xff1a;nvm use 版本号以后&#xff0c;并没有生效&#xff0c;nvm …

2023年【R2移动式压力容器充装】模拟考试及R2移动式压力容器充装模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装模拟考试考前必练&#xff01;安全生产模拟考试一点通每个月更新R2移动式压力容器充装模拟考试题题目及答案&#xff01;多做几遍&#xff0c;其实通过R2移动式压力容器充装操作证考试很简单。 1…

概率密度函数,概率分布函数

概率密度函数&#xff1a;描述信号的取值在某个确定的取值点附近的概率的函数&#xff1b;概率分布函数的导数。 以幅值大小为横坐标&#xff0c;以每个幅值间隔内出现的概率为纵坐标进行统计分析。反映了信号落在不同幅值强度区域内的概率情况。 直方图&#xff1a;对每个幅…

【Linux】TCP的服务端(守护进程) + 客户端

文章目录 &#x1f4d6; 前言1. 服务端基本结构1.1 类成员变量&#xff1a;1.2 头文件1.3 初始化&#xff1a;1.3 - 1 全双工与半双工1.3 - 2 inet_aton1.3 - 3 listen 2. 服务端运行接口2.1 accept&#xff1a;2.2 服务接口&#xff1a; 3. 客户端3.1 connect&#xff1a;3.2 …

Pikachu靶场——不安全的文件下载(Unsafe Filedownload)

文章目录 1. Unsafe Filedownload1.1 Unsafe Filedownload1.1.1 源代码分析1.1.2 漏洞防御 1.2 不安全的文件下载防御措施 1. Unsafe Filedownload 不安全的文件下载概述&#xff1a; 文件下载功能在很多web系统上都会出现&#xff0c;一般我们当点击下载链接&#xff0c;便会…

认知智能最新研究成果

声明&#xff1a;以下内容仅代表个人对现象和本质探索&#xff0c;不代表对学术成果评价。曾有幸和马文明斯基的学生段老师和方老师一起讨论过人工智能问题。随着自己对问题进一步理解&#xff0c;刚好18年左右开始接触认知智能理论核心认知计算部分。 第一&#xff1a;算法是一…

MySQL5.7版本与8.0版本在Ubuntu(WSL环境)系统安装

目录 前提条件 1. MySQL5.7版本在Ubuntu&#xff08;WSL环境&#xff09;系统安装 1. 1 下载apt仓库文件 1.2 配置apt仓库 1.3 更新apt仓库的信息 1.4 检查是否成功配置MySQL5.7的仓库 5. 安装MySQL5.7 1.6 启动MySQL 1.7 对MySQL进行初始化 1.7.1 输入密码 …

IDM(Internet Download Manager)2024中文版下载工具软件

IDM&#xff08;Internet Download Manager&#xff09;&#xff1a;功能强大&#xff0c;下载速度快&#xff0c;支持多线程下载&#xff0c;下载过程中遇到突然断电等情况&#xff0c;可以进行断点续传&#xff0c;很多人因此而首选IDM。 优点&#xff1a; &#xff08;1&a…

车牌文本检测与识别:License Plate Recognition Based On Multi-Angle View Model

论文作者&#xff1a;Dat Tran-Anh,Khanh Linh Tran,Hoai-Nam Vu 作者单位&#xff1a;Thuyloi University;Posts and Telecommunications Institute of Technology 论文链接&#xff1a;http://arxiv.org/abs/2309.12972v1 内容简介&#xff1a; 1&#xff09;方向&#x…

多源最短路径的原理及C++实现

时间复杂度 O(n3),n是端点数。 核心代码 template<class T, T INF 1000 * 1000 * 1000> class CNeiBoMat { public: CNeiBoMat(int n, const vector<vector<int>>& edges,bool bDirectfalse,bool b1Base false) { m_vMat.assign(n, vector<…

_pickle.UnpicklingError: STACK_GLOBAL requires str

问题详情 Scaled weight_decay 0.0005 Optimizer groups: 95 .bias, 95 conv.weight, 98 other Traceback (most recent call last):File "E:\yolov7-main\train.py", line 616, in <module>train(hyp, opt, device, tb_writer)File "E:\yolov7-main\tra…

Python开发入门

Life is short, use Python. Life’s pathetic, let’s pythonic. 一、Python简介 1.1 Python语言起源 Python的创始人是吉多范罗苏姆(Guido van Rossum)&#xff0c;1989年的圣诞节&#xff0c;吉多为了打发时间&#xff0c;决定开发一个新型的基于互联网社区的脚本解释程…

留住时光、固化时间、让一瞬成为永恒——全新的真人手办定制模式,就选易模小程序制作。

如何能永远留住一瞬间&#xff1f; 有人说我可以拍摄一张照片&#xff0c;照片的问世确实给生活中许多美好的瞬间留下了可以记录的工具。但是随着时间的流逝&#xff0c;照片终究也会泛黄&#xff0c;似乎有一些记忆的温度&#xff0c;有一些岁月的棱角&#xff0c;也是照片所给…

怒刷LeetCode的第23天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;贪心算法 方法二&#xff1a;动态规划 方法三&#xff1a;回溯算法 方法四&#xff1a;并查集 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;排序和遍历 方法二&#xff1a;扫描线算法 方法…