案例要爬取的網站是:http://www.quanshuwang.com/book/44/44683
步驟:
1、獲取小說主頁源代碼
2、在主頁源代碼中找到每個章節的超鏈接
3、獲取每個章節超鏈接的源代碼
4、獲取章節的內容
5、保存內容到本地
首先導入模板
import re import urllib.request
然后定義一個函數,專門用來爬取網站小說的
import re import urllib.request #定義一個爬取網絡小說的函數 def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read()
最后一行我們調用了urllib庫的方法,urlopen方法中我們傳進一個網址作為參數表示我們需要爬取的網站,.read()方法表示獲取源代碼。那我們現在打印html是否能成功在控制台把頁面的代碼給輸出了呢?答案是否定的,現在獲取的源碼是一個亂碼,我們還需要對該代碼進行轉碼,於是要在下面加多一行轉碼的。
import re import urllib.request #定義一個爬取網絡小說的函數 def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式
由上面我們可知代碼已經轉成了‘gbk’格式,並且也已經將它存在html這個變量上了,那我們怎么知道轉成什么格式呢?
前面我說過我要爬取的網站是:http://www.quanshuwang.com/book/44/44683
我建議小伙伴們在獲取該網頁源代碼的時候先在瀏覽器中查看分析一下該網頁源代碼的大概結構,分析清楚了好方便后面代碼的編寫。查看頁面源代碼有兩種方式,1:按住F12。2:鼠標指向頁面空白處點擊右鍵,選擇“查看頁面源代碼”。
我們先用第二種方法打開源代碼找到<meta>標簽便可知道該網站的格式了
接下來我另一種方式打開源代碼,按F12
鼠標點擊左上角的箭頭,再把鼠標指向網頁中的任何一部分內容,查看器馬上就能定位到該內容的源代碼位置。
因為我們要獲取整本小說,所以讓我們先獲取章節目錄吧,把鼠標指向其中一章並選中,下面就自動定位到該章節標簽位置了
我們對這行右擊鼠標->編輯HTML,然后把這一行都復制下來
回到編輯器這邊把剛才的代碼粘貼過來並打上注釋,作為一個參考的模板
def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式 #<li><a href="http://www.quanshuwang.com/book/44/44683/15379609.html" title="引子 穿越的唐家三少,共2744字">引子 穿越的唐家三少</a></li> #參考
因為我們需要抓取的是全部章節而不僅僅只是這一個章節,所以我們要用到正則表達式來進行匹配,先把通用的部分用(.*?)替代,(.*?)可以匹配所有東西
#定義一個爬取網絡小說的函數 def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式 #<li><a href="http://www.quanshuwang.com/book/44/44683/15379609.html" title="引子 穿越的唐家三少,共2744字">引子 穿越的唐家三少</a></li> #參考 reg = r'<li><a href="(.*?)" title=".*?">(.*?)</a></li>' #正則表達的匹配 reg = re.compile(reg) #可添加可不添加,增加效率 urls = re.findall(reg,html)
print(urls)
get_novel()
仔細的小伙伴就發現有些地方的.*?加括號,有些地方又不加,這是因為加了括號的都是我們要匹配的,不加括號是我們不需要匹配的。接下來一行調用re.compiled()方法是增加匹配的效率,建議習慣加上,最后一行開始與我們一開始獲取的整個網頁的源代碼進行匹配。到這步我們已經能把代碼所有章節以及章節鏈接的代碼都獲取了,打印在控制台上看一下
從結果我們可以知道對於每個循環出來的結果為一個元祖,有兩個索引,0和1,0為章節的超鏈接,1為章節的名字。
既然我們獲取到了每個章節的超鏈接那我們是不是就可以像上面的操作步驟一樣獲取這個鏈接里面的內容啦?答案是肯定的。
於是我們繼續寫以下的代碼獲取每個章節的代碼(跟上面獲取主頁代碼的步驟類似)
#定義一個爬取網絡小說的函數 def getNovelContent(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式 #<li><a href="http://www.quanshuwang.com/book/44/44683/15379609.html" title="引子 穿越的唐家三少,共2744字">引子 穿越的唐家三少</a></li> #參考 reg = r'<li><a href="(.*?)" title=".*?">(.*?)</a></li>' #正則表達的匹配 reg = re.compile(reg) #可添加可不添加,增加效率 urls = re.findall(reg,html) # print(urls) for url in urls: #print(url) chapter_url = url[0] #章節的超鏈接 chapter_title = url[1] #章節的名字 print(chapter_title) chapter_html = urllib.request.urlopen(chapter_url).read() #正文內容源代碼 chapter_html = chapter_html.decode("gbk")
get_novel()
至此我們已經可以得到每個章節的內容了,但是還有一個問題,就是我們只想獲取正文內容,正文以外的東西我們統統不要。
所以我們可以在網頁中打開其中一章並查看源代碼,例如我打開的是第一章,查找正文的內容在哪個標簽中。
上面兩張圖標識了我找到的正文內容開始與結束標簽的位置,標簽為<script>
於是我們在代碼中又可以通過正則表達式來匹配內容了
#定義一個爬取網絡小說的函數 def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式 #<li><a href="http://www.quanshuwang.com/book/44/44683/15379609.html" title="引子 穿越的唐家三少,共2744字">引子 穿越的唐家三少</a></li> #參考 reg = r'<li><a href="(.*?)" title=".*?">(.*?)</a></li>' #正則表達的匹配 reg = re.compile(reg) #可添加可不添加,增加效率 urls = re.findall(reg,html) # print(urls) for url in urls: chapter_url = url[0] #章節的超鏈接 chapter_title = url[1] #章節的名字 print(chapter_title) chapter_html = urllib.request.urlopen(chapter_url).read() #正文內容源代碼 chapter_html = chapter_html.decode("gbk") chapter_reg = r'</script> .*?<br />(.*?)<script type="text/javascript">' chapter_reg = re.compile(chapter_reg,re.S) chapter_content = re.findall(chapter_reg,chapter_html)
到這里我們已經完成了小說的全部爬取,在控制台打印一下吧
#定義一個爬取網絡小說的函數 def get_novel(): html = urllib.request.urlopen("http://www.quanshuwang.com/book/44/44683").read() html = html.decode("gbk") #轉成該網址的格式 #<li><a href="http://www.quanshuwang.com/book/44/44683/15379609.html" title="引子 穿越的唐家三少,共2744字">引子 穿越的唐家三少</a></li> #參考 reg = r'<li><a href="(.*?)" title=".*?">(.*?)</a></li>' #正則表達的匹配 reg = re.compile(reg) #可添加可不添加,增加效率 urls = re.findall(reg,html) # print(urls) for url in urls: chapter_url = url[0] #章節的超鏈接 chapter_title = url[1] #章節的名字 print(chapter_title) chapter_html = urllib.request.urlopen(chapter_url).read() #正文內容源代碼 chapter_html = chapter_html.decode("gbk") chapter_reg = r'</script> .*?<br />(.*?)<script type="text/javascript">' chapter_reg = re.compile(chapter_reg,re.S) chapter_content = re.findall(chapter_reg,chapter_html) for content in chapter_content: #打印章節的內容 content = content.replace("  ","") #把" "字符全都替換為"" content = content.replace("<br />","") #把"<br/>"字符全部替換為"" print(content) #打印內容
get_novel()
終於來到最后一步了,我們將爬取的內容保存。保存有兩種,一種是保存到本地,另一種是保存到數據庫中,本次案例我們保存到本地就行了。
import re import urllib.request import os def get_novle(): html = urllib.request.urlopen('http://www.quanshuwang.com/book/44/44683').read() # html = urllib.request.urlopen('http://www.xbiquge.la/7/7931/').read() html = html.decode('gbk') # <li><a href="http://www.quanshuwang.com/book/44/44683/15379610.html" title="第一章 斗羅大陸,異界唐三(一),共2112字">第一章 斗羅大陸,異界唐三(一)</a></li> reg = r'<li><a href="(.*?)" title=".*?">(.*?)</a></li>' reg = re.compile(reg) urls = re.findall(reg, html) # print(urls) for url in urls: # print(url) chapter_url = url[0] # print(chapter_url) chapter_title = url[1] # print(chapter_title) chapter_html = urllib.request.urlopen(chapter_url).read() chapter_html = chapter_html.decode('gbk') chapter_reg = r'</script> .*?<br />(.*?)<script type="text/javascript">' chapter_reg = re.compile(chapter_reg, re.S) chapter_content = re.findall(chapter_reg, chapter_html) # print(chapter_content) for content in chapter_content: content = content.replace(' ', '') content = content.replace('<br />', '') # print(content) base_path = '斗羅大陸' novel_path = os.path.join(base_path, chapter_title) with open(novel_path, 'w') as f: f.write(content) print('%s下載成功' % chapter_title) get_novle()
倒數第二行是我們保存文本的代碼,open第一個參數需要指定保存文本格式,第二個'w'意思是文件的模式為讀寫模式。更多文本處理操作可百度“python文本處理操作”,最后一行代碼為把章節的內容都寫進對應的每個章節中。