用之前获取到的数据对word2vec进行训练时发现得到的模型并不理想,所以为了使模型更加精确,我决定增加数据量继续进行训练
要从哪里获取大量的数据就是一个很头疼的事了,我一直没有很好的解决方案,直到昨天另外一个项目组开会时一个学长的方案给了我很大启发
这里数据的来源就是百度百科,经过观察很容易发现,百度百科有一个特点,其不同词条前半部分URL是相同的,都是https://baike.baidu.com/item/...,其差别主要在于末尾,在浏览器中我们看到的末尾就是该词条的名称,比如马化腾的百度百科词条URL就是,所以爬取不同词条时只需改变其末尾的词条名即可。
那么词条名我们从哪里找呢,之前用过的jieba分词给了我启发,当时我下载了搜狗输入法的词库用作分词的自定义词典,现在完全可以将搜狗输入法的词库用作搜索的关键词呀,只需要下载搜狗输入法细胞词库的scel文件,通过深蓝词库转换工具将其转换为txt文件即可,其格式完全符合我们爬虫的要求
但是这样做有一个限制,就是如果一个词有多个义项那么网站将会自动跳转至其第一个义项,比如如果要访问https://baike.baidu.com/item/GG,由于GG有很多含义,所以默认跳转到其第一个义项,即https://baike.baidu.com/item/GG/2256001,不过该问题对本项目并没有影响,以后使用时注意即可
下面是学长爬虫代码的改进版:
__author__='XJX'
__date__='2017.08.08'
#-*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
import urllib
from urllib import request
import re
import sys
import io
import sys
#reload(sys)
#sys.setdefaultencoding('utf-8')
def getHtml(url):
return urllib.request.urlopen(url).read().decode('utf-8')
#request = urllib.Request(url)
#print('mdzz')
#response = urllib.urlopen(request)
#return response.read().decode('utf-8')
file_in = r'C:\Users\JY\Desktop\1.txt'
file_out = r'C:\Users\JY\Desktop\data2.txt'
f = open(file_in,'r')
fp = open(file_out, 'w',encoding = 'utf8')
n = 0
flag = 0
for line in f:
line = line[:-1]
if str(line) == '糖尿病性心脏病':
flag = 1
if flag == 1:
try:
print(str(line))
url0 = "https://baike.baidu.com/item/"
url = url0 + urllib.parse.quote(str(line))
#print(url)
html = getHtml(url)
soup = BeautifulSoup(html,'html.parser')
#print(soup.title)
if str(soup.title) == '<title>百度百科——全球最大中文百科全书</title>':
print('404')
continue
#fp.write(u"#######################")
#fp.write(u"\n")
#fp.write(u"\n")
#fp.write(u"URL:")
#p.write(url)
#fp.write(u"\n")
#fp.write(u"title:")
#fp.write(u"\n")
#print('debug1')
#soup.title.string = soup.title.string.replace("_","")
#soup.title.string = soup.title.string.encode('utf-8').replace("百","")
#soup.title.string = soup.title.string.encode('utf-8').replace("度","")
#soup.title.string = soup.title.string.encode('utf-8').replace("科","")
#print('debug2')
#fp.write(soup.title.string)
#fp.write(u"\n")
#fp.write(u"\n")
#fp.write(u"content:")
#fp.write(u"\n")
#print('debug3')
for text in soup.find_all('div',class_="para"):
for div_tag in text.find_all('div', class_="description"):
div_tag.decompose()
if text.span:
text.span.decompose()
newstr ="".join(text.get_text().split())
#newstr = newstr.encode('gbk')
newstr = re.sub(r'\[[\d]*\]','',newstr)
newstr = re.sub(r'\[[\d]*-[\d]\]', '', newstr)
fp.write(newstr)
fp.write(u"\n")
#fp.write(u"\n")
n = n+1
print(n)
except:
print('error')
continue
fp.close()
f.close()
在学长原先爬虫代码的基础上主要改进了一下几个方面:
1.对URL中中文的处理
在实际应用时,我发现如果URL中出现中文,在访问时会出现异常,这是因为在网站实际访问时,其URL并不是像我们在浏览器看到的一样,而是将其转化为了urlencode形式,比如访问的实际是https://baike.baidu.com/item/%E9%A9%AC%E5%8C%96%E8%85%BE,但是爬虫在访问时就不会有这个过程,所以我们不能直接在URL中使用汉字,解决方法就是使用urllib库中的urllib.parse.quote()函数将汉字转化urlencode形式。
2.不存在页面的判断
原代码并无判断该词条是否存在的功能,需要对txt进行手动处理,保证该关键词的词条一定存在。
通过对百度百科页面的研究,我发现如果词条不存在时,将会返回一个错误页面
三秒后将会自动跳转到百度百科首页,通过查看该网页的源码,我发现其title是“<title>百度百科——全球最大中文百科全书</title>”,这与其他页面的title都不相同,而该爬虫所使用的bs4库里正好有一个soup.title函数,可以很方便的获取网页title,所以只需要对其title进行判断就可以知道该网页是否存在了,这里需要注意的是soup.title函数返回的是一个object,需要转化为String类型才能进行比较。
遇到不存在页面直接continue即可
经过这种方法获得了大量可靠的医学相关数据,爬取到了35000+的词条,模型的质量大大提升