0%

Python 爬虫学习笔记(一)静态网页

Python 爬虫日常还是比较有用的,写篇笔记,以防一段时间不用忘记怎么写了。

由于笔者本身并不主攻工业工程,所以内容偏向需求导向,对于原理层面的东西进行选择性忽略。

写在前面:

静态网页和动态网页的主要区别在于内容的生成方式、更新方式、交互性、响应速度、访问特点等方面。

静态网页:

  • 内容是固定的,一旦发布到服务器,内容就不会再改变。

  • 由 HTML、CSS 和 JavaScript 等前端技术构建,不需要服务器端的脚本语言支持。

  • 交互性较差,用户无法直接在页面上进行操作以改变内容。

  • 响应速度快,容易被搜索引擎检索。

  • 每个网页都有一个固定的 URL,且网页 URL 以 .htm、.html、.shtml等常见形式为后缀。

动态网页:

  • 内容可以根据用户的输入、数据库信息或其他变量实时更新。
  • 除了前端技术外,还需要服务器端的脚本语言和数据库支持。
  • 提供更丰富的用户体验,用户可以通过表单、按钮等交互元素来影响页面内容。
  • 响应速度相对较慢,因为服务器需要执行脚本语言,查询数据库,然后生成 HTML 内容发送给客户端。

不过正如前面笔者所说,不是很注重原理层面的东西,所以这静态网页和动态网页的区分,笔者做的可能不会是那么严格。

静态网页解析:

在对网页进行爬取之前,需要先对目标网页进行内容“人为解析”。这一点无论的静态网页还是动态网页都一样。

解析方式有多种:

  • 鼠标右键网页,查看网页源代码,找到想要爬取的目标内容位置。
  • 在网页通过开发工具(F12)“查看器”中找到想要爬取的目标内容位置。

爬虫工具库:

使用 Python 爬取静态网页内容通常使用 BeautifulSoup 库。

爬虫爬取文本内容:

文本内容往往比较容易获取,因为网页上的文本往往明文存储,直接以字符串形式爬取即可。

下面,以“爬取 Acwing 题库第一页的题目名称”为例介绍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 导入库
import requests
from bs4 import BeautifulSoup

# 设置请求路径
url = 'https://www.acwing.com/problem/'

# 请求网页
response = requests.get(url)
response.encoding = 'utf-8'
print(response.text)

# 解析网页
soup = BeautifulSoup(response.text, 'html.parser')

for i in range(0,100):
news = soup.find(id='problem-title-'+str(i))
if news:
print(news.text)

url 表示爬取的目标网页地址。

response 请求网页。

response.encoding 设置爬取内容编码,主要为了处理中文乱码的问题,除了 utf-8 可能还会需要使用 gbk

BeautifulSoup(response.text, 'html.parser') 表示解析网页的方式,html.parser 为默认参数,一般而言设为这个即可。

最后是根据需要爬取的内容进行 find

观察网页源码,可以知道,Acwing 题目标题的 id 是 problem-source-i(做其它爬虫时,可能仅按 id 进行 find 会出现不同信息的 id 相同,从而导致爬取到不需要的信息,可以先将目标范围缩小,然后再在小范围内进行 find)。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 导入库
import requests
from bs4 import BeautifulSoup

# 设置请求路径
url = 'https://www.acwing.com/problem/'

# 请求网页
response = requests.get(url)
response.encoding = 'utf-8'
print(response.text)

soup = BeautifulSoup(response.text, 'html.parser')

# 解析网页
news = soup.find(class_='table-responsive')

# print(news.text)

for i in range(0,100):
new = news.find(id='problem-title-'+str(i))
if new:
print(new.text)

爬虫爬取图片内容:

图片内容的爬取相对文本信息会复杂一点点。

同样使用 BeautifulSoup。

下面以“爬取 4399 小游戏主页所有游戏头图”为例介绍。

这里以开发者工具(F12)为例,去解析网页:

开发者工具笔者觉得还有一个好处是它可以反馈选择的 HTML 代码段对应于网页中的哪一部分。

如上图所示,选择的部分会加蓝。

但是注意到,网页中的图片会存在不同的代码段中,所以不易于先划分成小部分,再细找。

不过,网页中的图片,一般以 img 标识,同时,src 一般表示图片存储的 url。使用 file.write 将图片写入 jpg 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
from bs4 import BeautifulSoup

# 设置请求路径
url = 'https://www.4399.com/'

# 请求网页
response = requests.get(url)
response.encoding = 'gbk'
soup = BeautifulSoup(response.text, 'html.parser')

# 解析网页,找到所有的图片标签
img_tags = soup.find_all('img')

# 对于每一个图片 URL,发送一个 HTTP 请求,获取图片的数据
for i, img in enumerate(img_tags):
img_url = img.get('src')

# 如果图片 URL 是相对路径,转换为绝对路径

if img_url and img_url.startswith('//'):
img_url = 'http:' + img_url

# 请求图片数据
img_response = requests.get(img_url)

# 图片的数据在响应的内容中
img_data = img_response.content

# 创建一个文件,并将图片数据写入文件
with open(f'image_{i}.jpg', 'wb') as f:
f.write(img_data)

但是,分析网页源码,发现,还有很多图片的 url 表示是 lz_src,所以还要把 lz_src 的图片也加进去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import requests
from bs4 import BeautifulSoup

# 设置请求路径
url = 'https://www.4399.com/'

# 请求网页
response = requests.get(url)
response.encoding = 'gbk'
soup = BeautifulSoup(response.text, 'html.parser')

# 解析网页,找到所有的图片标签
img_tags = soup.find_all('img')

# 对于每一个图片 URL,发送一个 HTTP 请求,获取图片的数据
for i, img in enumerate(img_tags):
img_url = img.get('src')

# 如果图片 URL 是相对路径,转换为绝对路径

if img_url and img_url.startswith('//'):
img_url = 'http:' + img_url

# 请求图片数据
img_response = requests.get(img_url)

# 图片的数据在响应的内容中
img_data = img_response.content

# 创建一个文件,并将图片数据写入文件
with open(f'image_{i}.jpg', 'wb') as f:
f.write(img_data)
else:
print(img)
img_url = img.get('lz_src')

if img_url and img_url.startswith('//'):
img_url = 'http:' + img_url
# 请求图片数据
img_response = requests.get(img_url)

# 图片的数据在响应的内容中
img_data = img_response.content

# 创建一个文件,并将图片数据写入文件
with open(f'image_{i}.jpg', 'wb') as f:
f.write(img_data)

上图是爬取的结果图。

爬虫爬取视频内容:

使用 Python 代码,自己实现的视频爬虫暂时还没有实现。

但是笔者了解到了现成的 Python 爬虫工具实现了爬取大多数网站视频的功能。

yt-dlp:

还有两个工具 you-get 和 youtube-dl,不过更新的应该是 yt-dlp 了。

是 youtube-dl 的分支,因为 youtube-dl 很早就不更新维护了。

安装使用也很简单。

安装:

pip 安装:pip install yt-dlp 即可。

FFmpeg:

FFmpeg 是一个辅助工具,有的视频网站视频和音频分开储存,FFmpeg 可以帮助合并两者。

在 Github 上下载 zip 解压,将解压后文件夹中的二进制文件(bin)添加到系统环境变量中即可。

使用:

无需登录即可访问的视频:

在 cmd 中输入命令 yt-dlp 视频url 即可。

https://www.bilibili.com/video/BV1sT411P7qN/ 为例。

执行 yt-dlp https://www.bilibili.com/video/BV1sT411P7qN/ 即可。

需要登陆才能访问的视频:

比如会员视频。

(不一定可行,可能会因为视频网站的管控而不同)

先在本地登录视频平台账户,且确保本地可以观看。

将浏览器 cookies 传入 yt-dlp,执行下载命令即可。

格式如下:

yt-dlp --cookies-from-browser firefox:/本地 firefox Profile 地址/ 视频 url

不过 cookies 涉及个人隐私,谨慎操作。

本地 firefox Profile 地址,在 win+R 中输入 %APPDATA%\Mozilla\Firefox\Profiles\ 点击确定,即可跳转到 firefox Profile 文件地址。

说在后面,不知道为什么,腾讯视频中的很多视频,使用 yt-dlp 下载会报 Warning 导致下载时非常非常慢。优酷和 B 站测试下载速度是正常。由于笔者只有腾讯视频会员,测试腾讯视频会员视频时,是可以下载的(但是由于如上不知道的原因,下载非常慢,一个几百 MB 的视频可能需要下一天,只有几百 B 每秒的速度)