c爬虫抓取网页数据(自用Python模块的建立和使用--抓取和存数据)
优采云 发布时间: 2022-03-19 20:01c爬虫抓取网页数据(自用Python模块的建立和使用--抓取和存数据)
我们在这个例子中所做的就是将b站当前在线界面的20个视频转换成
从网页中抓取av号、类型、作者名、视频名、点击量、弹幕数,存入数据库进行简单分析。
整个步骤分为两部分——采集和保存数据
【抓住】
继续我们之前用 Python 编写爬虫的经验,我们可以类似地抓取我们需要的信息。
例如,抓取视频名称
import urllib2
from bs4 import BeautifulSoup
mainUrl="http://www.bilibili.com/online.html"
def toOnline():
'''进入在线列表页面'''
resp=urllib2.urlopen(mainUrl)
return resp
def getPageContent():
resp=toOnline()
html = resp.read().decode('utf-8').encode('gbk')
soup = BeautifulSoup(html, "html.parser", from_encoding="gbk")
return soup
def delNameTag(x):
arr = []
for i in range(0, len(x)):
b = str(x[i]).replace('<p class="etitle">', '')
c = b.replace('', '')
arr.append(c)
return arr</p>
def getName():
'''获取视频名称'''
soup=getPageContent()
data=soup.select('p[class="etitle"]')
data=delNameTag(data)
return data
这给了我们一个收录视频名称的长度为 20 的数组。
经过多次编写Python爬虫脚本的练习,这里不再重复逻辑。
需要注意的是,每个部分的逻辑都被分离出来,抽象成方法。这使得代码更清晰,更容易在以后维护和修改。
【存入数据库】
抓取数据后,我们需要将数据存入数据库。
在这个例子中,我们构建了一个私有的自用 Python 模块来方便数据库的操作。
【自用Python模块的建立与使用】
1.C:\Python27\Lib\site-packages 新建 myutil.pth
此文件存储我们的自定义脚本目录:D:/mywork/23 planB/my_script
【注意】这个文件中的目录是反斜杠的!!!
2.在D:/mywork/23 planB/my_script目录下创建一个myutil文件夹
3.myutil 文件夹是我们自定义的 Python 模块脚本
4.[重要] 该文件夹下必须有__init__.py 文件。没有这个文件就会失败。
这个文件的内容是空的,它是做什么的?未知。. . .
5. DBUtil的代码如下
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
class DBConfig:
#线下
_user = 'root'
_password = '''1230'''
_user_stat = 'mkj'
_password_stat='pwd)'
_charset = 'utf8'
_use_unicode = False
#线下
_readHost = '127.0.0.1'
_writeHost = '127.0.0.1'
_statHost = '127.0.0.1'
@staticmethod
def _getHost(isWrite = True):
if isWrite:
return DBConfig._writeHost
else:
return DBConfig._readHost
@staticmethod
def getConnection(dbName = None, isWrite = True):
return MySQLdb.connect(host = DBConfig._getHost(isWrite), user = DBConfig._user, passwd = DBConfig._password, db = dbName, charset = DBConfig._charset, use_unicode = DBConfig._use_unicode)
@staticmethod
def getConnectionByHost(dbName = None, hostName = None):
if hostName == 'stat':
return MySQLdb.connect(host = DBConfig._statHost, user = DBConfig._user_stat, passwd = DBConfig._password_stat, db = dbName, charset = DBConfig._charset, use_unicode = DBConfig._use_unicode)
else :
return MySQLdb.connect(host = DBConfig._statHost, user = DBConfig._user, passwd = DBConfig._password, db = dbName, charset = DBConfig._charset, use_unicode = DBConfig._use_unicode)
class DBUtil:
__connRead = None
__connWrite = None
__conn = None
__dbName = None
__hostName = None
def __init__(self, dbName = None, hostName = None):
_dbName = dbName.split("_")
length = len(_dbName)
self.__hostName = hostName
if _dbName[length-1].isdigit():
_dbName.pop()
self.__dbName = ("_").join(_dbName)
else:
self.__dbName = dbName
def __getConnection(self, isWrite = True):
if self.__hostName :
if not self.__conn:
conn = DBConfig.getConnectionByHost(self.__dbName, self.__hostName)
self.__conn = conn
return self.__conn
if isWrite:
if not self.__connWrite:
conn = DBConfig.getConnection(self.__dbName, isWrite)
self.__connWrite = conn
return self.__connWrite
else:
if not self.__connRead:
conn = DBConfig.getConnection(self.__dbName, isWrite)
self.__connRead = conn
return self.__connRead
def queryList(self, sql = None, params = None):
if (not sql): return None
conn = self.__getConnection(False)
cursor = conn.cursor()
cursor.execute(sql, params)
rows = cursor.fetchall()
return rows
def queryRow(self, sql, params = None):
if (not sql):return None
conn = self.__getConnection(False)
cursor = conn.cursor()
cursor.execute(sql, params)
row = cursor.fetchone()
return row
def queryCount(self, sql = None, params = None):
if (not sql): return None
conn = self.__getConnection(False)
cursor = conn.cursor()
cursor.execute(sql, params)
row = cursor.fetchone()
if not row:
return 0
return row[0]
def update(self, sql = None, params = None):
if (not sql): return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.execute(sql, params)
conn.commit()
return True
def insert(self, sql = None, params = None, returnPk = False):
if (not sql): return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.execute(sql, params)
conn.commit()
if not returnPk:
return None
return cursor.lastrowid
def insertMany(self, sql = None, params = None):
if not sql or not params: return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.executemany(sql, params)
conn.commit()
return True
def delete(self, sql = None, params = None):
if (not sql): return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.execute(sql, params)
conn.commit()
return True
def deleteMany(self, sql = None, params = None):
if not sql or not params: return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.executemany(sql, params)
conn.commit()
return True
def transDelAndInsMany(self, insertSql = None, delSql = None, insertParams = None, delParams = None):
if not insertSql or not insertParams or not delSql or not delParams: return False
conn = self.__getConnection()
cursor = conn.cursor()
cursor.executemany(insertSql, insertParams)
cursor.executemany(delSql, delParams)
conn.commit()
return True
def close(self):
if self.__connRead:
self.__connRead.close()
self.__connRead = None
if self.__connWrite:
self.__connWrite.close()
self.__connWrite = None
if __name__ == '__main__':
print 'start'
dbUtil = DBUtil('netgame_trade_12')
只要记住这段代码。只需要知道几个需要改的地方:用户名密码和主机地址
_user = 'root'
_password = '''1230'''
#线下
_readHost = '127.0.0.1'
_writeHost = '127.0.0.1'
_statHost = '127.0.0.1'
这里readHost和writeHost是分开写的,也就是读写分离。
【保存数据到数据库】
数据拿到了,自定义模块就OK了。接下来,我们将数据存储在数据库中。
先介绍一下数据库模块
from myutil.DBUtil import DBUtil
然后连接到数据库
planBDBUtil = DBUtil('mydb')
那么操作代码如下
def insertData():
'''数据库操作'''
avid=getAvId()
typeid=getTypeId()
name=getName()
hits=getHits()
dm=getDm()
author=getAuthor()
sql='insert into mydb.PLAN_B(ID, AV_ID, TYPE_ID, AUTHOR, NAME, HITS, DM, CREATED_DATE)'
for i in range(len(avid)-1):
namei=str(name[i])
authori=str(author[i])
#sql = 'insert into mydb.PLAN_B(ID, AV_ID, TYPE_ID, NAME, HITS, DM, CREATED_DATE) values (null, %s, %s, "%s", %s, %s, now())'%(avid[i],typeid[i],namei,hits[i],dm[i])
sql=sql+' SELECT NULL,%s, %s, "%s", "%s", %s, %s, now() union '%(avid[i],typeid[i],authori,namei,hits[i],dm[i])
sql=sql+' SELECT NULL,%s, %s, "%s", "%s", %s, %s, now()'%(avid[len(avid)-1],typeid[len(avid)-1],author[len(avid)-1],name[len(avid)-1],hits[len(avid)-1],dm[len(avid)-1])
planBDBUtil.insert(sql, ())
这里我们是插入操作,最后一句
planBDBUtil.insert(sql, ())
insert 函数是我们从 DBUtil 中找到的,用于处理插入操作。
我们可以专注于如何编写 SQL 语句。
【注意:SQL调试器的使用】
在这个例子中,我们在编写 SQL 语句时,遇到了很多错误。在这个过程中,我们多次使用 Navicat 中的查询功能来调试 SQL。
注意我们使用这个私有定义。
接下来,我们讲解一下SQL语句中遇到的问题!
[问题 一、 插入不带引号的字符串]
我们插入字符串的时候,不能直接插入,一直报错。后来找到原因,
插入字符串时,需要引号!!!
NULL,%s, %s, "%s", "%s", %s, %s, now()
如果不带引号直接插入字符串,系统无法区分数据类型,插入失败!
[问题二、一次插入一堆数据]
这里我们运行一次脚本,需要插入20条数据。
传统做法是循环插入,即执行20次插入语句。但是如果有 10,000 条数据呢?您是否必须访问数据库 10,000 次?
经验告诉我们,我们只需要访问数据库一次。否则对数据库的压力太大了!
我们如何一次插入 20 条数据?经过研究,我们发现如下代码模板
INSERT INTO table1 (mc,zb_mc,xx_mc,leibie)
SELECT('aa',NULL,NULL,1390)union
SELECT('bb',NULL,NULL,1400)union
SELECT('cc',NULL,NULL,1410)union
SELECT('dd',NULL,NULL,1420)union
SELECT('ee',NULL,NULL,1430)union
SELECT('ff',NULL,NULL,1440)
执行一次这样的语句,就可以一次向数据库中插入多条记录。
因此,我们需要循环来拼写 SQL 字符串。
sql='insert into mydb.PLAN_B(ID, AV_ID, TYPE_ID, AUTHOR, NAME, HITS, DM, CREATED_DATE)'
for i in range(len(avid)-1):
namei=str(name[i])
authori=str(author[i])
#sql = 'insert into mydb.PLAN_B(ID, AV_ID, TYPE_ID, NAME, HITS, DM, CREATED_DATE) values (null, %s, %s, "%s", %s, %s, now())'%(avid[i],typeid[i],namei,hits[i],dm[i])
sql=sql+' SELECT NULL,%s, %s, "%s", "%s", %s, %s, now() union '%(avid[i],typeid[i],authori,namei,hits[i],dm[i])
sql=sql+' SELECT NULL,%s, %s, "%s", "%s", %s, %s, now()'%(avid[len(avid)-1],typeid[len(avid)-1],author[len(avid)-1],name[len(avid)-1],hits[len(avid)-1],dm[len(avid)-1])
我们注意到句子中间有一个并集,但结尾没有,所以我们需要取出最后一个单独拼写。
当然,我们也可以在生成SQL字符串后,删除字符串末尾的union这个词。任何一个!
至此,整个过程结束!