参考链接:https://blog.csdn.net/qq_45775027/article/details/115319253
最近需要使用到爬虫+数据库,原文中作者有些没补齐,略作修改之后跑通了。
主要修改:
1.调整了数据获取的正则表达式;
2. 改了一下数据库的table名和定义名字;
3.加了数据清洗的模块;
实现了爬取qs大学排名,以及存储数据到数据库。
1.效果如下图:
2.使用工具以及环境:
python3.7环境,数据库软件navicat161_premium_en_x86.exe。
一键运行代码,生成对应的db文件,查看内容,和预期一致。
3.完整代码如下:
##参考链接:https://blog.csdn.net/qq_45775027/article/details/115319253
import sqlite3
import re
import time
import requests
from lxml import html
findNameData = re.compile(r'<td style="outline: none !important;">(.*?)</td>')
# =============================================================================
# findname = re.compile(r'<a href=".*?">(.*?)</a>')
# findname3 = re.compile(
# r'<td style="outline: 0px !important;"><p style="line-height: 1.8; outline: 0px !important;">(.*?)</p></td>')
# findname4 = re.compile(
# r'<td style="outline: 0px !important;"><p style="line-height: 1.8; outline: 0px !important;"><a href=".*?">(.*?)</a>.*?</p></td>')
# findaddres = re.compile(r'<td style="outline: 0px !important;">(.*?)</td>')
# findadress1 = re.compile(r'<td style="outline: 0px !important;"><a href=".*?">(.*?)</a></td>')
#
# findlink = re.compile(r'<a href="(.*?)"') # 创建正则表达式对象,表示规则(字符串的模式)
# =============================================================================
'''
通过findall找到所有table里面的tr
然后对tr里面的内容进行解析,如果没有链接,则data添加信息为空,有链接调用函数来解析链接网页
再向数据库传输解析内容
'''
def main():
basicurl = "http://www.qianmu.org/ranking/1528.htm"
datalist = getData(basicurl)
#datalist = [[166,11,12,13],[188,22,23,24]]
for data in datalist:
print(data)
saveDatadb(datalist,"rankData.db")
# 得到一个指定的网页内容
def askURL(url):
et = html.etree
respon = requests.get("http://www.qianmu.org/ranking/1528.htm")
selector = et.HTML(respon.text)
return selector
# 爬取主网页,将网页的tr提取出来进行分析
def getData(basicurl):
datalist = []
selector = askURL(basicurl)
# 找出每个tr,对每个tr解析
trs = selector.xpath('//div[@class="rankItem"]//tr[position()>1]')
# names = selector.xpath('//div[@class="rankItem"]//tr[position()>1]/td/a/text() | //div[@class="rankItem"]//tr['
# 'position()>1]/td[2]/text()')
# links = selector.xpath('//div[@class="rankItem"]//tr[position()>1]/td/a/@href')
# 获得了每一个tr内容
for tr in trs:
data = []
tr = html.tostring(tr, encoding='utf-8').decode('utf-8')
name1 = re.findall(findNameData, tr)
for tmp in range(len(name1)):
name1[tmp] = cleanData(name1[tmp])
print(name1[tmp])
data.append(name1[1])
data.append(name1[2])
data.append(name1[3])
data.append(name1[0])
datalist.append(data)
return datalist
# 清洗数据,去除<>及中间内容,将"替换为'
def cleanData(basename):
if not basename:
return
while ( "<" in basename):
s_index = basename.index("<")
e_index = basename.index(">")
rm_str = basename[s_index:e_index+1]
basename = basename.replace(rm_str,"")
while ( "\"" in basename):
basename = basename.replace('\"','\'')
return basename
# 保存数据
def saveDatadb(datalist, dbpath):
init_db(dbpath)
conn = sqlite3.connect(dbpath)
cur = conn.cursor() # 获取游标
# print("我执行了")
for data in datalist:
for index in range(len(data)):
data[index] = '"' + str(data[index]) + '"' # '"'+data[index]+'"'
sql = '''
insert into rankData(
name, ename, address, rank)
values (%s)''' % ",".join(data)
print(sql)
cur.execute(sql)
conn.commit() # 提交
cur.close()
conn.close() # 关闭链接
# 创建数据库
def init_db(dbpath):
#创建表之前判断不存在才创建,存在则跳过
sql = '''
create table rankData(
id integer primary key autoincrement,
name text ,
ename text ,
address text ,
rank text
);
'''
conn = sqlite3.connect(dbpath) # 建表
cursor = conn.cursor() # 游标
cursor.execute(sql) # 执行sql语句建表
conn.commit() # 提交
conn.close() # 关闭
if __name__ == "__main__": # 当程序执行时,调用函数 这样写的目的是严格控制函数执行的主流程
main()
4.上述程序使用的sqlite数据库,无需单独配置。
完整代码如上,本次实验对应的db文件以及数据库软件,已上传,设置的0积分,如果需要自行下载。
https://download.csdn.net/download/zhangb98/87364130