zoukankan      html  css  js  c++  java
  • python 爬虫应用——校园网搜索引擎(crawler application——Campus web search engine part-one)(上)

     

    看了《Python项目案例开发从入门到实战》(清华大学出版社  郑秋生 夏敏捷主编)中爬虫应用——校园网搜索引擎,这一章节涉及到的内容有:

    • 数据库的基本使用
    • 正则表达式
    • 中文分词

    我详细注释了其中关于校园网搜索引擎的代码,分享给大家:

      1 import sys
      2 from collections import deque
      3 import urllib
      4 from urllib import request
      5 import re
      6 from bs4 import BeautifulSoup
      7 import lxml
      8 import sqlite3
      9 import jieba
     10 
     11 # 要先定义爬虫抓取的第一个网址,这里是是华侨大学的主页
     12 url = 'https://www.hqu.edu.cn/index.htm'
     13 
     14 # 待爬取链接的集合,使用广度优先搜索
     15 unvisited = deque()
     16 
     17 # 已访问的链接集合
     18 visited = set()
     19 
     20 unvisited.append(url)
     21 
     22 # 建立数据库连接,没有则创建数据库
     23 conn = sqlite3.connect('viewsdu.db')
     24 # 创建游标对象
     25 c = conn.cursor()
     26 # 在 create table 之前先 drop table 是因为如果你的数据库中已经存在了名叫doc的浏览器了,那么就要再次运行把存在的的doc浏览器删除重建
     27 # !!!!如果之前不存在名叫doc的浏览器,那么这一句话要注释掉
     28 c.execute('drop table doc')
     29 # 创建名叫doc的数据库,包含两个变量,一个是int型的id,一个是text型的link
     30 c.execute('create table doc(id int primary key, link text)')
     31 # !!!!如果之前不存在名叫word的浏览器,那么这一句话要注释掉
     32 c.execute('drop table word')
     33 # 创建名叫word的数据库,包含连个变量,一个是varchar(25)型的term,一个是text类型的list
     34 c.execute('create table word(term varchar(25) primary key, list text)')
     35 # 提交数据库
     36 conn.commit()
     37 # 关闭数据库
     38 conn.close()
     39 
     40 print('************************** 开始爬取 ****************************')
     41 
     42 cnt = 0
     43 print('开始..........')
     44 # 当还存在带爬取的网页的时候就一直执行循环
     45 while unvisited:
     46     # 抛出第一个数
     47     url = unvisited.popleft()
     48     # 已经访问的链接集合添加当前访问链接
     49     visited.add(url)
     50     cnt += 1
     51     print('开始抓取第', cnt, '个链接: ', url)
     52 
     53     # 爬取网页内容
     54     try:
     55         # 打开网页
     56         response = request.urlopen(url)
     57         # 读取网页内容并使用 utf-8 进行解码
     58         content = response.read().decode('utf-8')
     59     except:
     60         continue
     61 
     62     # 寻找下一个可爬的链接,因为搜索范围是网站内,所以对链接有格式要求,需根据具体情况而定
     63     # 解析网页内容,可能有集中情况,这也是根据这个网站网页的具体情况写的
     64     soup = BeautifulSoup(content, 'lxml')
     65     # print(soup.prettify())
     66     # 找到所有的 target='_blank' 的链接,注意这个要根据爬取的内容进行修改
     67     all_a = soup.find_all('a', {'target': '_blank'})
     68     for a in all_a:
     69         # print(a.attrs['href'])
     70         # 得到href的值
     71         x = a.attrs['href']
     72         # 排除开头是http,但不是https://www.hqu.edu.cn
     73         if re.match(r'http.+', x):
     74             if not re.match(r'http://www.hqu.edu.cn/.+', x):
     75                 continue
     76         # "/info/1046/20314.htm"
     77         if re.match(r'/info/.+', x):
     78             x = 'http://www.hqu.edu.cn' + x
     79         # "info/1046/20314.htm"
     80         elif re.match(r'info/.+', x):
     81             x = 'http://www.hqu.edu.cn/' + x
     82         # "../info/1046/20314.htm"
     83         elif re.match(r'../info/.+', x):
     84             x = 'http://www.hqu.edu.cn' + x[2:]
     85         # "../../info/1046/20314.htm"
     86         elif re.match(r'../../info/.+', x):
     87             x = 'http://www.hqu.edu.cn' + x[5:]
     88         if (x not in visited) and (x not in unvisited):
     89             print(x)
     90             unvisited.append(x)
     91     # 下一页<a>
     92     a = soup.find('a', {'class': 'Next'})
     93     if a is not None:
     94         x = a.attrs['href']
     95         if re.match(r'xwdt/.+', x):
     96             x = 'http://www.hqu.edu.cn/index/' + x
     97         else:
     98             x = 'http://www.hqu.edu.cn/index/xwdt' + x
     99         if (x not in visited) and (x not in unvisited):
    100             unvisited.append(x)
    101 
    102     # ************************* 解析网页内容 ************************* #
    103     # 得到网页标题
    104     title = soup.title
    105     # 得到网页内容,注意这个要根据爬取的内容进行修改
    106     article = soup.find('div', class_='v_news_content')
    107     # 或者使用这个也可以
    108     # article = soup.find('div', id='vsb_content')
    109     # 作者,注意这个要根据爬取的内容进行修改
    110     author = soup.find('span', class_='arti_publisher')
    111     # 发布时间,注意这个要根据爬取的内容进行修改
    112     time = soup.find('span', class_='arti_update')
    113     # print('title : 
    ', title)
    114     # print('article : 
    ', article)
    115     # print('author : 
    ', author)
    116     # print('time : 
    ', time)
    117 
    118     if title is None and article is None and author is None:
    119         print('无内容的页面。')
    120         continue
    121 
    122     elif article is None and author is None:
    123         print('只有标题。')
    124         title = title.text
    125         title = ''.join(title.split())
    126         article = ''
    127         author = ''
    128 
    129     elif article is None:
    130         print('有标题有作者,缺失内容')
    131         title = title.text
    132         title = ''.join(title.split())
    133         article = ''
    134         author = author.get_text("", strip=True)
    135         author = ''.join(author.split())
    136 
    137     elif author is None:
    138         print('有标题有内容,缺失作者')
    139         title = title.text
    140         title = ''.join(title.split())
    141         article = article.get_text("", strip=True)
    142         article = ''.join(article.split())
    143         author = ''
    144     else:
    145         # 得到标签中文字内容
    146         title = title.text
    147         # 去除空格
    148         title = ''.join(title.split())
    149         # 得到变迁中文字内容,strip=True表示去除空白行
    150         article = article.get_text("", strip=True)
    151         article = ''.join(article.split())
    152         author = author.get_text("", strip=True)
    153         author = ''.join(author.split())
    154         
    155     print('网页标题:', title)
    156 
    157     # 对title,article,author内容的词进行结巴分词,使用的是搜索引擎模式的cut_for_search
    158     seglist = []
    159     for i in [title, article, author]:
    160         seggen = jieba.cut_for_search(i)
    161         seglist.extend(seggen)
    162 
    163     # 数据传输
    164     conn = sqlite3.connect("viewsdu.db")
    165     c = conn.cursor()
    166     # 在名为doc的数据库中插入行的一行
    167     c.execute('insert into doc values (?,?)', (cnt, url))
    168     # 对每个分出的词语建立倒排词表
    169     for word in seglist:
    170         # 检验看看这个词语是否已存在于数据库
    171         c.execute('select list from word where term=?', (word,))
    172         result = c.fetchall()
    173         # 如果不存在
    174         if len(result) == 0:
    175             docliststr = str(cnt)
    176             # 在word数据库中插入新的行值
    177             c.execute('insert into word values (?, ?)', (word, docliststr))
    178         # 如果已存在
    179         else:
    180             # 提取当前结果返回的内容,返回的就是如 ‘19 19’
    181             docliststr = result[0][0]
    182             # 加上新得到的内容,返回的内容如 ‘19 19 20’
    183             docliststr += ' ' + str(cnt)
    184             # 更新word数据库中term对应的值
    185             c.execute('update word set list=? where term=?', (docliststr, word))
    186     conn.commit()
    187     conn.close()
    188 print('词表建立完毕!!!')

     

    这里需要注意:关于前端网页中定义的那些搜索词,比如:{'target': '_blank'}, class_='v_news_content', class_='arti_publisher', class_='arti_update' 这些内容都是根据爬取的网页具体情况决定,要学会灵活变通。我这些名字来源主要因为如下:

    class_='arti_update' 来源:

    class_='v_news_content' 来源:

     

    class_='arti_publisher'来源:

     

    类似这样得到这些值。

    最终的结果是返回得到一个词表数据库,如下图所示:

    viewsdu.db 数据库:

    doc 浏览器:

    word 浏览器:

  • 相关阅读:
    Golang初学者的资源整理
    Mesos和kubernetes
    Go by Example
    dbus 和 policykit 实例篇(python) ()转
    CentOS7卸载KDE桌面(转)
    Please read “Security” section of the manual to find out how to run mysqld as root!错误解决(转)
    yum使用总结(转)
    Linux rpm 命令参数使用详解[介绍和应用](转)
    nginx+lua+redis高并发应用建设
    python网络爬虫进入(一)——简单的博客爬行动物
  • 原文地址:https://www.cnblogs.com/ttweixiao-IT-program/p/13324826.html
Copyright © 2011-2022 走看看