Python爬虫(二)——爬取电影天堂,保存下载地址

首先我们开始要分析一下,下载种子我们需要哪几步:

  1. 获取所有电影页的访问地址
  2. 获取电影页源码
  3. 提取出下载地址
  4. 将下载地址保存

首先第一步,我们来分析一下电影天堂网站的结构,发现他跟我们的古诗文网还是非常类似的,全站静网结构,不需要登录,页面有全新的地址,这对于初学来讲是非常容易上手的;接下来我们以国内电影(https://www.ygdy8.net/html/gndy/china/index.html)为例,先把所有电影详情页的地址获取到:

我们发现我们需要的地址<a href="***" class="ulink">以链接的形式存在,且所有的地址都是这种形式,那么我们可以用正则表达式直接匹配所有符合这种样式的文本,最后把地址做一个拼接就好了;

我们发现乱码了,这是因为什么,我们之前在爬取古诗文网的时候是没有这种问题的,这是因为网站的文字编码不一样,在我们python3里面默认使用的是utf-8,我们看下古诗文网和电影天堂的编码格式分别是什么:


我们发现古诗文网的编码格式就是“utf-8”,而电影天堂的编码格式是“gb2312”,编码格式不一样,当然会乱码了,所以我们需要设置一下编码格式:

这下就正常了,总结一下:如果发现获取的源码乱码了,到网页源码中搜索一下“charset”,看一下网页的编码是什么
ok,现在源码我们已经有了,接下来就是获取详情页的地址了:

import requests
import re    # 导入正则表达式库

url = 'https://www.ygdy8.net/html/gndy/china/index.html'
result = requests.get(url)
result.encoding = 'gb2312'
html = result.text
reg = '<a href="(.*?)" class="ulink">'    # 匹配的规则
href = re.findall(reg,html)    # 在源码中匹配所有满足其规则的文本
print(href)

# 输出结果:
# ['/html/gndy/dyzz/20191204/59430.html', '/html/gndy/jddy/20191203/59421.html', '/html/gndy/jddy/20191203/59420.html', '/html/gndy/dyzz/20191129/59405.html', '/html/gndy/dyzz/20191127/59402.html', '/html/gndy/dyzz/20191126/59401.html', '/html/gndy/dyzz/20191125/59398.html', '/html/gndy/dyzz/20191124/59394.html', '/html/gndy/jddy/20191118/59382.html', '/html/gndy/dyzz/20191115/59376.html', '/html/gndy/dyzz/20191113/59363.html', '/html/gndy/jddy/20191110/59357.html', '/html/gndy/jddy/20191110/59356.html', '/html/gndy/jddy/20191109/59352.html', '/html/gndy/jddy/20191109/59351.html', '/html/gndy/dyzz/20191107/59345.html', '/html/gndy/dyzz/20191101/59301.html', '/html/gndy/dyzz/20191027/59287.html', '/html/gndy/jddy/20191027/59282.html', '/html/gndy/dyzz/20191026/59279.html', '/html/gndy/dyzz/20191024/59273.html', '/html/gndy/jddy/20191019/59253.html', '/html/gndy/dyzz/20191017/59249.html', '/html/gndy/dyzz/20191016/59241.html', '/html/gndy/jddy/20191015/59236.html']

那么就有两个问题出现了:

  1. 为什么匹配的规则是<a href="(.*?)" class="ulink">?
    我们回顾一下上面我们需要的地址的那部分字段是怎么样的
    我们发现,非常相似,就是中间的网址被替换成了 (.*?)
  2. 其中的 (.*?) 是什么意思?
    那这个 (.*?) 就是未知字符了,他的准确意思是,任意长度的任意字符,这个是正则部分的内容,可以自行百度,这个基本可以说是万能用法,可以先把这个掌握,后面再慢慢学习其他的

我们现在已经把详情页的地址获取到了,下一步就是访问详情页,然后把磁力链接地址获取到了:


其实就是一样的操作,这边就不赘述了,我们发现上面的代码几乎有一半都是重复的,获取源码、正则匹配的部分可以直接写成方法:

我们现在已经把一个页面所有电影的磁力链接获取到了,接下来我们就需要将这些信息存储起来,当然不要忘记片名,不然哪个是哪个就傻傻分不清了:

 从上面的代码我们可以看到,已经将一个页面的磁力链接和片名对应,并且保存了起来,这里如果对zip()和csv读写相关有疑问的话,可以自行百度,也可以查看Python3基础篇——读写csv文件python3基础篇——列表的高级用法两篇文章;

接下来我们就需要把所有的页面都处理了,通过网址我们可以发现就是最后的数字变化,那么我们只需要将网址进行一个拼接就好了

SOS:惊奇的发现,当我们爬取到24页之后,后面没有磁力链接地址了,那么我们只好转战下载ftp的地址,同样也是可以下载的:

import requests
import re
import csv

def get_html(url):    # 获取页面源码
    url = url
    result = requests.get(url)    # 发出访问请求
    result.encoding = 'gb2312'    # 设置编码格式,搜索页面源码charset
    html = result.text            # 获取源码
    return html

title = []    # 存储标题
data = []     # 存储下载地址

n = 1        # 页码
status = 0   # 重新访问次数

while n < 123:    # 这里我们使用while循环,处理访问出错的页面
    try:    # 异常处理很重要,不然可能最后一页前破功了
        # 直接简单粗暴,拼接地址
        url = 'https://www.ygdy8.net/html/gndy/china/list_4_{}.html'.format(str(n))
        html = get_html(url)
        print(url)    # 将地址打印出来,可以知道现在搜索到哪一页了
        reg = '<a href="(.*?)" class="ulink">'    # 匹配详情页地址规则
        href = re.findall(reg,html)

        for h in href:    # 遍历页面所有电影详情页
            info_url = 'https://www.ygdy8.net/' + h
            info_html = get_html(info_url)
            try:
                data_reg = '<a href="(.*?)">ftp://'
                title_reg = '<font color=#07519a>(.*?)</font>'
                title_tmp = re.findall(title_reg, info_html)[0]
                data.append(re.findall(data_reg,info_html)[0])    # 将下载地址添加到列表
                title.append(title_tmp)    # 注意,先地址再标题,不然如果页面没有下载地址,标题添加进去就不对应了
            except:
                print('{}获取失败'.format(title_tmp))    # 打印那部电影出错了
        n += 1        # 翻页
        status = 0    # 重新访问次数情况
    except:    # 如果页面访问出错
        if status < 4:    # 重新访问三次
            status += 1   # 次数加1
            print('访问出错,重新访问第{}遍'.format(status))    # 输出错误次数信息
        else:
            n += 1        # 如果重新访问三次还是访问不到,那么直接翻页
            status = 0

all_data = list(zip(title, data))    # 将标题和地址打包
with open('国内电影.csv', 'w', newline='', encoding='utf-8-sig') as f:    # 写入文件
    writer = csv.writer(f)
    writer.writerows(all_data)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章