【学习记录】使用多协程和队列,爬取时光网电视剧TOP100的数据

使用多协程队列,爬取时光网电视剧TOP100的数据(剧名、导演、主演和简介),并用csv模块将数据存储下来。
时光网TOP100链接:http://www.mtime.com/top/tv/top100/
(爬虫精进11)
Windows 10 系统,Python 3.7

from gevent import monkey   #从gevent库里导入monkey模块。
monkey.patch_all()  #monkey.patch_all()能把程序变成协作式运行,就是可以帮助程序实现异步。
import gevent,requests,bs4,csv,time
from gevent.queue import Queue  #从gevent库里导入queue模块

#伪装头部
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'}

start = time.time()     #记录任务开始的时间
work = Queue()      #创建队列对象,并赋值给work。
#观察时光网网址的变化,2-10页有相同的规律,第1页单独安排
for i in range(1,11):
    if i == 1:
        url_1 = 'http://www.mtime.com/top/tv/top100/'
        work.put_nowait(url_1)  #将网址放入队列
    else:
        urls = 'http://www.mtime.com/top/tv/top100/index-{}.html'.format(i)
        work.put_nowait(urls)   #将网址放入队列

def crawler():
    while not work.empty():     #当队列不是空的时候,就执行下面的程序。
        url = work.get_nowait()     #用get_nowait()函数可以把队列里的网址都取出。
        res = requests.get(url,headers=headers)     #用requests.get()函数抓取网址。
        bs  =bs4.BeautifulSoup(res.text,'html.parser')      #解析网址
        titles = bs.find_all('div',class_="mov_con")
        for title in titles:
            name = title.find('a').text
            datas = title.find_all('p')
            for data in datas:
                #需要提取的“导演”,“主演”和“简介”标签内容都一样,无法根据标签进行抓取,可以采取切片判断的方式进行提取
                if data.text[:2] == '导演':       #判断文本前2个字符是否为“导演”
                    director = data.text[3:]      #如若if条件成立,切取第3个字符后面的文本内容赋值给director,即为导演姓名,下面的主演和简介同理。
                elif data.text[:2] =='主演':
                    actors = data.text[3:]
                else:
                    content = data.text
            writer.writerow([name,director,actors,content])

csv_file = open('【FB11】01.2.0_timetop movies save.csv','w',newline='',encoding='utf-8-sig')
writer = csv.writer(csv_file)
writer.writerow(['剧名','导演','主演','简介'])

task_list = []      #创建一个空任务列表
for x in range(3):      #等同于创建了3个爬虫
    task = gevent.spawn(crawler)        #用gevent.spawn()函数创建执行crawler()函数的任务
    task_list.append(task)              #用append函数把任务添加到tasks_list的任务列表里
    #因为gevent只能处理gevent的任务对象,不能直接调用普通函数,所以需要借助gevent.spawn()来创建任务对象。
    #gevent.spawn()的参数需为要调用的函数名及该函数的参数。比如,gevent.spawn(crawler,url)就是创建一个执行crawler函数的任务,参数为crawler函数名和它自身的参数url。

gevent.joinall(task_list)       #调用gevent库里的joinall方法,启动执行所有的任务。
end = time.time()       #记录任务结束时间
print(end-start)        #计算任务执行时间并打印
csv_file.close()

queue对象的方法:

put_nowait()		#往队列里储存数据
get_nowait()		#从队列里提取数据
empty()				#判断队列是否为空
full()						#判断队列是否为空
qsize()					#判断队列还剩多少数量
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于Python 3的多协程以及队列爬取时光电视剧top100的示例代码: ```python import requests from bs4 import BeautifulSoup import asyncio import aiohttp import time from queue import Queue async def fetch(session, url): async with session.get(url) as response: return await response.text() async def parse(html): soup = BeautifulSoup(html, 'html.parser') for item in soup.select('div[class="mov_con"] ul li'): rank = item.find('span', class_='top_num').text name = item.find('span', class_='mov_title').text score = item.find('span', class_='total_score').text print(rank, name, score) async def worker(session, queue): while not queue.empty(): url = queue.get() html = await fetch(session, url) await parse(html) async def main(): urls = [f'http://www.mtime.com/top/tv/top100/index-{i+1}.html' for i in range(10)] queue = Queue() for url in urls: queue.put(url) async with aiohttp.ClientSession() as session: tasks = [asyncio.create_task(worker(session, queue)) for _ in range(10)] await asyncio.gather(*tasks) if __name__ == '__main__': start_time = time.time() asyncio.run(main()) end_time = time.time() print(f'Time used: {end_time - start_time} seconds') ``` 这段代码使用Python的asyncio库和aiohttp库来实现多协程异步爬取页,使用Python的queue模块来实现任务队列。首先,我们定义了`fetch`函数来异步获取页内容,其返回值为响应的文本内容。然后,我们定义了`parse`函数来解析页内容,提取出电视剧的排名、名称和评分,并输出到控制台。接着,我们定义了`worker`函数来作为协程的工作函数,从任务队列中取出一个URL并异步地解析该URL对应的页。最后,我们定义了`main`函数来创建任务队列,创建异步协程,以及启动异步任务。在`main`函数中,我们先创建了10个URL,然后将这些URL放入任务队列中。接着,我们使用`async with`语句创建一个异步会话,并使用`create_task`函数创建10个异步协程,每个协程都调用`worker`函数,从任务队列中取出一个URL,并异步地解析对应的页。最后,我们使用`asyncio.gather`函数等待所有的异步协程执行完毕。在程序执行结束后,我们还输出了程序的执行时间。 需要注意的是,由于时光在一定时间内会对IP进行限制,如果爬虫速度过快可能会被封禁IP,因此我们在程序中设置了一个1秒钟的延时,以避免被封禁。如果您需要更高的爬取速度,请自行调整代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值