Python爬虫|Python爬虫入门(四):储存

系列专栏目录:

第一讲:Python爬虫|Python爬虫入门(一):爬虫基本结构&简单实例

第二讲:Python爬虫|Python爬虫入门(二):请求

第三讲:Python爬虫|Python爬虫入门(三):解析

第四讲:Python爬虫|Python爬虫入门(四):储存

------------------------萌萌哒的分割线------------------------


本篇我们接着上一篇教程(知乎专栏)继续讲。这篇主要讲一下一直没有实现的储存。事实上储存有很多种不同的方式,一般来说是要根据后期管理和分析的需要来选择储存方式。总体来说可以分为两大类:文件和数据库。数据文件格式多种多样,比如csv、dat、xml、xlsx等等。数据库有两大类:SQL和NoSQL(not only SQL)。这次我们主要介绍存入文件的csv格式。后续我们会介绍使用数据库储存。

为什么要用csv呢?这主要是从数据处理方面考虑的。无论是统计软件系列(R、Stata等)还是Python的pandas,都对csv有着天然的非常好的支持,所以推荐大家使用csv作为主要的文件储存方式。


一、Python的csv模块

Python的csv模块(13.1. csv - CSV File Reading and Writing - Python 2.7.13 documentation)是一个非常上天的标准库。这个标准库提供了各种各样的对于各种Python数据结构转换成csv等数据格式的支持。这里简单列举一些有用的函数和类及其方法,关于参数就不多介绍了,有兴趣可以自己去看官方文档。(其实我也不太用别的……)

#Python列表or元组与csv的转换
csv.reader(file)    #读出csv文件

csv.writer(file)    #写入csv文件
writer.writerow(data)    #写入一行数据
writer.writerows(data)    #写入多行数据 


#Python字典与csv的转换
csv.DictReader(file)    #读出csv文件

csv.DictWriter(file)    #写入csv文件  
writer.writeheader()    #写文件头
writer.writerow(data)    #写入一行数据
writer.writerows(data)    #写入多行数据 

二、储存:写入文件

我们接着昨天的代码。首先修改一下昨天的代码,把数据单独输出出来,使代码逻辑更清晰:
import requests
from bs4 import BeautifulSoup


def getHTML(url):
    r = requests.get(url)
    return r.content


def parseHTML(html):
    soup = BeautifulSoup(html,'html.parser')

    body = soup.body
    company_middle = body.find('div',attrs={'class':'middle'})
    company_list_ct = company_middle.find('div',attrs={'class':'list-ct'})
    
    company_list = []    #修改
    for company_ul in company_list_ct.find_all('ul',attrs={'class':'company-list'}):
        for company_li in company_ul.find_all('li'):
            company_url = company_li.a['href']
            company_info = company_li.get_text()
            company_list.append([company_info.encode('utf-8'),company_url.encode('utf-8')])    #修改,特别注意转码问题。
    
    return company_list    #修改


URL = 'http://www.cninfo.com.cn/cninfo-new/information/companylist'
html = getHTML(URL)
data_list = parseHTML(html)    #修改

好的,下面我们来把这个data_list写入文件:

# -*- coding: utf-8 -*-    
#上面这行是为了让中文能正常地写在.py文件里面
import codecs
import csv


def writeCSV(file_name,data_list):
    with open(file_name,'wb') as f:
        writer = csv.writer(f)
        for data in data_list:
            writer.writerow(data)

这段代码虽然很短,但是里面有很多东西,我们从with这行逐行解释一下:

第一行:

open函数是打开文件的。里面的两个个参数,第一个参数是文件名,第二个参数是写入方法,第三个参数是编码。读写方法常用的有几个,'r'是读,'w'是写,'a'是追加写入,后面加一个'b'是代表二进制读写。

with...as...是一个上下文管理协议。具体干什么暂时不用管它(其实我也不太能说明白),对于文件来说,它的作用就是相当于自动帮你管理文件的打开和关闭,不然的话你对一个文件需要这么做:

f = open('test','wb')
'''
sequences
'''
f.close()

所以使用with...as...是更安全的选择。

第二行:

前面提到的函数,目的是创建一个writer类,用来写入csv文件。

第三行、第四行:循环,把每一行写入文件。当然这里使用writerows也可以。

PS:关于编码,编码常用的就是'utf-8'这个系列的,还有就是'GB'系列的。注意,这里我们使用了utf-8编码,所以前面加入列表的数据也要先转成utf-8编码,不然就会报很坑的错误。编码是个大坑,我们后面专门讲一次。现在的编码处理还不是很好,先暂时这么用着……

PS的PS:不要用Excel打开数据文件,会乱码……因为我用不着用Excel打开(主要是不太会用Excel),所以就没有研究处理方法,如果有好的方案欢迎联系我~

三、完整代码示例

好的,最后让我们把代码拼一起:

# -*- coding: utf-8 -*-
import codecs
import csv

import requests
from bs4 import BeautifulSoup


def getHTML(url):
    r = requests.get(url)
    return r.content


def parseHTML(html):
    soup = BeautifulSoup(html,'html.parser')

    body = soup.body
    company_middle = body.find('div',attrs={'class':'middle'})
    company_list_ct = company_middle.find('div',attrs={'class':'list-ct'})
    
    company_list = []    #修改
    for company_ul in company_list_ct.find_all('ul',attrs={'class':'company-list'}):
        for company_li in company_ul.find_all('li'):
            company_url = company_li.a['href']
            company_info = company_li.get_text()
            company_list.append([company_info.encode('utf-8'),company_url.encode('utf-8')])    #修改
    
    return company_list    #修改


def writeCSV(file_name,data_list):
    with codecs.open(file_name,'wb') as f:
        writer = csv.writer(f)
        for data in data_list:
            writer.writerow(data)


URL = 'http://www.cninfo.com.cn/cninfo-new/information/companylist'
html = getHTML(URL)
data_list = parseHTML(html)    #修改
writeCSV('test.csv',data_list)

然后运行一下,就可以在与代码同目录的文件夹找到数据文件啦~

---

好的,到这里,我们的爬虫教程的入门系列就结束了。到这里,你应该学会的是单页静态网页的爬虫。这部分不在于讲方法而在于讲原理和提出问题。这部分的实现还有太多太多部分没有深入,我们会在后面的“深入网页请求”、“深入网页解析”、“深入数据储存”、“深入并发/海量数据的爬取”四个系列继续深入讨论。其中,“深入网页请求”系列将会深入讨论各种反爬策略、动态网页请求和对应的HTTP协议的知识;“深入网页解析”将会讲各种各样的解析方式,包括静态网页和动态网页的解析 ,数据格式包括直接解析字符串、re解析、bs4解析、json解析等,也会专门说说各种翻页技巧;“深入数据储存”系列我们会继续介绍csv的一些用法,以及坑爹的文件编码问题,也会深入介绍SQL和NoSQL的使用。“深入并发/海量数据的爬取”系列我们会介绍进程、线程、协程等基本概念及其实现,并用来提高爬虫效率,可能会有分布式方面的讨论。

PS:动态网页爬虫和翻页这两个专题可以放在接下来的四个系列穿插讲,也可以跟在入门系列后面,你可以把你的想法在评论区留言或者私信我~

------------------------萌萌哒的分割线------------------------


非商业转载注明作者即可,商业转载请联系作者授权并支付稿费。本专栏已授权“维权骑士”网站(rightknights.com)对我在知乎发布文章的版权侵权行为进行追究与维权。


项目联系方式:

编辑于 2017-02-07

文章被以下专栏收录

    WISER Club是厦门大学的一个数据科学(包括但不限于R&Python)学习兴趣组织,我们团队有一批对R语言和Python有浓厚兴趣的爱好者,我们将要承担第九届中国R语言会议(厦门会场)的举办。我们想通过这个专栏给大家分享一些关于R、关于Python、关于数据科学的技术文章和资源。

    微信公众号同名,欢迎投稿。全平台约20万开发者关注,会员来自全球十多个国家和地区,拥有十多个线上线下技术社群,向本专栏投稿即默认发布到Python中文社区全平台。Telegram:t.me/PyChina