python爬虫 猫眼电影和电影天堂数据csv和mysql存储过程解析


Posted in Python onSeptember 05, 2019

字符串常用方法

# 去掉左右空格
'hello world'.strip()  # 'hello world'
# 按指定字符切割
'hello world'.split(' ') # ['hello','world']
# 替换指定字符串
'hello world'.replace(' ','#') # 'hello#world'

csv模块

作用:将爬取的数据存放到本地的csv文件中

使用流程

  • 导入模块
  • 打开csv文件
  • 初始化写入对象
  • 写入数据(参数为列表)
import csv
with open('test.csv','w') as f: 
 writer = csv.writer(f) # 初始化写入对象
 # 写一行
 writer.writerow(['超哥哥',20])
 writer.writerow(['步惊云',22])
with open('test.csv','a') as f:
 writer = csv.writer(f)
 # 写多行
 data_list = [('聂风',23),('秦霜',30)]
 writer.writerows(data_list)

Windows中使用csv模块默认会在每行后面添加一个空行,使用newline=''可解决

with open('xxx.csv','w',newline='') as f:

猫眼电影top100抓取案例

确定URL网址

猫眼电影 - 榜单 - top100榜 目标

电影名称、主演、上映时间 操作步骤

1、查看是否为动态加载

右键 - 查看网页源代码 - 搜索爬取关键字(查看在源代码中是否存在)

2、找URL规律

  • 第1页:https://maoyan.com/board/4?offset=0
  • 第2页:https://maoyan.com/board/4?offset=10
  • 第n页:offset=(n-1)*10

3、正则表达式

<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>

4、编写程序框架,完善程序

  • 打印程序执行时间
  • 随机的User-Agent,(确保每次发请求使用随机)
  • 数据爬下来后做处理(字符串),定义成字典
  • 一条龙: 获取 -> 调用解析 -> 数据处理
  • 猫眼电影数据存入本地 maoyanfilm.csv 文件
from urllib import request
import time
import re
import csv
import random
class MaoyanSpider(object):
 def __init__(self):
  self.page = 1 # 用于记录页数
  self.url = 'https://maoyan.com/board/4?offset={}'
  self.agent = [
   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 \
   Safari/535.1',
   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
   'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; \
   .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)',
   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1']

 # 请求
 def get_page(self, url):
  headers = {'User-Agent': random.choice(self.agent)} # 每次使用随机的user-agent
  req = request.Request(url=url, headers=headers)  # 创建请求对象
  res = request.urlopen(req)       # 发起请求
  html = res.read().decode('utf-8')     # 获取请求内容
  self.parse_page(html)        # 直接调用解析函数

 # 解析
 def parse_page(self, html):
  pattren = re.compile(
   '<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>', re.S)
  r_list = pattren.findall(html)
  # rlist: [('霸王别姬', '\n    主演:张国荣,张丰毅,巩俐\n  ', '上映时间:1993-01-01'),(...),(...)]
  self.write_page(r_list)    # 写入csv文件

 # # 保存,打印输出
 # def write_page(self,r_list):
 #  one_film_dict = {}
 #  for rt in r_list:
 #   one_film_dict['name'] = rt[0].strip()
 #   one_film_dict['star'] = rt[1].strip()
 #   one_film_dict['time'] = rt[2].strip()[5:15]
 #
 #   print(one_film_dict)

 # 保存到csv文件(writerows) -- 推荐使用此方法
 def write_page(self, r_list):
  # 空列表,最终writerows()的参数: [(),(),()]
  film_list = []
  with open('maoyan.csv', 'a',newline="") as f:
   writer = csv.writer(f)
   for rt in r_list:
    # 把处理过的数据定义成元组
    t = (rt[0], rt[1].strip(), rt[2].strip()[5:15])
    film_list.append(t)

   writer.writerows(film_list)
 def main(self):
  for offset in range(0, 31, 10):
   url = self.url.format(offset)
   self.get_page(url)
   time.sleep(random.randint(1, 3))
   print('第%d页爬取完成' % self.page)
   self.page += 1
if __name__ == '__main__':
 start = time.time()
 spider = MaoyanSpider()
 spider.main()
 end = time.time()
 print('执行时间: %.2f' % (end - start))

数据持久化存储(MySQL数据库)

让我们来回顾一下pymysql模块的基本使用

import pymysql

db = pymysql.connect('localhost', 'root', '123456', 'maoyandb', charset='utf8')
cursor = db.cursor() # 创建游标对象
# execute()方法第二个参数为列表传参补位
cursor.execute('insert into film values(%s,%s,%s)', ['霸王别姬', '张国荣', '1993'])
db.commit() # 提交到数据库执行
cursor.close() # 关闭
db.close()

让我们来回顾一下pymysql中executemany()的用法

import pymysql

# 数据库连接对象
db = pymysql.connect('localhost', 'root', '123456', charset='utf8')
cursor = db.cursor() # 游标对象
ins_list = []   # 存放所有数据的大列表
for i in range(2):
 name = input('请输入第%d个学生姓名:' % (i + 1))
 age = input('请输入第%d个学生年龄:' % (i + 1))
 ins_list.append([name, age])

ins = 'insert into t3 values(%s,%s)' # 定义插入语句
cursor.executemany(ins, ins_list) # 一次数据库的IO操作可插入多条语句,提升性能

db.commit()  # 提交到数据库执行
cursor.close() # 关闭游标
db.close()  # 关闭数据库

ins = 'insert into maoyanfilm values(%s,%s,%s)'
cursor.execute(['霸王', '国荣', '1991'])
cursor.executemany([
  ['月光宝盒', '周星驰', '1993'],
  ['大圣娶亲', '周星驰', '1993']])

练习:把猫眼电影案例中电影信息存入MySQL数据库中(尽量使用executemany方法)

from urllib import request
import time
import re
import pymysql
import random
class MaoyanSpider(object):
 def __init__(self):
  self.page = 1 # 用于记录页数
  self.url = 'https://maoyan.com/board/4?offset={}'
  self.ua_list = [
   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) \
   Chrome/14.0.835.163 Safari/535.1',
   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
   'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; \
   .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)']
  # 创建数据库连接对象和游标对象
  self.db = pymysql.connect('localhost', 'root', '123456', 'maoyandb', charset='utf8')
  self.cursor = self.db.cursor()
 # 获取
 def get_page(self, url):
  # 每次使用随机的user-agent
  headers = {'User-Agent': random.choice(self.ua_list)}
  req = request.Request(url=url, headers=headers)
  res = request.urlopen(req)
  html = res.read().decode('utf-8')
  self.parse_page(html)  # 直接调用解析函数

 # 解析
 def parse_page(self, html):
  pattren = re.compile(
   '<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>', re.S)
  # rlist: [('霸王别姬','张国荣','1993'),(),()]
  r_list = pattren.findall(html)
  print(r_list)
  self.write_page(r_list)

 # 存入mysql数据库(executemany([ [],[],[] ]))
 def write_page(self, r_list):
  film_list = []
  ins = 'insert into filmtab values(%s,%s,%s)'  # 定义插入语句
  # 处理数据,放到大列表film_list中
  for rt in r_list:
   one_film = [rt[0], rt[1].strip(), rt[2].strip()[5:15]]
   # 添加到大列表中
   film_list.append(one_film)
  # 一次数据库IO把1页数据存入
  self.cursor.executemany(ins, film_list)
  # 提交到数据库执行
  self.db.commit()

 def main(self):
  for offset in range(0, 31, 10):
   url = self.url.format(offset)
   self.get_page(url)
   time.sleep(random.randint(1, 3))
   print('第%d页爬取完成' % self.page)
   self.page += 1

  # 断开数据库(所有页爬完之后)
  self.cursor.close()
  self.db.close()
if __name__ == '__main__':
 start = time.time()
 spider = MaoyanSpider()
 spider.main()
 end = time.time()
 print('执行时间: %.2f' % (end - start))

让我们来做个SQL命令查询

1、查询20年以前的电影的名字和上映时间

select name,time from filmtab where time<(now()-interval 20 year);

2、查询1990-2000年的电影名字和上映时间

select name,time from filmtab where time>='1990-01-01' and time<='2000-12-31';

让我们来复习一下mongdb数据库

import pymongo
# 1.连接对象
conn = pymongo.MongoClient(host='127.0.0.1', port=27017)
db = conn['maoyandb']  # 2.库对象
myset = db['filmtab']  # 3.集合对象
myset.insert_one({'name': '赵敏'}) # 4.插入数据库

练习:把猫眼电影案例中电影信息存入MongDB数据库中

from urllib import request
import re
import time
import random
import pymongo
class MaoyanSpider(object):
 def __init__(self):
  self.url = 'https://maoyan.com/board/4?offset={}'
  # 计数
  self.num = 0
  # 创建3个对象
  self.conn = pymongo.MongoClient('localhost', 27017)
  self.db = self.conn['maoyandb']
  self.myset = self.db['filmset']
  self.ua_list = [
   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
   'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET \
   CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)', ]

 def get_html(self, url):
  headers = {
   'User-Agent': random.choice(self.ua_list)
  }
  req = request.Request(url=url, headers=headers)
  res = request.urlopen(req)
  html = res.read().decode('utf-8')
  # 直接调用解析函数
  self.parse_html(html)

 def parse_html(self, html):
  re_bds = r'<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>'
  pattern = re.compile(re_bds, re.S)
  # film_list: [('霸王别姬','张国荣','1993'),()]
  film_list = pattern.findall(html)
  # 直接调用写入函数
  self.write_html(film_list)
 # mongodb数据库
 def write_html(self, film_list):
  for film in film_list:
   film_dict = {
    'name': film[0].strip(),
    'star': film[1].strip(),
    'time': film[2].strip()[5:15]
   }
   # 插入mongodb数据库
   self.myset.insert_one(film_dict)
 def main(self):
  for offset in range(0, 31, 10):
   url = self.url.format(offset)
   self.get_html(url)
   time.sleep(random.randint(1, 2))
if __name__ == '__main__':
 start = time.time()
 spider = MaoyanSpider()
 spider.main()
 end = time.time()
 print('执行时间:%.2f' % (end - start))

电影天堂案例(二级页面抓取)

1、查看是否为静态页面,是否为动态加载

右键 - 查看网页源代码

2、确定URL地址

百度搜索 :电影天堂 - 2019年新片 - 更多

3、目标

*********一级页面***********
1、电影名称
2、电影链接
*********二级页面***********

1、下载链接

4、步骤

找URL规律

第1页 :https://www.dytt8.net/html/gndy/dyzz/list_23_1.html

第2页 :https://www.dytt8.net/html/gndy/dyzz/list_23_2.html

第n页 :https://www.dytt8.net/html/gndy/dyzz/list_23_n.html

写正则表达式

1、一级页面正则表达式(电影名称、电影详情链接)

<table width="100%".*?<td height="26">.*?<a href="(.*?)" rel="external nofollow" rel="external nofollow" .*?>(.*?)</a>

2、二级页面正则表达式

<td style="WORD-WRAP.*?>.*?>(.*?)</a>

代码实现

# decode('gbk','ignore') 注意ignore参数

# 注意结构和代码可读性(一个函数不要太冗余)

from urllib import request
import re
import time
import random
from useragents import *
import pymysql
class FilmSky(object):
 def __init__(self):
  self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
  # 定义两个对象
  self.db = pymysql.connect('127.0.0.1', 'root', '123456', 'maoyandb', charset='utf8')
  self.cursor = self.db.cursor()

 # 获取html函数(因为两个页面都需要发请求)
 def get_page(self, url):
  req = request.Request(url=url, headers={'User-Agent': random.choice(ua_list)})
  res = request.urlopen(req)
  # ignore参数,实在处理不了的编码错误忽略
  # 查看网页源码,发现网页编码为 gb2312,不是 utf-8
  html = res.read().decode('gbk', 'ignore')
  return html

 # 解析提取数据(把名称和下载链接一次性拿到)
 # html为一级页面响应内容
 def parse_page(self, html):
  # 1. 先解析一级页面(电影名称 和 详情链接)
  pattern = re.compile('<table width="100%".*?<td height="26">.*?<a href="(.*?)" rel="external nofollow" rel="external nofollow" .*?>(.*?)</a>', re.S)
  # film_list: [('详情链接','名称'),()]
  film_list = pattern.findall(html)
  # [('/html/gndy/dyzz/20190806/58956.html', '019年惊悚动作《报仇雪恨/血债血偿》BD中英双字幕'),(),()]
  ins = 'insert into filmsky values(%s,%s)'
  for film in film_list:
   film_name = film[1]
   film_link = 'https://www.dytt8.net' + film[0]
   # 2. 拿到详情链接后,再去获取详情链接html,提取下载链接
   download_link = self.parse_two_html(film_link)

   self.cursor.execute(ins, [film_name, film_link])
   self.db.commit()

   # 打印测试
   d = {'电影名称': film_name, '下载链接': download_link}
   print(d)

 # {'电影名称': '019年惊悚动作《报仇雪恨/血债血偿》BD中英双字幕', '下载链接': 'ftp://ygdy8:ygdy8@yg90.dydytt.net:8590/阳光电影www.ygdy8.com.报仇雪恨.BD.720p.中英双字幕.mkv'}
 # 解析二级页面,获取下载链接
 def parse_two_html(self, film_link):
  two_html = self.get_page(film_link)
  pattern = re.compile('<td style="WORD-WRAP.*?>.*?>(.*?)</a>', re.S)
  download_link = pattern.findall(two_html)[0]
  return download_link
 # 主函数
 def main(self):
  for page in range(1, 11):
   url = self.url.format(page)
   html = self.get_page(url)
   self.parse_page(html)
   time.sleep(random.randint(1, 3))
   print('第%d页完成' % page)
if __name__ == '__main__':
 start = time.time()
 spider = FilmSky()
 spider.main()
 end = time.time()
 print('执行时间:%.2f' % (end - start))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python常用的文件及文件路径、目录操作方法汇总介绍
May 21 Python
在Python的while循环中使用else以及循环嵌套的用法
Oct 14 Python
Windows上配置Emacs来开发Python及用Python扩展Emacs
Nov 20 Python
Python 实现输入任意多个数,并计算其平均值的例子
Jul 16 Python
Python pickle模块实现对象序列化
Nov 22 Python
关于Python Tkinter Button控件command传参问题的解决方式
Mar 04 Python
keras model.fit 解决validation_spilt=num 的问题
Jun 19 Python
python爬虫使用requests发送post请求示例详解
Aug 05 Python
pycharm中如何自定义设置通过“ctrl+滚轮”进行放大和缩小实现方法
Sep 16 Python
浅析python函数式编程
Sep 26 Python
python库sklearn常用操作
Aug 23 Python
Pygame Draw绘图函数的具体使用
Nov 17 Python
python爬取Ajax动态加载网页过程解析
Sep 05 #Python
python实现静态服务器
Sep 05 #Python
python编写简单端口扫描器
Sep 04 #Python
python 3.6.7实现端口扫描器
Sep 04 #Python
python用线性回归预测股票价格的实现代码
Sep 04 #Python
python多线程扫描端口(线程池)
Sep 04 #Python
Python数据分析模块pandas用法详解
Sep 04 #Python
You might like
PHP If Else(elsefi) 语句
2013/04/07 PHP
Thinkphp5.0 框架视图view的比较标签用法分析
2019/10/12 PHP
Javascript与vbscript数据共享
2007/01/09 Javascript
CSS JavaScript 实现菜单功能 改进版
2008/12/09 Javascript
复选框全选与全不选操作实现思路
2013/08/18 Javascript
Jquery实现自定义窗口随意的拖拽
2014/03/12 Javascript
JavaScript实现更改网页背景与字体颜色的方法
2015/02/02 Javascript
浅谈Jquery为元素绑定事件
2015/04/27 Javascript
JavaScript实现类似拉勾网的鼠标移入移出效果
2016/10/27 Javascript
微信小程序入门教程
2016/11/18 Javascript
nodejs基础知识
2017/02/03 NodeJs
vue地区选择组件教程详解
2018/05/04 Javascript
vue实现的组件兄弟间通信功能示例
2018/12/04 Javascript
在Vant的基础上封装下拉日期控件的代码示例
2018/12/05 Javascript
8个有意思的JavaScript面试题
2019/07/30 Javascript
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
Python下的Mysql模块MySQLdb安装详解
2014/04/09 Python
Python使用lxml模块和Requests模块抓取HTML页面的教程
2016/05/16 Python
Python3学习urllib的使用方法示例
2017/11/29 Python
python 利用栈和队列模拟递归的过程
2018/05/29 Python
老生常谈python中的重载
2018/11/11 Python
pygame游戏之旅 调用按钮实现游戏开始功能
2018/11/21 Python
python调用函数、类和文件操作简单实例总结
2019/11/29 Python
使用opencv将视频帧转成图片输出
2019/12/10 Python
python怎么判断素数
2020/07/01 Python
整理HTML5的一些新特性与Canvas的常用属性
2016/01/29 HTML / CSS
中粮集团旗下食品网上购物网站:我买网
2016/09/22 全球购物
俄罗斯便宜的在线服装商店:GroupPrice
2020/04/10 全球购物
美国工业用品采购网站:Zoro.com
2020/10/27 全球购物
C#里面如何判断一个Object是否是某种类型(如Boolean)?
2016/02/10 面试题
学生党员的自我评价范文
2014/03/01 职场文书
软件工程毕业生自荐信
2014/07/04 职场文书
2015年大学生党员承诺书
2015/04/27 职场文书
Html5生成验证码的示例代码
2021/05/10 Javascript
Python Django获取URL中的数据详解
2021/11/01 Python