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) 
                     
                    
                 
                    
                