zoukankan      html  css  js  c++  java
  • 爬虫数据存储

    爬取的数据,需要保存,可以存储在文件中或者数据库中。

    • 存储在文件中,包括txt、csv、json;
    • 存储在数据库中,包括MySQL关系数据库和MongoDB数据库。

    python 字典操作参考:
    http://jianwl.com/2017/08/22/高效实用Python字典的清单/

    python 读写参考:
    https://www.cnblogs.com/liutongqing/p/6892099.html

    1、基本存储:存储至txt、csv、json

    (1)存入txt文件(saving_data.py)

    all_house数据结构:all_house[{'house_area':dd,'price':dd,'build_year':dd},{},{}...]

    f=open('net_saving_data.txt','w');
    for item in all_house:
        # house_area=item['house_area'];
        # price=item['price'];
        output='	'.join([str(item['house_area']),str(item['price']),str(item['build_year'])]);
        f.write(output);
        f.write('
    ');
    f.close();
    

    效果如图:

    • 若需要将几个变量写入txt中,可以用' '.join(["house_area","price","build_year"]),注意join()内是个列表

    (2)存入CSV文件(saving_data.py)

    CSV(Comma-Separated_values),以逗号分隔值的文件格式,文件以纯文本格式存储表格数据(数字和文本),每一行以换行符分隔,列与列之间用逗号分隔。与txt比较,能够存储的数据大小差不多,但是数据以逗号分隔较整齐,所有python网络爬虫经常用此来存储数据。

    • 从字典中写入csv文件
    import csv;
    
    f=open('net_saving_data.csv','w');
    csv_write=csv.writer(f);
    for item in all_house:
        csv_write.writerow([item.get('house_area',None),item.get('price',None),item.get('build_year',None)]);
        #f.write('
    ');
    f.close();
    

    效果如图:

    若是想在csv中加入key值,操作如下:

    csv_write.writerow(['house_area',item.get('house_area',None),'price',item.get('price',None),'build_year',item.get('build_year',None)]);
    

    效果如图:

    • 从列表中写入csv文件
    houses=[['2edr','ser','sge'],['as','hi','hioh','aaajio']];
    f=open('saving_data.csv','w');
    csv_write=csv.writer(f);
    for house in houses:
        csv_write.writerow([item for item in house]);
    f.close();
    

    效果如图:

    (3)写入json文件

    ##写入
    with open("anjuke_salehouse.json","w",encoding='utf-8') as f:
        json.dump(all_house,f,ensure_ascii=False);
        print(u'加载入文件完成...');
    

    2、csv、json、txt读取:

    (1)csv读取

    -参考:https://www.cnblogs.com/liutongqing/p/6892099.html

    import csv;
    houses=[];
    with open('net_saving_data.csv','r') as openscv:
        csv_reader=csv.reader(openscv);
        for row in csv_reader:
           houses.append(row); 
        openscv.close();
    print houses;
    

    原数据界面:

    读取数据界面如下:

    (2)json读取

    ##读入
    with open("anjuke_salehouse.json",'r',encoding='utf-8') as f:
        load_dict=json.load(f);
    print (load_dict);
    

    什么的不要想,直接load出来的就是json文件格式一模一样的一个对象。 主要是防止乱码的等参数设置。

    (3)txt读取

    参考文章:https://blog.csdn.net/shandong_chu/article/details/70173952

    with open('net_saving_data.txt','r') as opentxt:
        txt_reader=opentxt.readlines();
    for lin in txt_reader:
        print (lin);
    

    3、MySQL数据库操作

    建库、更删改查,因为下面涉及一些对数据库的操作,现在这里复习一下基本的更删改查

    (1)建数据库、建表

    create table urls(id int NOT NULL auto_increment,url varchar(1000) NOT NULL,content varchar(4000) NOT NULL,created_time timestamp default current_timestamp,primary key(id));
    */
    

    (2)查表结构或查database

    describe urls;
    show databases;
    

    (3)表中插入数据

    insert into urls(url,content)values("www.baidu.com","这是内容。")
    select * from urls where id=1;
    

    (4)从数据表中提取数据

    insert into urls(url,content)values("www.blog.com","博客网址。");
    select * from urls ;
    

    (5)删除数据

    delete from urls where url='www.baidu.com';
    select * from urls ;
    

    (6)修改数据
    将id=2的content改成博客园

    insert into urls(url,content)values("www.santostang.com","Santos blog");
    update urls set url='www.blog.com',content="博客园" where id=2;
    select * from urls ;
    

    (7)语句参考地址:https://blog.csdn.net/ljxfblog/article/details/52066006

    UNION

    select * from a order by id) union (select * from b order by id);
    
    • 如果不同的语句中取出的行,有完全相同(这里表示的是每个列的值都相同),那么union会将相同的行合并,最终只保留一行。也可以这样理解,union会去掉重复的行。如果不想去掉重复的行,可以使用union all。如果子句中有order by,limit,需用括号()包起来。推荐放到所有子句之后,即对最终合并的结果来排序或筛选。两次查询的列数必须一致

    JOIN

    //使用连表查询
    SELECT Persons.LastName, Persons.FirstName,Orders.OrderNo
    FROM Persons, Orders
    WHERE Persons.Id_P = Orders.Id_P 
    
    //使用join查询(inner join)
    SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    INNER JOIN Orders
    ON Persons.Id_P = Orders.Id_P
    ORDER BY Persons.LastName
    



    • 有时为了得到完整的结果,我们需要从两个或更多的表中获取结果。我们就需要执行 join。 数据库中的表可通过键将彼此联系起来。主键(Primary Key)是一个列,在这个列中的每一行的值都是唯一的。在表中,每个主键的值都是唯一的。这样做的目的是在不重复每个表中的所有数据的情况下,把表间的数据交叉捆绑在一起。上面的例子中使用的 INNER JOIN(内连接),JOIN默认使用内连接,可以省略INNER。 我们还可以使用其他几种连接。

    LEFT JOIN

    //使用left join查询,只要左表有匹配的条件,就会生成一行,右表的列值为空。
    SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    LEFT JOIN Orders
    ON Persons.Id_P=Orders.Id_P
    ORDER BY Persons.LastName
    



    RIGHT JOIN

    //使用right join查询,只要右表有匹配的条件,就会生成一行,左表的列值为空。
    SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    RIGHT JOIN Orders
    ON Persons.Id_P=Orders.Id_P
    ORDER BY Persons.LastName
    



    FULL JOIN

    //使用full join查询,只要其中一个表中存在匹配,就会生成一行,另一个表的列值为空。
    SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    FULL JOIN Orders
    ON Persons.Id_P=Orders.Id_P
    ORDER BY Persons.LastName
    



    • JOIN: 如果表中有至少一个匹配,则返回行(INNER JOIN 与 JOIN)
    • LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
    • RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
    • FULL JOIN: 只要其中一个表中存在匹配,就返回行

    ALTER

    alter table urls add created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
    #增加一列
    alter table test modify content char(10) 
    #修改表列类型
    

    4、python操作MySQL数据库

    参考文献:https://www.cnblogs.com/whatisfantasy/p/6134660.html

    在操作数据库的时候,python2中一般使用mysqldb,但在python3中已经不在支持mysqldb了,我们可以用pymysql和mysql.connector。本文的所有操作都是在python3的pymysql下完成的。python -m pip install pymysql

    mysql -u root -p
    using mysql;
    select host,user from mysql.user;
    

    mysql的host、user、password等信息。

    查询

    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping');
    cur=conn.cursor();#获取方法,创建游标
    
    sql='select * from urls';
    recount=cur.execute(sql);#操作execute()方法写入sql语句
    data=cur.fetchall(); # 返回数据,返回的是tuple类型
    print data;
    
    • conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping')用于创建数据库的连接,里面指定参数(用户名,密码,主机信息)。cur=conn.cursor()通过获取的数据库连接conn下的cursor()方法来创建游标,之后通过游标操作execute()方法写入纯SQL语句。完成MySQL数据库操作后,需要关闭游标cur和连接conn。

    插入数据

    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping');
    cur=conn.cursor();
    
    sql1='insert into urls(url,content)values(%s,%s)';
    params=('www.sinlang.com','新浪微博');
    recount=cur.execute(sql1,params);
    ##executemany 批量插入
    li=[('www.blogs.com','批量插入的第一个'),('www.sou.com','批量插入的第二个')];
    sql2='insert into urls(url,content)values(%s,%s)';
    recount=cur.executemany(sql2,li);
    
    sql3=sql='select * from urls';
    recount=cur.execute(sql3);
    data=cur.fetchall();
    conn.commit;
    cur.close;
    conn.close;
    
    print data;
    #返回的都是元组((1,'','',time),(2,'','',time)...(6,'','',time));
    
    • 其中commit只要执行一次,以上都是返回元组。

    插入数据,返回dict类型的数据

    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping');
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor);# 参数设置
    sql='select * from urls';
    recount=cur.execute(sql);
    
    data=cur.fetchall();
    cur.close();
    conn.close();
    print recount;
    print data;
    #返回的是列表含字典[{u'url': 'www.baidu.com', u'content': 'xxx', u'id': 1, u'created_time': datetime.datetime(2018, 8, 22, 22, 2, 23)}, {xxx}, {xxx}];
    

    fechone来逐条获取数据或者for循环

    • for 循环获取数据
    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping');
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor);
    sql='select * from urls';
    recount=cur.execute(sql);
    
    data=cur.fetchall();
    for i in range(len(data)):
        print data[i]
    cur.close();
    conn.close();
    print recount;
    
    • fechone来逐条获取数据
    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='scraping');
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor);
    sql='select * from urls';
    recount=cur.execute(sql);
    
    cur.close();
    conn.close();
    print recount;
    
    for i in range(recount):
        data=cur.fetchone();
        print data;
    

    两种方法获取结果都如下:

    5、爬取网页数据存入MySQL数据库

    (1) 在cmd 数据库中先创建database 和相应表;

    create database anjuke;
    use anjuke;
    create table anjuke (id int not null Auto_increment,house_title varchar(1000) not null,house_layout varchar(1000) not null,house_area int not null,house_levers int not null,brokername varchar (1000),address varchar(2000),price int not null,primary key(id));
    

    (2)将数据插入数据库中,爬取的数据格式如下[{},{},{},{}]。for循环列表,提取每一个字典中的信息,建立sql语义传参至execute中。

    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='anjuke');
    cur=conn.cursor();
    for item in all_house:
        house_title=item['house_title'];
        house_layout=item['house_layout'];
        house_area=item['house_area'];
        house_levers=item['house_levers'];
        brokername=item['brokername'];
        house_address=item['house_address'];
        price=item['price'];
        sql='insert into anjuke(house_title,house_layout,house_area,house_levers,address,brokername,price) values (%s,%s,%s,%s,%s,%s,%s)';
        #parme=(house_title,house_layout,house_area,house_levers,house_address,brokername,price);
        #cur.execute(sql,parme);
        cur.execute(sql,(house_title,house_layout,house_area,house_levers,house_address,brokername,price));
    conn.commit();
    cur.close();
    conn.close();
    

    (3) 读取存入MySQL数据库de网页爬取数据,可以[{},{},{}...{}]或者{}/n{}/n{}/n.../n{}形式输出。

    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='anjuke');
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor);
    sql='select * from anjuke';
    cur.execute(sql);
    conn.close();
    cur.close();
    data=cur.fetchall();#[{},{},{}...{}]
    print data;
    
    conn=pymysql.connect(host='localhost',user='root',passwd='123456',db='anjuke');
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor);
    sql='select * from anjuke';
    recount=cur.execute(sql);
    conn.close();
    cur.close();
    for i in range(recount):
        data=cur.fetchone();
        print data;
    
    • 可close()后,再对cur进行data的输出。

    总结 NOTE

    • 数据存至txt csv有固定格式,记住就好
    • 存到mysql,主要是连接数据库:conn=mysql.connect()、获取游标:cur=conn.cursor、对数据库操作:cur.execute(sql)、获取数据库:cur.fetchall()四个操作进行数据库操作。一般获取后,可以不用commit,存入数据等需要conn.commit(),但都要conn.close(),cur.close()
    • 另外深入可参考:http://www.runoob.com/python/python-mysql.html
  • 相关阅读:
    Metadata Lock原理5
    Seconds_Behind_Master
    Metadata Lock原理4
    MySQL Troubleshoting:Waiting on query cache mutex 腾讯数据库工程师:幕南风
    Metadata Lock原理2
    Metadata Lock原理1
    Online DDL与pt-online-schema-change
    Solaris 安装JDK
    RAID 概述
    4K Block Size的Device和 Aligned IO
  • 原文地址:https://www.cnblogs.com/mingjiatang/p/9543293.html
Copyright © 2011-2022 走看看