当前位置 主页 > 网站技术 > 代码类 >

    Python3.x+迅雷x 自动下载高分电影的实现方法

    栏目:代码类 时间:2020-01-12 15:09

    快要过年了,大家都在忙些什么呢?一到年底公司各种抢票,备年货,被这过年的气氛一烘,都归心似箭,哪还有心思上班啊。归心似箭=产出低下=一行代码十个错=无聊。于是想起了以前学过一段时间的Python,自己平时也挺爱看电影的,手动点进去看电影详情然后一部一部的去下载太烦了,何不用Python写个自动下载电影的工具呢?诶,这么一想就不无聊了。以前还没那么多XX会员的时候,想看看电影都是去XX天堂去找电影资源,大部分想看的电影还是有的,就它了,爬它!

    话说以前玩Python的时候爬过挺多网站的,都是在公司干的(Python不属于公司的业务范围,纯属自己折腾着好玩),我那个负责运维的同事天天跑过来说:你又在爬啥啊,你去看看新闻,某某爬东西又被抓了!出了事你自己负责啊!哎呀我的娘亲,吓的都没继续玩下去了。这个博客是爬取某天堂的资源(具体是哪个天堂下面的代码里会有的),会不会被抓啊?单纯的作为技术讨论,个人练手,不做商业用途应该没事吧?写到这里小手不禁微微颤抖...

    得嘞,死就死吧,我不入地狱谁入地狱,先看最终实现效果:

    如上,这个下载工具是有界面的(牛皮吧),只要输入一个根地址和电影评分,就可以自动爬电影了,要完成这个工具需要具备以下知识点:

    PyCharm的安装和使用 这个不多说,猿们都懂,不属于猿类的我也没办法科普了,就是个IDE tkinter 这是个Python GUI开发的库,图中这个简陋的可怜的界面就是基于TK开发的,不想要界面也可以去掉,丝毫不影响爬电影,加上用户界面可以显得屌一点,当然最主要的是我想学习一点新知识静态网页的分析技巧 相对于动态网站的爬取,静态网站的爬取就显得小菜了,F12会按吧,右键查看网页源代码会吧,通过这些简单的操作就可以查看网页的排版布局规则,然后根据这些规则写爬虫,soeasy 数据持久化 已经下载过的电影,下次再爬电影的时候不希望再下载一次吧,那就把下载过的链接存储起来,下载电影之前去比对是否下载过,以过滤重复下载 迅雷X的下载安装 这个就更不用多说了,作为当代社会主义有为青年,谁没用过迅雷?谁的硬盘里没有几部动作类型的片子?

    差不多就这些了,至于实现的技术细节的话,也不多,requests+BeautifulSoup的使用,re正则Python数据类型Python线程dbm、pickle等数据持久化库的使用,等等,这个工具也就这么些知识范畴了。当然,Python是面向对象的,编程思想是所有语言通用的,这个不是一朝一夕的事,也没办法通过语言描述清楚。各位对号入座,以上哪个知识面不足的自己去翻资料学习,我可是直接贴代码的。

    说到Python的学习还是多说两句吧,以前学习Python爬虫的时候看的是 @工匠若水 https://blog.csdn.net/yanbober的博客,这哥们的Python文章写的真不错,对于有过编程经验却从没接触过Python的人很有帮助,基本上很快就能上手一个小项目。得嘞,撸代码:

    import url_manager
    import html_parser
    import html_download
    import persist_util
    from tkinter import *
    from threading import Thread
    import os
     
    class SpiderMain(object):
      def __init__(self):
        self.mUrlManager = url_manager.UrlManager()
        self.mHtmlParser = html_parser.HtmlParser()
        self.mHtmlDownload = html_download.HtmlDownload()
        self.mPersist = persist_util.PersistUtil()
     
      # 加载历史下载链接
      def load_history(self):
        history_download_links = self.mPersist.load_history_links()
        if history_download_links is not None and len(history_download_links) > 0:
          for download_link in history_download_links:
            self.mUrlManager.add_download_url(download_link)
            d_log("加载历史下载链接: " + download_link)
     
      # 保存历史下载链接
      def save_history(self):
        history_download_links = self.mUrlManager.get_download_url()
        if history_download_links is not None and len(history_download_links) > 0:
          self.mPersist.save_history_links(history_download_links)
     
      def craw_movie_links(self, root_url, score=8):
        count = 0;
        self.mUrlManager.add_url(root_url)
        while self.mUrlManager.has_continue():
          try:
            count = count + 1
            url = self.mUrlManager.get_url()
            d_log("craw %d : %s" % (count, url))
            headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36',
              'Referer': url
            }
            content = self.mHtmlDownload.down_html(url, retry_count=3, headers=headers)
            if content is not None:
              doc = content.decode('gb2312', 'ignore')
              movie_urls, next_link = self.mHtmlParser.parser_movie_link(doc)
              if movie_urls is not None and len(movie_urls) > 0:
                for movie_url in movie_urls:
                  d_log('movie info url: ' + movie_url)
                  content = self.mHtmlDownload.down_html(movie_url, retry_count=3, headers=headers)
                  if content is not None:
                    doc = content.decode('gb2312', 'ignore')
                    movie_name, movie_score, movie_xunlei_links = self.mHtmlParser.parser_movie_info(doc, score=score)
                    if movie_xunlei_links is not None and len(movie_xunlei_links) > 0:
                      for xunlei_link in movie_xunlei_links:
                        # 判断该电影是否已经下载过了
                        is_download = self.mUrlManager.has_download(xunlei_link)
                        if is_download == False:
                          # 没下载过的电影添加到迅雷下载列表
                          d_log('开始下载 ' + movie_name + ', 链接地址: ' + xunlei_link)
                          self.mUrlManager.add_download_url(xunlei_link)
                          os.system(r'"D:\迅雷\Thunder\Program\Thunder.exe" {url}'.format(url=xunlei_link))
                          # 每下载一部电影都实时更新数据库,这样可以保证即使程序异常退出也不会重复下载该电影
                          self.save_history()
              if next_link is not None:
                d_log('next link: ' + next_link)
                self.mUrlManager.add_url(next_link)
          except Exception as e:
            d_log('错误信息: ' + str(e))
     
     
    def runner(rootLink=None, scoreLimit=None):
      if rootLink is None:
        return
      spider = SpiderMain()
      spider.load_history()
      if scoreLimit is None:
        spider.craw_movie_links(rootLink)
      else:
        spider.craw_movie_links(rootLink, score=float(scoreLimit))
      spider.save_history()
     
    # rootLink = 'https://www.dytt8.net/html/gndy/dyzz/index.html'
    # rootLink = 'https://www.dytt8.net/html/gndy/dyzz/list_23_207.html'
    def start(rootLink, scoreLimit):
      loop_thread = Thread(target=runner, args=(rootLink, scoreLimit,), name='LOOP THREAD')
      #loop_thread.setDaemon(True)
      loop_thread.start()
      #loop_thread.join() # 不能让主线程等待,否则GUI界面将卡死
      btn_start.configure(state='disable')
     
    # 刷新GUI界面,文字滚动效果
    def d_log(log):
      s = log + '\n'
      txt.insert(END, s)
      txt.see(END)
     
    if __name__ == "__main__":
      rootGUI = Tk()
      rootGUI.title('XX电影自动下载工具')
      # 设置窗体背景颜色
      black_background = '#000000'
      rootGUI.configure(background=black_background)
      # 获取屏幕宽度和高度
      screen_w, screen_h = rootGUI.maxsize()
      # 居中显示窗体
      window_x = (screen_w - 640) / 2
      window_y = (screen_h - 480) / 2
      window_xy = '640x480+%d+%d' % (window_x, window_y)
      rootGUI.geometry(window_xy)
     
      lable_link = Label(rootGUI, text='解析根地址: ',\
                bg='black',\
                fg='red', \
                font=('宋体', 12), \
                relief=FLAT)
      lable_link.place(x=20, y=20)
     
      lable_link_width = lable_link.winfo_reqwidth()
      lable_link_height = lable_link.winfo_reqheight()
     
      input_link = Entry(rootGUI)
      input_link.place(x=20+lable_link_width, y=20, relwidth=0.5)
     
      lable_score = Label(rootGUI, text='电影评分限制: ', \
                bg='black', \
                fg='red', \
                font=('宋体', 12), \
                relief=FLAT)
      lable_score.place(x=20, y=20+lable_link_height+10)
     
      input_score = Entry(rootGUI)
      input_score.place(x=20+lable_link_width, y=20+lable_link_height+10, relwidth=0.3)
     
      btn_start = Button(rootGUI, text='开始下载', command=lambda: start(input_link.get(), input_score.get()))
      btn_start.place(relx=0.4, rely=0.2, relwidth=0.1, relheight=0.1)
     
      txt = Text(rootGUI)
      txt.place(rely=0.4, relwidth=1, relheight=0.5)
     
      rootGUI.mainloop()