Python爬虫入门_实战电影排行榜TOP50 爬取
1.爬虫需求
爬取 https://dianying.2345.com/top/ 电影排行榜 TOP50的电影信息
2.实现效果
爬取的电影信息 写入 txt 文件,并把电影封面写入 frontCover 文件夹
爬取图片效果如下
3.多线程(线程池)代码实现
代码总体结构变化不大,主要 新增 MyThread类 继承了 threading.Thread ,并在 run 方法中 根据传入的 要下载的 list,调用了 download 方法。
在 top50_list 方法中 开始调用 多线程,在此之前 把抓取到的 url 分成了 两份,起了两个子线程分别负责一份的下载。 不多说 多线程的机制了, 以后 有机会单独写一篇文章。
# 电影排行榜 TOP50 爬取 - 改造多线程(线程池)
import os
import time
from concurrent.futures import ThreadPoolExecutor
import requests
from bs4 import BeautifulSoup
url = 'https://dianying.2345.com/top/'
def top50_list(url):
html = requests.get(url)
# encoding是从http中的header中的charset字段中提取的编码方式,
# 若header中没有charset字段则默认为ISO-8859-1编码模式,则无法解析中文,这是乱码的原因
# html.encoding = html.apparent_encoding
# 手动设置
html.encoding = 'GBK'
# print(html.encoding)
# ISO-8859-1
soup = BeautifulSoup(html.text, 'html.parser')
li_list = soup.find(class_='picList clearfix').children
li_one = []
li_tow = []
index = 0
for li in li_list:
if li.name == 'li':
if index > 25:
li_tow.append(li)
else:
li_one.append(li)
index = index + 1
# 声明线程池,并设置线程池的 最大线程数
pool = ThreadPoolExecutor(5)
# todo 此处特别注意 不能写成 download(li_one, '线程1')
args1 = [li_one, '线程1']
args2 = [li_tow, '线程2']
# 通过submit函数提交执行的函数到线程池中,submit函数立即返回任务句柄,不阻塞
t1 = pool.submit(lambda p: download(*p),args1)
print('线程1创建完成' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
t2 = pool.submit(lambda p: download(*p),args2)
print('线程2创建完成' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# cancel方法用于取消某个任务,该任务没有放入线程池中才能取消成功
# 这个任务 还在排队,没有被执行 就可以被 取消,如果在执行了 那么取消不了
print(t1.cancel())
# result方法可以获取task的执行结果,这个方法是阻塞的
print(t1.result())
# done方法用于判定某个任务是否完成
print(t1.done())
print(t2.done())
def download(li_list, name):
if name =='线程1':
time.sleep(1)
movie_list = []
for li in li_list:
print('我是' + name)
movie = {}
# 电影名称
movie['name'] = li.find(class_='sTit').text
# 电影主演阵容
star_list = li.find(class_='pActor').find_all('a')
star_str = ''
for star in star_list:
star_str = star_str + (star.text + ',')
movie['star'] = star_str
# 电影描述
movie['desc'] = li.find(class_='pTxt pIntroShow').text
movie['pic'] = li.find(class_='pic').find('img')['src']
movie_list.append(movie)
# 写入文件
with open('top50.txt', 'a+', encoding='utf-8') as f:
for item in movie_list:
f.write('电影名称:{} \t 主演阵容: {} \t {} \t 封面: {} \t \n'.format(
item['name'], item['star'], item['desc'], item['pic']
))
# 下载封面图
for item in movie_list:
result = requests.get('https:' + item['pic'])
file_name = 'frontCover/' + item['name'] + '.jpg'
if ':' in file_name:
file_name = file_name.replace(':', '')
os.makedirs(os.path.dirname(file_name), exist_ok=True)
with open(file_name, 'wb') as f:
f.write(result.content)
if name == '线程1':
print('线程1执行完成')
else:
print('线程2执行完成')
if __name__ == '__main__':
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
top50_list(url)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
适度放松,前路迷惘 停下来休息休息。 end
别人不会对你的痛感同身受,也没义务为你的过去买单,更不可能决定你的未来。
评论区