L3&L4 第一个爬虫项目
L3&L4 第一个爬虫项目
1 爬虫的基本步骤
向服务器发送请求-解析网页中源代码-提取数据-保存数据
- 向网页发送请求,获取网页源代码;
- 导入新的模块,解析网页源代码;
- 查看网页中的数据节点;
- 解析内容,提取节点的数据;
- 学习查找节点的方法,提取节点中的内容。
2 获取网页源代码
想要获取网页中的数据,首先要获取网页 HTML 代码,再把数据从中提取出来。
我们要向网页的服务器发送请求,服务器返回的响应就是网页 HTML 代码。
# TODO 使用import导入requests模块
import requests
# TODO 将URL地址赋值给变量url
url="https://www.baidu.com"
# TODO 将变量url传入requests.get(),赋值给response
response=requests.get(url)
# TODO 使用print输出response
print(response)
3 解析网页源代码
3-1 节点
对于一个网页的节点来说,它可以定义id、class或其他属性,而且节点之间还有层级关系。
我们可以借助网页节点的结构和属性,提取想要的信息。
网页中的每个部分都可以叫做节点。例如:html标签(例如:<h1>标签、<p>标签)、属性、文本等都是一个节点。
3-2 解析工具——BeautifulSoup
BeautifulSoup 是 Python 的一个 HTML 或 XML 的解析模块,可以用它来从网页中提取想要的数据。
BeautifulSoup不是一个内置模块,所以在使用前要先通过代码 pip install bs4 在终端中进行安装。
如果在自己电脑上安装不上或安装缓慢,可在命令后添加 pip install bs4 -i https://mirrors.aliyun.com/pypi/simple/ 进行加速
3-3 lxml 解析器
网络爬虫的最终目的就是过滤选取网络信息,最重要的部分可以说是解析器。解析器的优劣决定了爬虫的速度和效率。
Beautiful Soup 官方推荐我们使用的是 lxml 解析器,原因是它具有更高的效率,所以我们也将采用lxml解析器。
lxml 不是一个内置模块,所以在使用前要先通过代码 pip install lxml 在终端中进行安装。
如果在自己电脑上安装不上或安装缓慢,可在命令后添加 pip install lxml -i https://mirrors.aliyun.com/pypi/simple/ 进行加速。
3-4 创建BeautifulSoup对象
soup = BeautifulSoup(html, "lxml")
第一个参数
是需要解析的 HTML 文本,在这里我们传入变量 html。
第二个参数
是解析器的类型,这里我们使用的是lxml。
# 使用import导入requests模块
import requests
# 从bs4中导入BeautifulSoup
from bs4 import BeautifulSoup
# 将URL地址赋值给变量url
url = "https://www.baidu.com"
# 将变量url传入requests.get(),赋值给response
response = requests.get(url)
# 将服务器响应内容转换为字符串形式,赋值给html
html = response.text
# TODO 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup=BeautifulSoup(html,"lxml")
# TODO 使用print输出soup
print (soup)
4 解析内容,提取节点的数据
4-1 定位内容所在节点,查看提取内容在源代码中的位置;
文本所在的位置,是包含在<em>XXX</em>这样的节点中,它们都有相同的标签。
我们可以使用 BeautifulSoup 中的 find_all() 函数,获取所有符合指定条件的节点。
4-2 使用find_all() 函数,在代码中查找节点
ps = soup.find_all(name = "h1")
find_all(name=“标签”) 根据标签名查询节点
如果想要获取h1标签所在的节点,可以传入name参数,其参数值为h1 。
name 可以省略,也可以直接传入参数值。
输出的结果是包含所有 h1 节点的列表。
# 使用import导入requests模块
import requests
# 从bs4中导入BeautifulSoup
from bs4 import BeautifulSoup
# 将URL地址赋值给变量url
url = "https://www.baidu.com"
# 将变量url传入requests.get(),赋值给response
response = requests.get(url)
# 将服务器响应内容转换为字符串形式,赋值给html
html = response.text
# 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup = BeautifulSoup(html, "lxml")
# TODO 使用find_all()查询soup中head的节点,赋值给content_all
content_all=soup.find_all(name="head")
# TODO 使用print输出content_all
print (content_all)
4-3 获取标签内容
# 使用import导入requests模块
import requests
# 从bs4中导入BeautifulSoup模块
from bs4 import BeautifulSoup
# 将URL地址赋值给变量url
url = "https://www.icourse163.org/"
# 将变量url传入requests.get(),赋值给response
response = requests.get(url)
# 将服务器响应内容转换为字符串形式,赋值给html
html = response.text
# 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup = BeautifulSoup(html, "lxml")
# 使用find_all()查询soup中div的节点,赋值给content_all
content_all = soup.find_all(name="div")
# TODO for循环遍历content_all
for content in content_all:
# TODO 获取每个节点中标签内的内容,赋值给contentString
contentString=content.string
# TODO 使用print输出不为None的contentString
if content.string!=None:
print (contentString)
5 学习查找节点的方法,提取节点中的内容
5-1 string属性
.string 属性只能提取单个节点或节点统一的内容。
提取单个节点内容:
例如
<p><em>这是一个段落</em></p>
p 节点包含一个子节点 em ,由于 p 节点有且只有一个子节点,使用 .string 属性时,会输出 em 节点的 .string 内容。
提取节点包含多个子节点时:
当定位的节点中同时包含了多个子节点时,其中有节点是 em 标签内容,其他节点是纯文字。
使用 .string 属性时,不清楚应该调用哪个节点的内容,会返回None值。
# 定义html
html = """
<p>
<em>网络爬虫</em>
这是一个段落
</p>"""
# 从bs4中导入BeautifulSoup模块
from bs4 import BeautifulSoup
# 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup = BeautifulSoup(html, "lxml")
# 使用find_all()查询soup中p节点,赋值给content_all
content_all = soup.find_all(name="p")
# for循环遍历content_all
for content in content_all:
# TODO 获取每个节点中标签内的内容,赋值给contentString
content_all=soup.find_all(name="p")
contentString=content.string
# 使用print输出contentString
print(contentString)
5-2 text属性
遇到节点中既包含其他节点,也有文字时,可以使用 .text 属性来提取内容。
.text 属性能直接提取该节点中的所有文字,并返回字符串格式。
# 定义html
html = """
<p>
<em>网络爬虫</em>
这是一个段落
</p>"""
# 从bs4中导入BeautifulSoup模块
from bs4 import BeautifulSoup
# 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup = BeautifulSoup(html, "lxml")
# 使用find_all()查询soup中p节点,赋值给content_all
content_all = soup.find_all(name="p")
# for循环遍历content_all
for content in content_all:
# TODO 获取节点内的全部内容,赋值给contentString
contentString = content.text
# 使用print输出contentString
print(contentString)
6 练习
爬虫去请求网页响应,获取 5 页中全部的用户昵称。
该如何翻页呢? 5 个网页链接大部分内容是相同的,每翻一页page后面的增加1。
第一页:https://www.qiushibaike.com/text/page/1/
第五页:https://www.qiushibaike.com/text/page/5/
整理下思路:
- 导入requests和bs4模块;
- 使用for循环和格式化字符串的知识,获取5页的URL;
例如:url = f"https://www.qiushibaike.com/text/page/{num}/" - 将url参数,添加进requests.get()中,获取网页HTML代码;
- 创建一个BeautifulSoup对象,使用find_all()函数获取节点;
- 调用.string属性,获取每个节点中标签内的内容。
# TODO 使用import导入requests模块
import requests
# TODO 从bs4中导入BeautifulSoup模块
from bs4 import BeautifulSoup
# TODO 使用for循环遍历,range()函数生成的1-5的数字
for num in range(1,6):
# TODO 利用格式化字符生成串网站链接,赋值给变量url
url = f"https://www.qiushibaike.com/text/page/{num}/"
# TODO 将变量url传入requests.get(),赋值给response
response=requests.get(url)
# TODO 将服务器响应内容转换为字符串形式,赋值给html
html=response.text
# TODO 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup=BeautifulSoup(html,"lxml")
# TODO 使用find_all()查询soup中h2的节点,赋值给name_all
name_all=soup.find_all(name="h2")
# TODO for循环遍历name_all
for name in name_all:
# TODO 获取每个节点中标签内的内容,赋值给name
name = name.string
# TODO print输出name
print(name)