来自 《Python项目案例开发从入门到实战》(清华大学出版社 郑秋生 夏敏捷主编)中爬虫应用——校园网搜索引擎html
这一部分的下半节代码内容主要讲的是 网页排名和搜索模块python
网页排名采用TF(Term Frequency)/IDF(Inverse Document Frequency)统计。
其中TF意思是词频,表示词条t在文档d中出现的频率。IDF意思是逆文本频率指数,计算公式是 idf = log(N/df),其中N是文档总数,df是包含词条t的文档数量,当有TF(词频)和IDF(逆文档频率)后,将这两个词相乘,就能获得一个词的TF-IDF的值。某个词在文章中的TF-IDF越大,那么通常而言这个词在这篇文章的重要性会越高,因此经过计算文章中各个词的TF-IDF,由大到小排序,排在最前面的几个词,就是该文章的关键词。web
注意: 要想这部分的代码运行成功,必定要先看个人博客中前两章的内容 《 python 爬虫应用——校园网搜索引擎(crawler application——Campus web search engine part-one)(上)》 而后生成 viewsdu.db 数据库才能够运行成功。sql
import sqlite3 import jieba import urllib import lxml import math from urllib import request from collections import deque from bs4 import BeautifulSoup # 连接已经建立好的数据库(这个在上一篇博客中已经教了如何建立)
conn = sqlite3.connect("viewsdu.db") # 建立游标对象
c = conn.cursor() # 计算doc浏览器中的总函数
c.execute('select count (*) from doc') # fetchall返回的是[(82,)],即文档的条目总数,为了计算IDF中的文档总数
N = 1 + c.fetchall()[0][0] # target = input('请输入搜索词: ')
target = '校园'
# 将搜索内容粉刺
seggen = jieba.cut_for_search(target) # 字典,用于存储“文档号: 文档得分”,文档得分越高,表示这个词在这个文档中的重要程度越高
score = {} for word in seggen: print('获得查询词', word) # 建立字典,返回的是word在每一个文档中出现的次数,即TF词频的结果
tf = {} c.execute('select list from word where term=?', (word,)) result = c.fetchall() if len(result) > 0: # 获得当 term=word 时的 list 的值,这里返回的是字符串,如'3 3 4 4 5 5 58 58'
doclist = result[0][0] # 根据空格切割字符串,返回列表如 ['3', '3', '4', '4', '5', '5', '58', '58',]
doclist = doclist.split(' ') # 把字符串转换为整型,返回的是 [3, 3, 4, 4, 5, 5, 58, 58]
doclist = [int(x) for x in doclist] # set是集合,python中的集合主要用来去重,set(doclist)后结果就是 {3, 4, 5, 58},最终df再获得长度4
df = len(set(doclist)) # 逆文本频率指数的计算公式,IDF=log(文档总数/包含词条的文档数量)
idf = math.log(N/df) # 计算词频TF,即在某文档中出现的次数,返回的结果是{3:2, 4:2, 5:2, 58:2}
for num in doclist: if num in tf: tf[num] = tf[num] + 1
else: tf[num] = 1
# !!!注意,当你看懂了这个是用字典表示列表中每一个字出现的次数的时候,你能够用下面这一行代码替换上面的5行代码,效果同样
# tf = {i: doclist.count(i) for i in doclist}
# TF统计结束,如今开始计算score=TF∗IDF
for num in tf: if num in score: # 若是该num文档已经有分数了,则累加
score[num] = score[num] + tf[num]*idf else: score[num] = tf[num]*idf # 对score字典按字典的值排序
sortedlist = sorted(score.items(), key=lambda d: d[1], reverse=True) print('得分列表', sortedlist) cnt = 0 for num, docscore in sortedlist: cnt = cnt + 1
# 根据num的值在doc浏览器中找到相对应的连接(网址)
c.execute('select link from doc where id=?', (num,)) # 获得具体连接的字符串
url = c.fetchall()[0][0] # 输出网址和对应得分
print(url, '得分: ', docscore) try: # 打开网页
response = request.urlopen(url) # 能够输出网页内容
content = response.read().decode('utf-8') except: print('oops...读取网页出错') continue
# 解析网页输出标题
soup = BeautifulSoup(content, 'lxml') # 获得网页标题
title = soup.title if title is None: print('No title') else: #
title = title.text print(title) # 超过20条则结束,即输出前20条
if cnt > 20: break
if cnt == 0: print('无搜索结果') pass
结果:数据库