首先我们开始要分析一下,下载种子我们需要哪几步:
- 获取所有电影页的访问地址
- 获取电影页源码
- 提取出下载地址
- 将下载地址保存
首先第一步,我们来分析一下电影天堂网站的结构,发现他跟我们的古诗文网还是非常类似的,全站静网结构,不需要登录,页面有全新的地址,这对于初学来讲是非常容易上手的;接下来我们以国内电影为例,先把所有电影详情页的地址获取到:
我们发现我们需要的地址<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']
那么就有两个问题出现了:
- 为什么匹配的规则是<a href="(.*?)" class="ulink">?
我们回顾一下上面我们需要的地址的那部分字段是怎么样的
我们发现,非常相似,就是中间的网址被替换成了 (.*?) - 其中的 (.*?) 是什么意思?
那这个 (.*?) 就是未知字符了,他的准确意思是,任意长度的任意字符,这个是正则部分的内容,可以自行百度,这个基本可以说是万能用法,可以先把这个掌握,后面再慢慢学习其他的
我们现在已经把详情页的地址获取到了,下一步就是访问详情页,然后把磁力链接地址获取到了:
其实就是一样的操作,这边就不赘述了,我们发现上面的代码几乎有一半都是重复的,获取源码、正则匹配的部分可以直接写成方法:
我们现在已经把一个页面所有电影的磁力链接获取到了,接下来我们就需要将这些信息存储起来,当然不要忘记片名,不然哪个是哪个就傻傻分不清了:
从上面的代码我们可以看到,已经将一个页面的磁力链接和片名对应,并且保存了起来,这里如果对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)