【python实战】记一次爬取下载某福利网站视频
本帖最后由 p794639 于 2021-2-22 19:22 编辑本原创帖-吾爱首发
虽然写的不是什么很高级的东西,但是剽窃可耻
小白初次发帖违规之处,敬请管理大大帮忙修改下{:1_919:}第一次接触这个,写的不好之处还请大佬指点
最近几天突然想学学爬虫,然后就去b站搜索各种视频,看到了一个实战讲解爬取某图片素材网站的小姐姐图片,小白的我就跟着做,然后网站在抓取了几次页面不知道为什么就关闭了。还没开始正式爬取网站就没了,这个如何是好,我就搜索图片或者视频的网站想找个然后来爬,在过程中看到个福利网站广告,于是就开始了这次爬虫的学习生涯,从刚写爬虫,然后一直修改到现在这个程度,总共用了俩天时间。福利网站已打码,代码拿出来大家一起学习讨论,还请大佬不吝赐教{:1_893:} :loveliness:
**实现功能:
1.主页获取不同类型子链接
2.爬取当前类型视频有多少页
3.爬取当前子链接页面所有视频地址
4.爬取完当前页面自动翻页爬取下一页视频
5.爬取视频页面下载地址
6.对各个地址进行拼接
7.对获取到的视频下载链接进行下载**
全部源代码如下:# -*- coding: utf-8 -*-
# @Time : 2021/1/19 16:35
# @AuThor: Purple soul-吾爱
# @FileName: 爬虫成品.py
importrequests,re,os,sys,time
from urllib.request import urlopen
from tqdm import tqdm
'''创建一个类'''
class Color:
def __init__(self):
self.dit1 = {}
self.downsize = 0
self.file_address=0
'''添加请求头'''
self.headers ={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
}
self.port = 'https://xxxxx.xyz'
'''子网站地址'''
self.port_1 = '/h/dalu/'
self.port_2 = '/h/rihan/'
self.port_3 = '/h/oumei/'
self.port_4 = '/h/sanji/'
self.port_5 = '/h/dongman/'
self.port_6 = '/h/tupian/'
self.port_8 = '/h/duanpian/'
'''视频下载'''
def download_from_url(self,url,moive_name,moive_num):
"""
@param: url to download file
@param: moive_name place to put the file
:return: bool
"""
# 获取文件长度
try:
file_size = int(urlopen(url).info().get('Content-Length', -1))
except Exception as e:
print(e)
print("错误,访问url: %s 异常" % url)
return False
# 判断本地文件夹是否存在
if not os.path.exists(self.dir_name):
os.makedirs(self.dir_name)
# 判断本地文件存在时
if os.path.exists(self.dir_name + '/' + moive_name + self.file_geshi):
# 获取文件大小
first_byte = os.path.getsize(self.dir_name + '/' + moive_name + self.file_geshi)
else:
# 初始大小为0
first_byte = 0
# 判断大小一致,表示本地文件存在
if first_byte >= file_size:
print("文件已经存在,无需下载")
return file_size
header = {"Range": "bytes=%s-%s" % (first_byte, file_size)}
pbar = tqdm(
total=file_size, initial=first_byte,
unit='B', unit_scale=True, desc=url.split('/')[-1])
# 访问url进行下载
time.sleep(1)
req = requests.get(url, headers=header, stream=True)
try:
with(open(self.dir_name + '/' + moive_name + self.file_geshi, 'wb')) as f:
for chunk in req.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
pbar.update(1024)
except Exception as e:
print(e)
return False
pbar.close()
return True
'''请求视频网页链接'''
def request_video_link(self):
self.title = re.findall('<p><a href="(.*?)">(.*?)</a></p>', self.html)# 获取当前页视频链接和标题
self.dir_name = re.findall("<a href='/'>.*?</a> > <a href='.*?'>(.*?)</a> > </div>", self.html)# 获取分类文件夹名称
# 将列表转换为字典
dit1 = dict(self.title)
for d in dit1.keys():
if re.match('^/h\/\w+\/', d):
movie_name = dit1
print("{:.10s}\t\t{:.60s}".format(d,dit1))#打印获取到的子链接及视频名称
file_address= requests.get(self.port + d, headers=self.headers)
file_address_html = file_address.text
# print(file_address_html)
self.file_obtain_geshi = re.findall('id=".*?">(.*?)</span><span style=".*?"', file_address_html)#获取文件格式字符串
file_address =re.findall('id=".*?">(.*?)</span><span style=".*?"', file_address_html)#得到视频下载地址
self.file_obtain_geshi = ''.join(self.file_obtain_geshi).split(".")[-1:]#对得到的地址格式进行切片
self.file_geshi ='.'+str(self.file_obtain_geshi)#在文件格式前加'.'
'''视频下载地址是单独的,所以需要获取解析地址来和视频地址拼接'''
file_address = self.file_down_address + file_address#将解析地址和获取到的视频地址拼接
# print(file_address)
self.download_from_url(file_address,movie_name,d)
'''获取下一页'''
def next_request_video_link(self):
self.request_video_link()
for url in self.urls:
self.port_page = self.port_request +url
print()
print('当前网页链接为:'+self.port_page)
self.response = requests.get(self.port_request +url, headers=self.headers)
self.html = self.response.text
self.request_video_link()
def dowm_type_choice(self):
dit = {1: '大陆', 2: '日韩', 3: '欧美', 4: '三级', 5: '动漫', 6: '图片', 7: '短片'}
print(dit)
choice_type = eval(input('请选择下载类型(输入数字1-7):'))
while not (choice_type in dit.keys()):
choice_type = eval(input('输入错误请重新输入(输入数字1-7):'))
if choice_type == 2:
self.port_request = self.port + self.port_2
self.file_down_address = 'https://xxxx.com/mp4/'
elif choice_type == 3:
self.port_request = self.port + self.port_3
self.file_down_address = 'https://xxxx.com/mp4/'
elif choice_type == 4:
self.port_request = self.port + self.port_4
self.file_down_address = 'https://xxxx.com/mp4/'
elif choice_type == 5:
self.port_request = self.port + self.port_5
self.file_down_address = 'https://xxxx.com/mp4/'
elif choice_type == 6:
self.port_request = self.port + self.port_6
self.file_down_address = 'https://xxxxx.com/mp4/'
elif choice_type == 7:
self.port_request = self.port + self.port_8
self.file_down_address = 'https://xxxxx.com/mp4/'
else:
self.port_request = self.port + self.port_1
self.file_down_address = 'https://xxxxx.com/mp4/'
self.response = requests.get(self.port_request, headers=self.headers)
self.html = self.response.text
self.urls = re.findall("<option value='(.*?)'>.*?</option>", self.html)# 获取当前类型所有子网页链接
print('当前类型为:%d :' % (choice_type), end='')
print(dit.get(choice_type))
print(self.port_request)
print('****************************开始下载****************************')
rx_seckill.next_request_video_link()
if __name__ == '__main__':
a = """
oooooooooo.o888o o888o d88b' 'P88b oo
`888' `Y8b888 888 Y8bo. .ob8Y ,"8
888 d88' 888 888 .od88bo. `Y888o..o888Y' oooo
888ooo888Y 888 888 d8' `8b `"Y8888Y"' `888
888 888. 888 888 888 888 .o888YY888o. 888
888`88b. `Y8b d88'`Y8b d88'.ob8Y Y8bo. 888
o888oo888o Y8bod8P' `88od8P' o888o o888oo888o
功能列表:
1.选择下载类型
吾爱破解论坛 http://www.52pojie.cn
"""
print(a)
rx_seckill = Color()
choice_function = input('请选择:')
if choice_function == '1':
rx_seckill.dowm_type_choice()
else:
print('没有此功能')
sys.exit(1)
效果图如下:
PS:排版较丑,还请各位见谅
https://static.52pojie.cn/static/image/hrline/1.gifhttps://static.52pojie.cn/static/image/hrline/1.gif
觉得有帮助的小伙伴给个免费的评分,十分感谢
https://static.52pojie.cn/static/image/hrline/2.gifhttps://static.52pojie.cn/static/image/hrline/2.gif
都打码了还好意思要评分。 p794639 发表于 2021-1-20 14:10
大佬可以给说说这样会写有什么问题吗
很简单,被eval执行的代码里面有恶意代码就凉凉,如非必要,绝对不要使用eval 535744567 发表于 2021-1-19 17:58
暂时用不到,但是支持一下
谢谢@535744567 p794639 发表于 2021-1-20 14:25
谢谢,学到了。不过我感觉只用来读取我键盘输入没问题吧
不建议这么做,你可以限定输入分隔符之后分割输入结果进行强制类型转换,使用eval在任何时候都可能造成难以预测的后果 p794639 发表于 2021-1-20 13:51
额,我只能说我小白,那个内置语句没学过。不过谢谢老哥指点
嗯也不错了奥利给 看的出来,写出这个 也花了不少功夫,不过你的代码 逻辑不清楚,而且还有大量的冗余代码,基本完全不符合pep8的规范,还有很大提升空间 看楼主把Python运用得很熟练谢谢分享用Python爬取的好经验 我对大码的福利网站更感兴趣 现在 用不到以后或许会用到{:1_918:} 好家伙,我直接好家伙 147369 发表于 2021-1-19 18:09
好家伙,我直接好家伙
:lol:lol写的比较low 不会把别人小网站爬崩了吧 :loveliness:欢迎各位朋友提出宝贵意见 好家伙,活学活用 佩服,不是看重结果,主要是学习{:1_886:}