使用多协程和队列,爬取时光网电视剧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() #判断队列还剩多少数量