博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python网络数据采集-第5章存储数据
阅读量:4126 次
发布时间:2019-05-25

本文共 8171 字,大约阅读时间需要 27 分钟。

5.1 媒体文件简述

网络上的资源很多,有图片,视频,常规文件rar\zip等,由于网络爬去的数据量大,如果直接保存,相对只保存对应的链接字符串,有很多缺陷:1、由于下载,导致爬取速度慢;2、消耗存储空间;3、而且还要实现文件下载的方法,繁琐;优点:1、防止由于盗链改变导致的信息丢失(盗链即网页内部通往外部网页的链接),盗链所连接的信息可能变化

简单地文件下载

# 1、单个文件下载from urllib.request import urlretrievefrom urllib.request import urlopenfrom bs4 import BeautifulSoup'''爬去网页示例内容
# 批量爬取文件并下载import osfrom urllib.request import urlopenfrom urllib.request import urlretrievefrom bs4 import BeautifulSoup'''爬去网页示例内容

5.2 把数据存储到csv中

这里的意思是将Html中的表格数据存储到csv表格中。1、找到一个table标签及其对应的id;2、找到所有的tr标签,即所有的行信息;3、遍历所有的行信息,找到每行对应的td或者th标签,写入csv中

# 例1:简单地csv文件写入# 文件如果不存在会自动创建import csvcsvFile = open("files/test.csv","w+")try:    writer = csv.writer(csvFile)    writer.writerow(('number1','number2','number3'))    for i in range(10):        writer.writerow((i,i+2,i*2))finally:    csvFile.close()# 例2,网页信息写入csvfrom urllib.request import urlopenfrom bs4 import BeautifulSoupimport codecshtml = urlopen("https://baike.baidu.com/item/%E5%9B%BD%E5%86%85%E7%94%9F%E4%BA%A7%E6%80%BB%E5%80%BC/31864?fromtitle=GDP&fromid=41201")bsObj = BeautifulSoup(html,"html5lib")# print(bsObj)table = bsObj.findAll("table",{
"class":"table-view log-set-param"})[1]rows = table.findAll("tr")'''excel打开csv文件,可以识别编码“GB2312”,但是不能识别“utf-8”,数据库里的字符串编码是utf-8.因此:当从csv读取数据(data)到数据库的时候,需要先把GB2312转换为unicode编码,然后再把unicode编码转换为utf-8编码:data.decode('GB2312').encode('utf-8')当从数据库读取数据(data)存到csv文件的时候,需要先把utf-8编码转换为unicode编码,然后再把unicode编码转换为GB2312编码:data.decode('utf-8').encode('GB2312')'''# windows下使用GB2312# linux下使用utf-8csvFile = open("files/gdpList.csv",'wt',newline='',encoding="GB2312")writer = csv.writer(csvFile)# 另外注意pycharm中打开csv文件肯能感觉是乱的,其实就是以逗号分开的,没有问题try: for row in rows: csvRow = [] for cell in row.findAll('td'): csvRow.append(cell.getText()) writer.writerow(csvRow)finally: csvFile.close()

实验结果:

5.3 python连接mysql

这里的连接和java都是一个道理,但是相比java要简便很多。安装pymysql库后自动导入就可以使用pymysql

'''# 1、简单实验:import pymysqlconn = pymysql.Connect("localhost","root","root","pythontes")cur = conn.cursor()cur.execute("select * from pages")# fetchone():"""Fetch the next row"""# fetchall():"""Fetch all the rows"""for row in cur.fetchall():    print(row)    cur.close()conn.close()# 以上输出为:# ('a1', 'liuBei', '123')# ('a2', 'guanYu', '123')# ('a3', 'zhangSanFei', '123')'''# 2、网页保存到mysql# 数据库存储网页信息# 还是上次那个GDP排名数据from urllib.request import urlopenfrom bs4 import BeautifulSoupimport codecsimport pymysqlhtml = urlopen("https://baike.baidu.com/item/%E5%9B%BD%E5%86%85%E7%94%9F%E4%BA%A7%E6%80%BB%E5%80%BC/31864?fromtitle=GDP&fromid=41201")bsObj = BeautifulSoup(html,"html5lib")# print(bsObj)table = bsObj.findAll("table",{
"class":"table-view log-set-param"})[1]rows = table.findAll("tr")# 输出到数据库mysqlconn = pymysql.connect("localhost","root","root","pythontes")# 错误记录1:UnicodeEncodeError: 'latin-1' codec can't encode character# 原因:windows系统编码不同# 参考链接:https://stackoverflow.com/questions/3942888/unicodeencodeerror-latin-1-codec-cant-encode-characterconn.set_charset("utf8")cur = conn.cursor()try: tag = True for row in rows: # 这里需要跳过第一行说明部分 if tag: tag = False continue csvRow = [] for cell in row.findAll('td'): csvRow.append(cell.getText()) print(csvRow) ''' 错误记录2: 由于爬取的网页都是字符串类型,但是数据库不支持格式转换写入, 即(%d,int(csvRow[0]))转换无效,所以只能将所有的类型保存为字符串类型 ''' # 一种写法 # cur.execute("insert into gdpList values(%s,%s,%s,%s,%s,%s)",(csvRow[0],csvRow[1],csvRow[2],csvRow[3],csvRow[4],csvRow[5])) # 另一种写法 sql = "insert into gdpList values(%s,%s,%s,%s,%s,%s)" cur.execute(sql,csvRow) # 提交 cur.connection.commit()finally: cur.close() conn.close()

数据库实现网络图的爬取(深度爬取)

简要谈谈数据库的优化:

  • id和主键:首先最好每一个表都要有一个id字段,对数据查找都是有帮助的;关键字一般创建为单一不变的值,最能代表此行数据的字段
  • 索引:索引用该改善数据的查找优化,根据不同的数据形式设定对应的索引,索引相当于字典,比如我们可以对创建一个字段的前10个字符作为索引:1、ALTER TABLE table_name ADD INDEX index_name (column_list(10)) ;2、CREATE INDEX index_name ON table_name (column_list(10))。
  • 分表来节省空间和时间:单个数据表可能存在大量的重复数据,比如统计一个镇的所有居民信息,对于村这个字段,可能很多人都是在一个村,所以存在大量的重复。因此分为:镇-村表,和村-居民表,要节省不少空间,同时查询速度也快

以下为爬取深度网络,并将网络链接对应信息保存;使用了两个数据库表

# 建数据库表CREATE TABLE `pages` (`id` INT NOT NULL AUTO_INCREMENT,`url` VARCHAR(255) NOT NULL,`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`))CREATE TABLE `links` (`id` INT NOT NULL AUTO_INCREMENT,`fromPageId` INT NOT NULL,`toPageId` INT NOT NULL,`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`))
""" @author: zoutai@file: linkToLink.py @time: 2018/01/24 @description: 爬取一个深度为4的网络,保存网络之间的连接关系(两两对应)"""import refrom urllib.request import urlopenimport pymysqlfrom bs4 import BeautifulSoupconn = pymysql.connect("localhost", "root", "root", "pythontes")conn.set_charset("utf8")cur = conn.cursor()# 定义一个set,对page进行去重pages = set()def insertLink(fromPageId, toPageId):    cur.execute("select * from links where fromPageId = %s and toPageId = %s", (int(fromPageId), int(toPageId)))    if cur.rowcount == 0:        cur.execute("insert into links (fromPageId,toPageId) values (%s,%s)", (int(fromPageId), int(toPageId)))        conn.commit()# 返回当前url存储的iddef insertPage(pageUrl):    cur.execute("select * from pages where url = %s", (pageUrl))    if cur.rowcount == 0:        cur.execute("insert into pages (url) values (%s)", pageUrl)        conn.commit()        return cur.lastrowid    else:        return cur.fetchone()[0]def getLinks(pageUrl, recursionLevel):    global pages    if recursionLevel < 0:        return    pageId = insertPage(pageUrl)    html = urlopen("https://en.wikipedia.org" + pageUrl)    bsObj = BeautifulSoup(html, "html5lib")    for link in bsObj.findAll("a", href=re.compile("^(/wiki/)((?!:).)*$")):        insertLink(pageId, insertPage(link.attrs["href"]))        if link.attrs['href'] not in pages:            newPage = link.attrs['href']            pages.add(newPage)            getLinks(newPage, recursionLevel - 1)getLinks("/wiki/Kevin_Bacon", 2)

5.4 发送Email数据,使用163的SMTP邮件服务器

“””

@author: zoutai
@file: sendEmail.py
@time: 2018/01/24
@description: 邮件发送
“”“

完全参考:

from smtplib import SMTPfrom email.mime.text import MIMETextfrom email.header import Headerdef send_email(SMTP_host, from_addr, password, to_addrs, subject, content):    email_client = SMTP(SMTP_host)    email_client.login(from_addr, password)    # create msg    msg = MIMEText(content,'plain','utf-8')    msg['Subject'] = Header(subject, 'utf-8')#subject    msg['From'] = 'soundslow
' msg['To'] = "xx@qq.com" email_client.sendmail(from_addr, to_addrs, msg.as_string()) email_client.quit()if __name__ == "__main__": send_email("smtp.163.com","xxx@163.com","xxx","530337704@qq.com","来自163的邮件","今晚的卫星有点亮")

转载地址:http://yqepi.baihongyu.com/

你可能感兴趣的文章
一些很酷的.Net技巧
查看>>
鲍尔默致员工信:部署09年微软5大工作重心
查看>>
使用ScriptManager控件
查看>>
程序员四大忌
查看>>
JavaScript基础知识
查看>>
ScriptManager 以及ScriptManagerProxy Service属性的使用
查看>>
在 ASP.NET AJAX 中使用 Web 服务
查看>>
UpdatePanel的使用注意
查看>>
JavaScript常见问题总结
查看>>
Web实用小工具推荐使用
查看>>
.NET垃圾回收机制详解与心得体会
查看>>
不能不去的jQuery网站
查看>>
品味《编程之美》
查看>>
一维表转换成二维表
查看>>
获取文件目录的两种方法
查看>>
永不言弃
查看>>
"Not associated with a trusted SQL Server connection"解决方法
查看>>
C#修改文件或文件夹名称
查看>>
解决回车刷新页面问题
查看>>
FCKeditor使用说明
查看>>