SPIDER-DAY02--数据持久化--mysql,csv,mongodb
电影天堂案例
import requests
import re
import time
import random
# http://httpbin.org/get
class DyttSpider:
def __init__(self):
self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
def get_html(self, url):
"""请求 解析 数据处理"""
# content.decode() 手动转码
# ignore参数: 忽略转码过程中的异常
html = requests.get(url=url, headers=self.headers).content.decode('gb2312', 'ignore')
# 直接调用解析函数
self.parse_html(html)
def parse_html(self, html):
"""正则解析提取数据"""
regex = '<td height="26">.*?<a href="(.*?)" class="ulink">(.*?)</a>'
r_list = re.findall(regex, html, re.S)
for r in r_list:
item = {}
item['name'] = r[1]
item['href'] = 'https://www.dytt8.net' + r[0]
print(item)
def crawl(self):
"""程序入口函数"""
for page in range(1, 2):
page_url = self.url.format(page)
# 请求解析
self.get_html(url=page_url)
# 控制频率
time.sleep(random.randint(1, 3))
if __name__ == '__main__':
spider = DyttSpider()
spider.crawl()
1. MySQL数据持久化
1.1 pymysql回顾
-
MySQL建库建表
create database dyttdb charset utf8;
use dyttdb;
create table dytt_tab(
href varchar(500),
name varchar(100)
)charset=utf8; -
pymysql示例
"""
库: dyttdb
表: dytt_tab
在表中任意插入1条表记录
"""
import pymysql
# 1.创建2个对象(连接对象 游标对象)
db = pymysql.connect('localhost','root','123456', 'dyttdb', charset='utf8')
cur = db.cursor()
# 2.执行sql命令,并提交到数据库执行
cur.execute('insert into dytt_tab values(%s,%s)', ['http://dhxy.html', '足球小将'])
db.commit()
# 3.关闭断开数据库连接
cur.close()
db.close()
1.2 电影天堂数据持久化
import requests
import re
import time
import random
import pymysql
class DyttSpider:
def __init__(self):
self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
# 创建数据库连接对象和游标对象
self.db = pymysql.connect(
'localhost','root','123456','dyttdb', charset='utf8'
)
self.cur = self.db.cursor()
def get_html(self, url):
"""请求 解析 数据处理"""
# content.decode() 手动转码
# ignore参数: 忽略转码过程中的异常
html = requests.get(url=url, headers=self.headers).content.decode('gb2312', 'ignore')
# 直接调用解析函数
self.parse_html(html)
def parse_html(self, html):
"""正则解析提取数据"""
regex = '<td height="26">.*?<a href="(.*?)" class="ulink">(.*?)</a>'
r_list = re.findall(regex, html, re.S)
ins = 'insert into dytt_tab values(%s,%s)'
for r in r_list:
# 数据存入MySQL数据库
self.cur.execute(ins, r)
self.db.commit()
print(r)
def crawl(self):
"""程序入口函数"""
for page in range(1, 101):
page_url = self.url.format(page)
# 请求解析
self.get_html(url=page_url)
# 控制频率
time.sleep(random.randint(1, 3))
# 断开数据库连接
self.cur.close()
self.db.close()
if __name__ == '__main__':
spider = DyttSpider()
spider.crawl()
2. CSV数据持久化
2.1 CSV持久化概述
【1】作用
将爬取的数据存放到本地的csv文件中
【2】使用流程
2.1> 打开csv文件
2.2> 初始化写入对象
2.3> 写入数据(参数为列表)
【3】示例代码
import csv
with open('sky.csv','w') as f:
writer = csv.writer(f)
writer.writerow([])
2.2 CSV示例代码
import csv
with open('test.csv','w') as f:
writer = csv.writer(f)
writer.writerow(['超哥哥','25'])
2.3 电影天堂CSV持久化
import requests
import re
import time
import random
import csv
# http://httpbin.org/get
class DyttSpider:
def __init__(self):
self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
# 打开文件并初始化写入对象
self.f = open('dytt.csv', 'w')
self.writer = csv.writer(self.f)
def get_html(self, url):
"""请求 解析 数据处理"""
# content.decode() 手动转码
# ignore参数: 忽略转码过程中的异常
html = requests.get(url=url, headers=self.headers).content.decode('gb2312', 'ignore')
# 直接调用解析函数
self.parse_html(html)
def parse_html(self, html):
"""正则解析提取数据"""
regex = '<td height="26">.*?<a href="(.*?)" class="ulink">(.*?)</a>'
r_list = re.findall(regex, html, re.S)
for r in r_list:
# 数据存入csv文件中
self.writer.writerow(r)
print(r)
def crawl(self):
"""程序入口函数"""
for page in range(1, 2):
page_url = self.url.format(page)
# 请求解析
self.get_html(url=page_url)
# 控制频率
time.sleep(random.randint(1, 3))
# 关闭文件
self.f.close()
if __name__ == '__main__':
spider = DyttSpider()
spider.crawl()
3.1 MongoDB介绍
【1】MongoDB为非关系型数据库,基于key-value方式存储
【2】MongoDB基于磁盘存储,而Redis基于内存
【3】MongoDB数据类型单一,就是JSON文档
MySQL数据类型:数值类型、字符类型、枚举类型、日期时间类型
Redis数据类型:字符串、列表、哈希、集合、有序集合
MongoDB数据类型: JSON文档
# 此生铭记: MongoDB是基于磁盘存储的非关系型数据库,数据类型很单一,值就是JSON文档
【4】和MySQL对比
MySQL: 库 - 表 - 表记录
MongoDB:库 - 集合 - 文档
【5】特性
MongoDB无需提前建库建集合,直接使用即可,会自动创建
3.2 MongoDB常用命令
【1】进入命令行: mongo
【2】查看所有库: show dbs
【3】切换库: use 库名
【4】查看库中集合:show collections | show tables
【5】查看集合文档:db.集合名.find().pretty()
【6】统计文档个数:db.集合名.count()
【7】删除集合: db.集合名.drop()
【8】删除库: db.dropDatabase()
3.3 与Python交互
-
pymongo模块
【1】模块名: pymongo
sudo pip3 install pymongo
【2】使用流程
2.1》创建数据库连接对象
2.2》创建库对象(库可以不存在)
2.3》创建集合对象(集合可以不存在)
2.4》在集合中插入文档 -
示例代码
"""
库名: dyttdb
集合名: dytt_set
插入1条文档: {'name':'活着','star':'牛犇'}
"""
import pymongo
# 3个对象:连接对象 库对象 集合对象
conn = pymongo.MongoClient('localhost', 27017)
db = conn['dyttdb']
myset = db['dytt_set']
# 集合中插入文档
myset.insert_one({'name':'活着','star':'牛犇'})
# 1. show dbs
# 2. use dyttdb
# 3. show collections
# 4. db.集合名.find().pretty()
# 5. db.集合名.count()
# 6. db.dropDatabase() -
笔趣阁数据持久化
import requests
import re
import time
import random
import pymongo
class DyttSpider:
def __init__(self):
self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
# 创建3个对象(连接对象 库对象和集合对象)
self.conn = pymongo.MongoClient(
'localhost', 27017
)
self.db = self.conn['dyttdb']
self.myset = self.db['dytt_set']
def get_html(self, url):
"""请求 解析 数据处理"""
# content.decode() 手动转码
# ignore参数: 忽略转码过程中的异常
html = requests.get(url=url, headers=self.headers).content.decode('gb2312', 'ignore')
# 直接调用解析函数
self.parse_html(html)
def parse_html(self, html):
"""正则解析提取数据"""
regex = '<td height="26">.*?<a href="(.*?)" class="ulink">(.*?)</a>'
r_list = re.findall(regex, html, re.S)
for r in r_list:
item = {}
item['name'] = r[1]
item['href'] = 'https://www.dytt8.net' + r[0]
print(item)
# 把数据存入mongodb数据库
self.myset.insert_one(item)
def crawl(self):
"""程序入口函数"""
for page in range(1, 101):
page_url = self.url.format(page)
# 请求解析
self.get_html(url=page_url)
# 控制频率
time.sleep(random.randint(1, 3))
if __name__ == '__main__':
spider = DyttSpider()
spider.crawl()
4. 汽车之家多级页面爬虫
4.1 项目需求
【1】爬取地址
https://www.guazi.com/bj/buy/o1/#bread
【2】爬取分析
*********一级页面需抓取***********
1、汽车详情页链接
*********二级页面需抓取***********
1、汽车名字、
2、行驶里程
3、排量
4、变速箱
5、价格
4.2 项目实现流程
【1】确认数据来源 - 响应内容中存在所抓取数据!!!
【2】找URL地址规律
第1页: https://www.guazi.com/bj/buy/o1/#bread
第2页: https://www.guazi.com/bj/buy/o2/#bread
第n页: https://www.guazi.com/bj/buy/on/#bread
【3】 写正则表达式
3.1》一级页面正则表达式
'<li data-scroll-track=.*?href="(.*?)"'
3.2》二级页面正则表达式
'<h1 class="titlebox">(.*?)<.*?<li class="two"><span>(.*?)</span>.*?<span>(.*?)</span>.*?<span>(.*?)</span>.*?<span class="price-num">(.*?)</span>'
【4】代码实现
4.3 代码实现
"""
1、一级页面所抓数据
1.1 每辆汽车(40辆)详情页的链接
2、二级页面所抓数据
2.1 汽车名称
2.2 行驶里程
2.3 排量
2.4 变速箱
2.5 价格
"""
import requests
import re
import time
import random
from fake_useragent import UserAgent
class CarSpider:
def __init__(self):
"""定义常用变量"""
self.one_url = 'https://www.guazi.com/bj/buy/o{}/#bread'
def get_html(self, url):
"""功能函数1: 请求,发请求获取响应内容"""
headers = {'User-Agent':UserAgent().random}
html = requests.get(url=url, headers=headers).text
return html
def refunc(self, regex, html):
"""功能函数2: 正则解析提取数据"""
r_list = re.findall(regex, html, re.S)
return r_list
def parse_html(self, url):
"""爬虫逻辑函数由此开始"""
# 1.获取一级页面响应内容,并提取每辆汽车详情页链接
# 2.依次拼接每辆详情页地址,发请求提取详情页数据
# 3.把结果打印输出(放到字典item中)
one_html = self.get_html(url)
one_regex = '<li data-scroll-track=.*?href="(.*?)"'
href_list = self.refunc(one_regex, one_html)
for href in href_list:
# 获取1辆汽车详情页的具体数据
self.get_car_info(href)
# 控制频率
time.sleep(random.uniform(0, 2))
def get_car_info(self, href):
"""获取一辆汽车具体数据的函数"""
two_url = 'https://www.guazi.com' + href
two_html = self.get_html(two_url)
two_regex = '<h1 class="titlebox">(.*?)<.*?<li class="two"><span>(.*?)</span>.*?<span>(.*?)</span>.*?<span>(.*?)</span>.*?<span class="price-num">(.*?)</span>'
# car_list:[('名字','里程','排量','变速箱','价格')]
car_list = self.refunc(two_regex, two_html)
item = {}
item['car_name'] = car_list[0][0].strip()
item['car_km'] = car_list[0][1]
item['car_displace'] = car_list[0][2]
item['car_type'] = car_list[0][3]
item['car_price'] = car_list[0][4]
print(item)
def crawl(self):
"""程序入口函数"""
for page in range(1, 11):
page_url = self.one_url.format(page)
self.parse_html(page_url)