p794639 发表于 2021-1-19 17:55

【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

hjlost 发表于 2021-1-19 18:41

都打码了还好意思要评分。

whisperbb 发表于 2021-1-20 14:13

p794639 发表于 2021-1-20 14:10
大佬可以给说说这样会写有什么问题吗

很简单,被eval执行的代码里面有恶意代码就凉凉,如非必要,绝对不要使用eval

p794639 发表于 2021-1-19 18:10

535744567 发表于 2021-1-19 17:58
暂时用不到,但是支持一下

谢谢@535744567

whisperbb 发表于 2021-1-20 14:47

p794639 发表于 2021-1-20 14:25
谢谢,学到了。不过我感觉只用来读取我键盘输入没问题吧

不建议这么做,你可以限定输入分隔符之后分割输入结果进行强制类型转换,使用eval在任何时候都可能造成难以预测的后果

UNITY1 发表于 2021-1-20 14:04

p794639 发表于 2021-1-20 13:51
额,我只能说我小白,那个内置语句没学过。不过谢谢老哥指点

嗯也不错了奥利给

UNITY1 发表于 2021-1-20 13:35

看的出来,写出这个 也花了不少功夫,不过你的代码 逻辑不清楚,而且还有大量的冗余代码,基本完全不符合pep8的规范,还有很大提升空间

寒冰流火 发表于 2021-1-20 08:25

看楼主把Python运用得很熟练谢谢分享用Python爬取的好经验

ilavac 发表于 2021-1-19 19:14

我对大码的福利网站更感兴趣

buluo987 发表于 2021-1-19 18:03

现在 用不到以后或许会用到{:1_918:}

535744567 发表于 2021-1-19 17:58

147369 发表于 2021-1-19 18:09

好家伙,我直接好家伙

p794639 发表于 2021-1-19 18:10

147369 发表于 2021-1-19 18:09
好家伙,我直接好家伙

:lol:lol写的比较low

基督山 发表于 2021-1-19 18:12

不会把别人小网站爬崩了吧

p794639 发表于 2021-1-19 18:14

:loveliness:欢迎各位朋友提出宝贵意见

woshicp 发表于 2021-1-19 18:14

好家伙,活学活用

逸清尘ceo 发表于 2021-1-19 18:15

佩服,不是看重结果,主要是学习{:1_886:}
页: [1] 2 3 4 5 6 7
查看完整版本: 【python实战】记一次爬取下载某福利网站视频