文章目录
- 前言
- 1. 导入模块和库
- 2. 定义函数 `download_image(url, filepath)`
- 3. 定义函数 `get_page()`
- 4. 主程序入口
- 完整代码
- 运行效果
- 结束语
前言
本文主要介绍了使用Python编写的多线程爬虫程序,用于下载表情包网站上的图片。通过解析网页内容和使用XPath定位,可以获取到图片的URL,并将其保存到本地。
1. 导入模块和库
import requests
from lxml import etree
from threading import Thread
from queue import Queue
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests
:导入requests
库,它是一个用于发送HTTP请求的流行库,可以方便地进行网络通信。from lxml import etree
:从lxml
库中导入etree
模块,它用于处理XML数据,提供了一种灵活且高效的方式来解析和操作XML文档。from threading import Thread
:从threading
库中导入Thread
类,它用于创建并管理线程,可以实现多任务并发执行。from queue import Queue
:从queue
库中导入Queue
类,它是Python内置的线程安全的队列,用于在多线程环境下进行安全的数据交换。import ssl
:导入ssl
库,它提供了用于操作SSL/TLS协议的函数,用于创建和配置安全套接字。ssl._create_default_https_context = ssl._create_unverified_context
:设置SSL上下文,将验证关闭,以允许使用不受信任的证书。
2. 定义函数 download_image(url, filepath)
def download_image(url, filepath):
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'}
resp = requests.get(url, headers=headers)
with open(filepath, 'wb') as f:
f.write(resp.content)
-
headers
定义了一个字典变量,其中包含了User-Agent头信息。User-Agent头部告诉服务器发送请求的客户端程序的类型和版本号。这里使用常见的浏览器User-Agent信息,以模拟浏览器行为。 -
resp = requests.get(url, headers=headers)
发送GET请求到指定的URL,并传入了上面定义的headers。requests.get()
返回一个Response
对象,该对象包含服务器响应的内容和其他相关信息。 -
with open(filepath, 'wb') as f:
打开指定的文件路径,使用二进制模式写入文件。'wb'
表示以二进制写入模式打开文件。 -
f.write(resp.content)
将从服务器响应中获得的原始二进制数据写入文件。resp.content
获取响应的内容,其中包含了图像的二进制数据。
3. 定义函数 get_page()
def get_page():
while not q.empty():
url = q.get()
resp = requests.get(url)
e = etree.HTML(resp.text)
src_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@data-original')
name_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@title')
for src, name in zip(src_list, name_list):
end = src.split('.')[-1]
new_name = f'doutu/{name}.{end}'.replace('?', '')
print(f'正在下载{new_name}')
download_image(src, new_name)
while not q.empty():
循环直到队列q
为空。url = q.get()
从队列q
中取出一个元素,赋值给变量url
。resp = requests.get(url)
发送GET请求到指定的url
,并返回Response
对象,赋值给变量resp
。e = etree.HTML(resp.text)
使用etree.HTML()
将获取到的响应文本转换成可进行XPath查询的ElementTree
对象,赋值给变量e
。src_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@data-original')
使用XPath定位找到所有<div class="tagbqppdiv"><a><img>
标签的data-original
属性值,保存在列表src_list
中。name_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@title')
使用XPath定位找到所有<div class="tagbqppdiv"><a><img>
标签的title
属性值,保存在列表name_list
中。for src, name in zip(src_list, name_list):
遍历src_list
和name_list
中的元素,依次赋值给变量src
和name
。end = src.split('.')[-1]
将src
按照.
进行分割,取最后一个元素作为文件扩展名,赋值给end
变量。new_name = f'doutu/{name}.{end}'.replace('?', '')
根据获取到的文件名、扩展名以及固定的目录路径,拼接成新的文件路径字符串。并且移除文件名中的问号字符(如果有的话)。print(f'正在下载{new_name}')
打印提示信息,显示当前正在下载的文件名。download_image(src, new_name)
调用download_image
函数,下载并保存图片。
4. 主程序入口
if __name__ == "__main__":
q = Queue()
for i in range(1, 10):
q.put(f'https://www.fabiaoqing.com/biaoqing/lists/page/{i}.html')
for j in range(3):
t = Thread(target=get_page)
t.start()
q = Queue()
创建一个队列对象,用于存储要下载的网页URL。- 使用
for
循环将从1到9的数字作为参数拼接成网页URL,并将URL放入队列q
中。 for j in range(3):
使用for
循环创建3个线程。t = Thread(target=get_page)
创建一个线程,目标函数是get_page
函数。t.start()
启动线程,开始执行get_page
函数。
完整代码
import requests # 导入requests库,用于发送HTTP请求
from lxml import etree # 导入lxml库中的etree模块,用于处理和解析XML数据
from threading import Thread # 导入threading库中的Thread类,用于创建线程
from queue import Queue # 导入queue库中的Queue类,用于创建线程安全的队列
import ssl # 导入ssl库,用于创建和配置安全套接字
ssl._create_default_https_context = ssl._create_unverified_context # 设置SSL上下文,允许使用不受信任的证书
def download_image(url, filepath):
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'} # 定义请求头部信息,模拟浏览器访问
resp = requests.get(url, headers=headers) # 发送GET请求到指定的URL,并传入请求头部信息
with open(filepath, 'wb') as f: # 使用二进制写入模式打开指定文件路径
f.write(resp.content) # 将响应内容的二进制数据写入文件
def get_page():
while not q.empty(): # 当队列q不为空时循环执行以下操作
url = q.get() # 从队列q中获取一个元素,赋值给变量url
resp = requests.get(url) # 发送GET请求到指定的URL
e = etree.HTML(resp.text) # 将响应内容解析为可进行XPath查询的ElementTree对象,赋值给变量e
src_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@data-original') # 使用XPath定位找到所有满足条件的img标签的data-original属性值,返回一个列表
name_list = e.xpath('//div[@class="tagbqppdiv"]/a/img/@title') # 使用XPath定位找到所有满足条件的img标签的title属性值,返回一个列表
for src, name in zip(src_list, name_list): # 使用zip函数将src_list和name_list中的元素逐个配对
end = src.split('.')[-1] # 将src按照'.'进行分割,并取最后一个元素作为文件扩展名,赋值给变量end
new_name = f'doutu/{name}.{end}'.replace('?', '') # 根据获取到的文件名、扩展名以及固定的目录路径,拼接成新的文件路径字符串,并移除文件名中的问号字符(如果有的话)
print(f'正在下载{new_name}') # 打印提示信息,显示当前正在下载的文件名
download_image(src, new_name) # 调用download_image函数,下载并保存图片
if __name__ == "__main__":
q = Queue() # 创建一个线程安全的队列对象
for i in range(1, 10):
q.put(f'https://www.fabiaoqing.com/biaoqing/lists/page/{i}.html') # 将拼接好的URL放入队列q中,用于存储要下载的网页URL
for j in range(3): # 循环3次
t = Thread(target=get_page) # 创建一个线程,目标函数是get_page函数
t.start() # 启动线程,开始执行get_page函数
运行效果
结束语
多线程爬虫是一种高效的爬取网页内容的方式,在对大量图片进行下载时尤为有效。本文提供了一个简单的实例,展示了如何使用Python的requests、lxml和threading库编写多线程爬虫程序。
通过前言和代码实例,读者可以学习到如何导入必要的模块和库、定义下载图片函数、创建线程以及使用队列进行任务分配。
希望本文能够对读者理解和使用多线程爬虫程序提供一些帮助。