#!/usr/bin/env python # encoding: utf-8 """ @version: v1.0 @author: xag @license: Apache Licence @contact: xinganguo@gmail.com @site: http://www.xingag.top @software: PyCharm @file: 4.dytt.py @time: 2018/9/16 18:46 @description:爬电影天堂【 lxml + xpath + requests】【2018新片精品,包含更多】 """ import requests from lxml import etree import time # url = 'http://www.dytt8.net/html/gndy/dyzz/list_23_1.html' # 主页地址 BASE_DOMAIN = 'http://www.dytt8.net' HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36', } def get_detail_urls(url): """ 获取电影详情页面的url :param url: 每一页电影列表的地址url :return: """ response = requests.get(url, headers=HEADERS) # 注意:右键查看源代码,charset=gb2312" 编码方式【网站编码不规范,解码必须用响应的编码方式进行解码】 # print(response.content.decode('gbk')) # html_element = etree.HTML(response.content.decode('gbk')) # 注意:电影天堂第3页使用默认的gbk会有乱码,这里使用默认的解码方式【href为英文,解析不会受影响】 html_element = etree.HTML(response.text) # 【数据 - 字符串列表】详情页面地址 # 所有class为tbspan的table标签/子孙标签中的a标签的href属性 detail_urls = html_element.xpath('//table[@class="tbspan"]//a/@href') # 深拷贝一份列表数据,实现一变遍历列表,一边删除列表数据 # 过滤掉【综合电影】导致的脏数据 detail_urls_new = detail_urls for index, detail_url in enumerate(detail_urls_new): if detail_url == '/html/gndy/jddy/index.html': detail_urls.remove(detail_url) # print(detail_urls) # print(BASE_DOMAIN + detail_url) # 组装详情页面的地址 detail_urls = map(lambda x: BASE_DOMAIN + x, detail_urls) return detail_urls def parse_detail_page(detail_url): """ 解析电影详情页面 :param detail_url: 详情页面的地址 :return: """ response = requests.get(detail_url, headers=HEADERS) text = response.content.decode('gbk') html_element = etree.HTML(text) # 【数据 - 电影标题】 title = html_element.xpath('//div[@class="title_all"]//font[@color="#07519a"]/text()')[0] # 获取zoom标签 zoom_element = html_element.xpath('//div[@id="Zoom"]')[0] # 【数据 - 电影封面和电影截图】 imgs = zoom_element.xpath(".//img/@src") # 注意:为了避免脏数据导致应用挂掉,提前初始化 year, country, type, rating, duration, director, actors, cover, screen_shot, download_url = '', '', '', '', '', '', '', '', '', '' if len(imgs) > 0: cover = imgs[0] # 【数据 - 电影截图】 if len(imgs) > 1: screen_shot = imgs[1] # 获取div[@id='zoom']标签下面的所有的文本数据【子孙所有的text文本数据】 infos = zoom_element.xpath('.//text()') # 解析具体内容的函数 def parse_info(info, rule): return info.replace(rule, '').strip() # 遍历infos每一项去获取有用的数据 for key, info in enumerate(infos): # print('遍历第{}项'.format(key)) # print(info) # print('结束==================================================') if info.startswith('◎年  代'): # 年代 year = parse_info(info, '◎年  代') elif info.startswith('◎产  地'): # 产地 country = parse_info(info, '◎产  地') elif info.startswith('◎类  别'): # 类别 type = parse_info(info, '◎类  别') elif info.startswith('◎豆瓣评分'): # 豆瓣评分 rating = parse_info(info, '◎豆瓣评分') elif info.startswith('◎片  长'): # 片长 duration = parse_info(info, '◎片  长') elif info.startswith('◎导  演'): # 导演 director = parse_info(info, '◎导  演') elif info.startswith('◎主  演'): # 演员【第一个演员】 actor_first = parse_info(info, '◎主  演') actors = [actor_first] # 继续往下面遍历 for index in range(key + 1, len(infos)): item = infos[index].strip() if item.startswith('◎简  介'): break # 获取所有的演员 # print(item) actors.append(item) elif info.startswith('◎简  介'): # desc = parse_info(info, '◎简  介') for index in range(key + 1, len(infos)): item = infos[index].strip() if item.startswith('【下载地址】'): break desc = item print(detail_url) # 下载地址 if len(html_element.xpath('//td[@bgcolor="#fdfddf"]/a/text()')) > 0: download_url = html_element.xpath('//td[@bgcolor="#fdfddf"]/a/text()')[0] elif len(html_element.xpath('//td[@bgcolor="#fdfddf"]/text()')) > 0: download_url = html_element.xpath('//td[@bgcolor="#fdfddf"]/text()')[0] film = { 'title': title, 'cover': cover, 'screen_shot': screen_shot, 'year': year, 'country': country, 'type': type, 'rating': rating, 'duration': duration, 'director': director, 'actors': actors, 'desc': desc, 'download_url': download_url } return film def spider(): """ 爬虫的入口 :return: """ base_url = 'http://www.dytt8.net/html/gndy/dyzz/list_23_{}.html' films = [] # 1.获取第1-10页的数据 for index in range(1, 11): print('开始爬第{}页'.format(index)) # 2.电影列表的地址url url = base_url.format(index) # 3.获取当前页面包含的所有电影【详情地址】 detail_urls = get_detail_urls(url) # 4.解析每一项电影的详情页面 for key, detail_url in enumerate(detail_urls): # print('索引:' + str(key) + ',地址:' + detail_url) # print('解析详情页面:' + detail_url) film = parse_detail_page(detail_url) films.append(film) # 5.每爬取一页,就休眠2秒钟 time.sleep(1) print(films) if __name__ == '__main__': spider()