前言:本文章主要是通过“多线程”的高性能网络爬虫对“豆瓣网”Top250电影榜相关数据进行采集,从而提高网络爬虫采集的效率。
更多优秀文章借鉴:
导航小助手
1. 项目需求及介绍:
2. 目标网址:
3. 操作实现:
项目需求及介绍:
1.了解“多线程”爬虫操作原理。
2.了解如何将“多线程爬虫”与网络爬虫的基础知识相结合。
3.了解如何实现网络爬虫的切换网址页面原理。
4.了解如何将“多线程”爬虫采集的数据保存到json文件中。
目标网址:
https://movie.douban.com/top250
操作实现:
1.打开豆瓣电影排行榜top250,确定采集目标(电影名称、上映日期、评分等)。
2.引入queue库中的Queue()模块,然后创建队列,分别为网址队列以及内容队列;除此之外,还要引入threading库,用于创建线程。
import requests
import threading
from queue import Queue
from lxml import etree
import time
import json
import re
class DouBanFilm():
# 初始化
def __init__(self):
# 在网页中点击f12打开谷歌开发者工具,即可查看自己的用户代理以及Cookie等
self.headers = {"User-Agent":"xxx"}
self.url_queue = Queue()
self.content_queue = Queue()
3.又观察得start值的变换随页面的变化而变化(即步长为25,起始页为1,终止页为10),使用字符串格式化以及队列的put()方法,向网址队列中放入网址。
def get_url_list(self):
url_temp = "https://movie.douban.com/top250?start={}&filter="
url_list = [url_temp.format(i) for i in range(0, 226, 25)]
for url in url_list:
print("正在请求:",url)
# 将url放入网址列表(通过put)
self.url_queue.put(url)
4.使用网址队列的get()方法将队列中的网址逐个取出并发起HTTP请求,并进行源代码的提取,所以使用xpath来对目标信息进行提取,再将所采集的内容如步骤3放入内容队列。
while True:
# 从网址队列中提取出将要访问的网址
url = self.url_queue.get()
html = requests.get(url,headers=self.headers).text
5.当所有信息提取完毕并且存入内容队列时,使用网址队列的task_done()方法,发出任务已完成信号。
self.url_queue.task_done()
6.因为所存入的数据为python的字典格式,使用json格式对已存入内容的内容队列逐个提取并使用dumps()方法对相关内容解析为字符串形式并存入json文件中;并使用内容队列的task_done()方法,发出任务已完成信号。
def save_data(self):
while True:
content_list = self.content_queue.get()
with open("thread-doubanfilm.json", "a+", encoding="utf-8") as f:
f.write(json.dumps(content_list, ensure_ascii=False, indent=2))
# 内容列表发送已完成信号
self.content_queue.task_done()
7.定义run方法,这里首先创建一个线程任务列表,再将获取网址队列作为任务参数放置任务列表(1个获取网址队列线程)中,再通过循环9次,创建9个解析网页源代码获取内容的多线程,最后创建一个保存json文件线程;将以上线程放入任务列表中,创建线程格式如下。
thread_list = []
for j in range(9):
# target后加任务名,这里意为将自定义的获取数据的函数作为线程任务
t_content = threading.Thread(target=self.get_data)
# 将线程任务放入线程列表中
thread_list.append(t_content)
(8)最后在线程列表中执行线程。
# 调用t.setDaemon(True)将线程设置为守护线程,这样主线程结束时,守护线程也会随之结束
for t in thread_list:
t.setDaemon(True)
t.start()
# 查看程序运行时间
if __name__ == '__main__':
s_time = time.time()
douban=DouBanFilm()
douban.run()
e_time = time.time()
print(f"总用时:{e_time-s_time}秒")
结果演示如下图所示(可以看出,使用多线程爬取方式比传统爬取方式效率高很多):
控制台输出爬取结果:
打开json文件:
注意:需要源代码请私聊博主哦~
创作不易,请点个赞哦~