需求
一级页面抓取:电影详情页链接
二级页面抓取:电影名称和电影下载链接
增量获取:网站中电影资源后将更新的数据爬取下来
步骤
- 确定响应内容中是否存在所需抓取数据(是否为静态页面):看是否能在源代码中搜到关键词
- 找url规律
一级页面url规律:
第n页:https://www.dytt8.net/html/gndy/dyzz/list_23_n.html - 根据页面元素写正则
//一级页面正则
<table width="100%".*?<td width="5%".*?<a href="(.*?)".*?ulink">.*?</table>
//二级页面正则
<div class="title_all"><h1><font color=#07519a>(.*?)</font></h1></div>.*?<td style="WORD-WRAP.*?>.*?>(.*?)</a>
- 爬虫程序
- 多级页面抓取思路:
先写1,2级页面通用的功能函数
然后依次做1,2级页面该做的事
最后设置增量抓取,将数据存入mysql数据库
- 多级页面抓取思路:
from urllib import request
import re
import time
import random
from fake_useragent import UserAgent
import pymysql
from hashlib import md5
import sys
class FilmSkySpider(object):
def __init__(self):
self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
#连接Mysql,数据表为filmdb
self.db = pymysql.connect('localhost','root','123456','filmskydb',charset='utf8')
#创建游标
self.cursor = self.db.cursor()
#多级页面获取,先封装通用函数
#功能函数1:获取htm的函数
def get_html(self,url):
headers = {'User=Agent':UserAgent().random}
req = request.Request(url=url,headers=headers)
#向网站发起请求并获取响应
resp = request.urlopen(req)
#读取响应,将传输的字节串转为字符串
html = resp.read().decode('gb18030','ignore') #这网站是GBK的,用gb18030是因为它能识别的最多,其他的还有gb2312,gbk,只能做到gb18030,如果还有解码错误的,用'ignore'表示忽略掉解码错误
return html
#功能函数2:re匹配出数据
def parse_func(self,re_bds,html):
p = re.compile(re_bds,re.S)
r_list = p.findall(html)
return r_list
#解析提取所有需求数据
def parse_html(self,one_url):
#提取一级页面所需:二级页面链接
#获取一级页面html
one_html = self.get_html(one_url)
#用re解析一级页面html得到链接,格式为['/html/xxx','/html/xxx','']
re_dbs = '<table width="100%".*?<a class="ulink" href="(.*?)">.*?</table>'
href_list = self.parse_func(re_dbs,one_html)
#for循环一页一页提取二级页面数据
for href in href_list:
#拼出二级页面链接
link = 'https://www.dytt8.net' + href
#将链接用md5加密,转为finger
s = md5()
s.update(link.encode())
finger = s.hexdigest()
#若数据库中没有finger,表示网页中数据更新,抓
if not self.is_go_on(finger):
#向详情页发请求,提取名字和下载链接,将这个功能封装成函数
self.parse_two_page(link)
#抓取一个电影的所需信息后,休眠
time.sleep(random.randint(1,2))
#抓完后将finger存入request_finger表中
ins = 'insert into request_finger value(%s)'
self.cursor.execute(ins,[finger])
self.db.commit()
#网页数据未有更新,无需抓取,退出进程
else:
sys.exit('完成')
#到指纹表request_finger中查看是否存在该finger
def is_go_on(self,finger):
sel = 'select finger from request_finger where finger=%s'
result = self.cursor.execute(sel,[finger])
#数据库中已有该finger时,返回给调用函数True
if result:
return True
#解析提取二级页面数据具体的函数
def parse_two_page(self,link):
#获取二级页面html
two_html = self.get_html(link)
#用re匹配二级页面html,格式为r_list:[(电影名称,下载链接)]
re_bds = '<div class="title_all"><h1><font color=#07519a>(.*?)</font></h1></div>.*?<td style="WORD-WRAP.*?>.*?>(.*?)</a>'
r_list = self.parse_func(re_bds,two_html)
#将数据拼接成字典,以防有些网站故意做不同格式的标签断掉我的re(list返回空),为了防止程序断掉,用if r_list忽略为空的情况
if r_list:
item = {}
item['name'] = r_list[0][0].strip()
item['download'] = r_list[0][1].strip()
print(item)
#将二级页面所需数据存入数据表filmtab
ins = 'insert into filmtab value(%s,%s)'
L = [item['name']],item['download']
self.cursor.execute(ins,L)
self.db.commit()
#入口函数
def run(self):
for i in range(1,205): #一共204页
#拼接url
one_url = self.url.format(i)
#调用解析,提取数据的函数
self.parse_html(one_url)
if __name__ == '__main__':
spider = FilmSkySpider()
spider.run()