目标:
在已经获得网页内容的前提下,除去自己不想要的内容,并且转化为 json格式的文本,导入到mongodb数据库中。
概要:
在上一次基础上(详见mongodb搭建校内搜索引擎——爬取网页文本)利用BeautifulSoup继续处理文本,过滤自己不感兴趣的标签中的文本,并用jieba分词模块,将文本分割成关键词,同时获得关键词在这个网页文档中的权重,最后用Python序列化,将python中的dict转化为json中的{}。
我的思考
1.在前一次的基础上,我发现结果文档会把html源码中如下内容提取出来:
这里是script标签中的内容,显然其中有很多我并不想要的信息,我选择过滤掉script标签中的内容,BeautifulSoup中有四种对象种类:Tag , NavigableString , BeautifulSoup , Comment .这里tag种类有属性.name,可以用tag.name找到所有script标签,并且对标签中的内容处理。
可以使用如下方法:
soup=BeautifulSoup(html_text,"lxml")#用BeautifulSoup获取网页内的纯文本
script=soup.find_all("script")#找到所有script的标签
for x in script:#判断script标签是否包含文本,若有,直接置为空
if x.string!=None:
x.string.replace_with(" ")
2.用jieba分词对文档分词,实现的基本思路是:
- 加载词典dict.txt
- 从内存的词典中构建该句子的DAG(有向无环图)
- 对于词典中未收录词,使用HMM模型的viterbi算法尝试分词处理
- 已收录词和未收录词全部分词完毕后,使用dp寻找DAG的最大概率路径
- 输出分词结果
实现起来并不麻烦,详细用法参见:fxsjy/jieba
可以用如下方法:
def text_cut(url,content,result_text):
withWeight=True
jieba.analyse.set_stop_words("stop_words.txt")#设置stopwords即设置过滤不提取的文字,比如说:"的","了"
jieba.analyse.set_idf_path("idf.txt")#设置文档,使得提取出的词语在文本中的权重得到调整
tags = jieba.analyse.extract_tags(content, topK=2000, withWeight=True)
if withWeight is True:
for tag in tags:#得到List
s=trs_2(url,tag[0],tag[1])
result_text.write(json.dumps(s,default=lambda obj: obj.__dict__,ensure_ascii=False))#序列化输出
result_text.write("\n")
else:
print(",".join(tags))
3.用序列化的方法,使得输出为标准的json格式,方便直接用mongoimport导入mongodb数据库。
可以用如下方法(详见:序列化):
class trs_2(object):#定义转化的类
"""docstring for trs_2"""
def __init__(self,url,key,frequency):
self.url=url
self.key=key
self.frequency=frequency
...
result_text.write(json.dumps(s,default=lambda obj: obj.__dict__,ensure_ascii=False))#序列化输出
源码:
#-*-coding:utf8-*-
from bs4 import BeautifulSoup
import requests
import re
import xlrd
import time
import jieba
import jieba.analyse
import sys
reload (sys)
sys.setdefaultencoding("utf-8")
import json
class trs_2(object):
"""docstring for trs_2"""
def __init__(self,url,key,frequency):
self.url=url
self.key=key
self.frequency=frequency
def get_text(url):
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36"}
html=requests.get(url,headers = headers)#获取网页源码
html_text=html.text
soup=BeautifulSoup(html_text,"lxml")#用BeautifulSoup获取网页内的纯文本
# fp_result=open("result_2.json","a")
script=soup.find_all("script")#找到所有script的标签
for x in script:#判断script标签是否包含文本,若有,直接置为空
if x.string!=None:
x.string.replace_with(" ")
row_number=0
fp_result.write(url)#打开文件结果以txt文件输出
fp_result.write("\n------------------------------------------\n")
script=soup.find_all("script")
for x in script:
if x.string!=None:
x.string.replace_with(" ")
content="".join(soup.stripped_strings)
text_cut(url,content,fp_result)
# fp_result.close()#关闭文件
def get_xls(path):#打开已经通过爬虫获取的url列表,并且逐个读取url
data=xlrd.open_workbook(path)#打开excle文件
table=data.sheets()[0]#打开工作表0
nrows=table.nrows#获取行数
finished_line=0
for i in range(nrows):#逐个输出每行的内容
ss=table.row_values(i)#获取列数
for j in range(len(ss)):#逐个输出每列的内容
finished_line+=1#记录完成进度
try:
get_text(ss[j])
process=1.0*finished_line/nrows
print "have finished %.3f" %process#记录完成进度
print str(finished_line)
except requests.exceptions.ConnectionError:#当出现requests.exceptions.ConnectionError时,将错误的链接记录到error.txt文件,错误原因有待进一步研究解决
fp_error.write(ss[j]+"\n")
print "target finished "+str(nrows)#记录总共的行数
def text_cut(url,content,result_text):
withWeight=True
jieba.analyse.set_stop_words("stop_words.txt")#设置stopwords即设置过滤不提取的文字,比如说:"的","了"
jieba.analyse.set_idf_path("idf.txt")#设置文档,使得提取出的词语在文本中的权重得到调整
tags = jieba.analyse.extract_tags(content, topK=2000, withWeight=True)
if withWeight is True:
for tag in tags:#得到List
s=trs_2(url,tag[0],tag[1])
result_text.write(json.dumps(s,default=lambda obj: obj.__dict__,ensure_ascii=False))#序列化输出
result_text.write("\n")
else:
print(",".join(tags))
fp_result=open("result_2.json","a")
fp_error=open("error.txt","a")#打开记录错误的文件
fp_error.write(time.strftime('%Y-%m-%d',time.localtime(time.time())))#记录此次运行时间
fp_error.write("\n------------------------------------------\n")
get_xls("cs.xlsx")#调用函数,获取内容
fp_error.close()#关闭错误文件
fp_result.close()