什么是爬蟲
網絡爬蟲,也叫網絡蜘蛛(spider),是一種用來自動瀏覽萬維網的網絡機器人。其目的一般為編纂網絡索引。
網絡搜索引擎等站點通過爬蟲軟件更新自身的網站內容或其對其他網站的索引。網絡爬蟲可以將自己所訪問的頁面保存下來,以便搜索引擎事后生成索引供用戶搜索。
爬蟲訪問網站的過程會消耗目標系統資源。不少網絡系統並不默許爬蟲工作。因此在訪問大量頁面時,爬蟲需要考慮到規划、負載,還需要講“禮貌”。 不願意被爬蟲訪問、被爬蟲主人知曉的公開站點可以使用robots.txt文件之類的方法避免訪問。這個文件可以要求機器人只對網站的一部分進行索引,或完全不作處理。
互聯網上的頁面極多,即使是最大的爬蟲系統也無法做出完整的索引。因此在公元2000年之前的萬維網出現初期,搜索引擎經常找不到多少相關結果。現在的搜索引擎在這方面已經進步很多,能夠即刻給出高質量結果。
爬蟲還可以驗證超鏈接和HTML代碼,用於網絡抓取。
環境:pycharm2017、python3.7
對於初學者來說,爬取小說是最簡單的應用,而對於沒有任何語法基礎的人來說,清晰的邏輯往往比大段的代碼更重要。
整個過程分為以下幾步:
1.確定爬取目標(網頁,前段頁面)
首先要明確爬蟲的原理,是從網頁源代碼進行進行數據爬取,本次是以http://www.92kshu.cc/69509/為例,進行小說爬取
2.分析代碼,進行數據爬取
主要用到的是python的正則表達式,對想要爬取數據進行選擇
title = re.findall(r'<meta property="og:novel:book_name" content="(.*?)"/>',html)[0]
在此語句中,用的是re庫,對字符進行篩選,從網頁代碼中找到獨一無二的標志代碼段,進行篩選,如果一次不能直接篩選,則可進行多重,比如實例中,先爬取html,然后爬取dl,只是為了爬取對應章節的地址和每一章節的標題。
用re.findall(r'')進行匹配,需匹配的位置用(.*?)代替.
正則表達式表
模式 | 描述 |
---|---|
^ | 匹配字符串的開頭 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字符。 |
[...] | 用來表示一組字符,單獨列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0個或多個的表達式。 |
re+ | 匹配1個或多個的表達式。 |
re? | 匹配0個或1個由前面的正則表達式定義的片段,非貪婪方式 |
re{ n} | 精確匹配 n 個前面表達式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的兩個 o。 |
re{ n,} | 匹配 n 個前面表達式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。"o{1,}" 等價於 "o+"。"o{0,}" 則等價於 "o*"。 |
re{ n, m} | 匹配 n 到 m 次由前面的正則表達式定義的片段,貪婪方式 |
a| b | 匹配a或b |
(re) | 對正則表達式分組並記住匹配的文本 |
(?imx) | 正則表達式包含三種可選標志:i, m, 或 x 。只影響括號中的區域。 |
(?-imx) | 正則表達式關閉 i, m, 或 x 可選標志。只影響括號中的區域。 |
(?: re) | 類似 (...), 但是不表示一個組 |
(?imx: re) | 在括號中使用i, m, 或 x 可選標志 |
(?-imx: re) | 在括號中不使用i, m, 或 x 可選標志 |
(?#...) | 注釋. |
(?= re) | 前向肯定界定符。如果所含正則表達式,以 ... 表示,在當前位置成功匹配時成功,否則失敗。但一旦所含表達式已經嘗試,匹配引擎根本沒有提高;模式的剩余部分還要嘗試界定符的右邊。 |
(?! re) | 前向否定界定符。與肯定界定符相反;當所含表達式不能在字符串當前位置匹配時成功 |
(?> re) | 匹配的獨立模式,省去回溯。 |
\w | 匹配字母數字及下划線 |
\W | 匹配非字母數字及下划線 |
\s | 匹配任意空白字符,等價於 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意數字,等價於 [0-9]. |
\D | 匹配任意非數字 |
\A | 匹配字符串開始 |
\Z | 匹配字符串結束,如果是存在換行,只匹配到換行前的結束字符串。 |
\z | 匹配字符串結束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等. | 匹配一個換行符。匹配一個制表符。等 |
\1...\9 | 匹配第n個分組的內容。 |
\10 | 匹配第n個分組的內容,如果它經匹配。否則指的是八進制字符碼的表達式。 |
3.清洗(用python進行清洗)
replace('a','b'),用b替換a,進行初步清洗,也可以用MapReduce進行清洗。
4.存入文件
fb = open('%s.txt' % title,'w',encoding='utf-8')
建立文件,並且該文件為寫入狀態,其中%s是占位符,也就是用% title 進行替換
chapter_url = "http://www.92kshu.cc%s" %chapter_url
這段代碼為連接字符串,與+相比,%s能夠節省內存
fb.write(String)就是來寫入文件的語句
源代碼:
1 #down web pages 2 3 import requests 4 import re 5 6 url = 'http://www.92kshu.cc/69509/' 7 response = requests.get(url) 8 response.encoding = 'gbk' 9 html = response.text 10 title = re.findall(r'<meta property="og:novel:book_name" content="(.*?)"/>',html)[0] 11 fb = open('%s.txt' % title,'w',encoding='utf-8') 12 #獲取每章的內容 13 #print(html) 14 dl = re.findall(r'<dl><dt><i class="icon"></i>正文</dt>(.*?)</dl>',html)[0] 15 print(dl) 16 chapter_info_list = re.findall(r'<dd><a href="(.*?)">(.*?)</a></dd>',dl) 17 #print(chapter_info_list) 18 for chapter_info in chapter_info_list: 19 chapter_url,chapter_title = chapter_info 20 chapter_url = "http://www.92kshu.cc%s" %chapter_url 21 #print(chapter_url) 22 chapter_response = requests.get(chapter_url) 23 chapter_response.encoding = 'gbk' 24 chapter_html = chapter_response.text 25 chapter_content = re.findall(r'<div class="chapter">(.*?)><br>',chapter_html)[0] 26 #print(chapter_content) 27 chapter_content = chapter_content.replace('<p>','') 28 chapter_content = chapter_content.replace('</p>','') 29 fb.write(chapter_title) 30 fb.write(chapter_content) 31 fb.write('\n') 32 print(chapter_url)