一、前言
这篇文章,我们将会尝试从零搭建一个简单的新闻搜索引擎
当然,一个完整的搜索引擎十分复杂,这里我们只介绍其中最为核心的几个模块
分别是数据模块、排序模块和搜索模块,下面我们会逐一讲解,这里先从宏观上看一下它们之间的工作流程
二、工作流程
三、数据模块
数据模块的主要作用是爬取网络上的数据,然后对数据进行清洗并保存到本地存储
一般来说,数据模块会采用非定向爬虫技术广泛爬取网络上的数据,以保证充足的数据源
但是由于本文只是演示,所以这里我们仅会采取定向爬虫爬取中国社会科学网上的部分文章素材
而且因为爬虫技术我们之前已经讲过很多,这里就不打算细讲,只是简单说明一下流程
首先我们来源gaodaimacom搞#^代%!码网定义一个数据模块类,名为 DataLoader
,类中有一个核心变量 data
用于保存爬取下来的数据
以及两个相关的接口 grab_data
(爬取数据) 和 save_data
(保存数据到本地)
grab_data()
的核心逻辑如下:
1.首先调用 get_entry()
,获取入口链接
def get_entry(self): baseurl = 'http://his.cssn.cn/lsx/sjls/' entries = [] for idx in range(5): entry = baseurl if idx == 0 else baseurl + 'index_' + str(idx) + '.shtml' entries.append(entry) return entries
2.然后调用 parse4links()
,遍历入口链接,解析得到文章链接
def parse4links(self, entries): links = [] headers = { 'USER-AGENT': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } for entry in entries: try: response = requests.get(url = entry, headers = headers) html = response.text.encode(response.encoding).decode('utf-8') time.sleep(0.5) except: continue html_parser = etree.HTML(html) link = html_parser.xpath('//div[@class="ImageListView"]/ol/li/a/@href') link_filtered = [url for url in link if 'www' not in url] link_complete = [entry + url.lstrip('./') for url in link_filtered] links.extend(link_complete) return links
3.接着调用 parse4datas()
,遍历文章链接,解析得到文章内容
def parse4datas(self, entries): datas = [] headers = { 'USER-AGENT': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } data_count = 0 for entry in entries: try: response = requests.get(url = entry, headers = headers) html = response.text.encode(response.encoding).decode('utf-8') time.sleep(0.2) except: continue html_parser = etree.HTML(html) title = html_parser.xpath('//span[@class="TitleFont"]/text()') content = html_parser.xpath('//div[@class="TRS_Editor"]//p//text()') content = [cont.replace('\u3000', '').replace('\xa0', '').replace('\n', '').replace('\t', '') for cont in content] content = [cont for cont in content if len(cont) > 30 and not re.search(r'[《|》]', cont)] if len(title) != 0 or len(content) != 0: data_count += 1 datas.append({ 'id' : data_count, 'link': entry, 'cont': '\t'.join(content), 'title': title[0] }) return datas