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 : \n', title)
114     # print('article : \n', article)
115     # print('author : \n', author)
116     # print('time : \n', 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 瀏覽器:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM