Python用正則表達(dá)式實(shí)現(xiàn)爬取古詩文網(wǎng)站信息
分析古詩文網(wǎng)站
下圖1展示了古詩文網(wǎng)站—》詩文 欄目的首頁數(shù)據(jù)。該欄目的地址是:https://so.gushiwen.cn/shiwens/
第二頁的地址是:https://so.gushiwen.cn/shiwens/default.aspx?page=2&tstr=&astr=&cstr=&xstr= 。依次類推第n頁的地址就是page=n。其他不變。
1. 用正則表達(dá)式獲取總頁數(shù)
匹配的正則表達(dá)式是r'<div class="pagesright">.*?<span .*?>(.*?)</span>'
- 首先,r修飾的字符串是原生字符串,首先匹配到<div class="pagesright"> 標(biāo)簽,然后再通過.*?匹配到里面的里面的<a>標(biāo)簽<span>標(biāo)簽等。這里. 可以匹配到任意的一個字符(換行符除外),* 號可以匹配0或者任意多個字符。? 號表示只能匹配到1個或者0個。這里加上?號是為了使用非貪婪模式。
- <span .*?> 通過匹配到存放總頁數(shù)的<span>標(biāo)簽。在標(biāo)簽里指定.*?
- (.*?) 加上() 可以指定不同的分組,這里我們只需要獲取頁數(shù)所以就單獨(dú)添加一個分組。
所以,最終的代碼是:
def get_total_pages(): resp = requests.get(first_url) # 獲取總頁數(shù) ret = re.findall(r'<div class="pagesright">.*?<span .*?>(.*?)</span>', resp.text, re.DOTALL) result = re.search('\d+', ret[0]) for page_num in range(int(result.group())): url = 'https://so.gushiwen.cn/shiwens/default.aspx?page=' + str(page_num) parse_page(url)
在findall方法中傳入re.DOTALL參數(shù)是為了是. 號可以匹配到換行符\n。
前面ret的結(jié)果是/ 5頁。再獲取5這個數(shù)字的話,還需要做一次匹配查找,這就是通過re.search('\d+', ret[0]) 來進(jìn)行查找。
2. 提取詩的標(biāo)題
如上圖2展示了詩的標(biāo)題的HTML源碼,從中可以看出詩的標(biāo)題被存在<b>標(biāo)簽 匹配詩的標(biāo)題的正則表達(dá)式是<div class="cont">.*?<b>(.*?)</b>
首先還是匹配到<div class="cont"> 標(biāo)簽,接著就是匹配<b>(.*?)</b> 這里還是采用非貪婪模式來進(jìn)行匹配。
3. 提取作者和朝代
如上圖3展示了詩的作者和朝代的HTML源碼,從中可以看出作者和朝代都是在<p class="source"></p> 標(biāo)簽下的兩個a標(biāo)簽中。
3.1 提取作者
提取作者的正則表達(dá)式是<p class="source">.*?<a .*?>(.*?)</a> 首先還是匹配到<p class="source"> 標(biāo)簽。接著就是匹配第一個<a> 標(biāo)簽中的內(nèi)容。
3.2 提取朝代
提取朝代的正則表達(dá)式是<p class="source">.*?<a .*?><a .*?>(.*?)</a> 與提取作者不同的是多了一個<a .*?> ,這是因?yàn)槌诘诙€<a>標(biāo)簽中。
4. 提取詩的內(nèi)容
如上圖4展示了詩的內(nèi)容的HTML源碼,從中可以看出詩句都在<div class="contson">標(biāo)簽中,所以只需要匹配到這個標(biāo)簽里的內(nèi)容即可。其正則表達(dá)式是<div class="contson" .*?>(.*?)</div>。
但是這樣匹配出來的數(shù)據(jù)是包含<br> 標(biāo)簽的。所以,我們需要通過sub 方法將這個標(biāo)簽替換掉。re.sub(r'<.*?>+', "", content)。
整理代碼
至此,我們就將所有想要的數(shù)據(jù)都提取到了。接下來,我們還需要對數(shù)據(jù)進(jìn)行處理。我們期望的最終數(shù)據(jù)格式是:
poems=[ { "title": '漁家傲·花底忽聞敲兩槳', "author":'張三', 'dynasty':'唐朝', 'content':'xxxxxx' } { "title": '鵝鵝鵝', "author":'李四', 'dynasty':'唐朝', 'content':'xxxxxx' } ]
前面,我們分別得到了所有標(biāo)題的列表titles;所有作者的列表authors;所有朝代的列表dynastys;所有詩句的列表contents。
那么,我們?nèi)绾螌⑦@些列表組合成上面的那種形式呢?
這里,就需要用到 zip 函數(shù)了。該函數(shù)可以將多個列表組合成一個新的列表,其中列表的元素是元組。比如:
a=['name','age'] b=['張三',18] c=zip(a,b)
調(diào)用zip 方法之后得到一個zip對象,該對象可以轉(zhuǎn)換成list 對象。最終得到的結(jié)果如下圖5
完整源代碼
# -*- utf-8 -*- """ @url: https://blog.csdn.net/u014534808 @Author: 碼農(nóng)飛哥 @File: gushiwen_rep.py @Time: 2021/12/7 07:40 @Desc: 用正則表達(dá)式爬取古詩文網(wǎng)站 古詩文網(wǎng)站的地址: https://www.gushiwen.cn/ """ import re import requests headers = { 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36' } first_url = 'https://so.gushiwen.cn/shiwens/default.aspx' def get_total_pages(): resp = requests.get(first_url) # 獲取總頁數(shù) ret = re.findall(r'<div class="pagesright">.*?<span .*?>(.*?)</span>', resp.text, re.DOTALL) result = re.search('\d+', ret[0]) for page_num in range(int(result.group())): url = 'https://so.gushiwen.cn/shiwens/default.aspx?page=' + str(page_num) parse_page(url) # 解析頁面 def parse_page(url): resp = requests.get(url) text = resp.text # 提取標(biāo)題 (.*) 進(jìn)行分組,只提取<b>標(biāo)簽中的內(nèi)容,默認(rèn)情況下 .不能匹配\n。加上re.DOTALL 表示.號可以匹配所有,貪婪模式 # titles = re.findall(r'<div class="cont">.*<b>(.*)</b>', text,re.DOTALL) # 非貪婪模式 titles = re.findall(r'<div class="cont">.*?<b>(.*?)</b>', text, re.DOTALL) # 提取作者 authors = re.findall(r'<p class="source">.*?<a .*?>(.*?)</a>', text, re.DOTALL) # 提取朝代 dynastys = re.findall(r'<p class="source">.*?<a .*?><a .*?>(.*?)</a>', text, re.DOTALL) # 提取詩句 content_tags = re.findall(r'<div class="contson" .*?>(.*?)</div>', text, re.DOTALL) contents = [] for content in content_tags: content = re.sub(r'<.*?>+', "", content) contents.append(content) poems = [] for value in zip(titles, authors, dynastys, contents): # 解包 title, author, dynasty, content = value poems.append( { "title": title, "author": author, 'dynasty': dynasty, 'content': content } ) print(poems) """ poems=[ { "title": '漁家傲·花底忽聞敲兩槳', "author":'張三', 'dynasty':'唐朝', 'content':'xxxxxx' } { "title": '漁家傲·花底忽聞敲兩槳', "author":'張三', 'dynasty':'唐朝', 'content':'xxxxxx' } ] """ """ zip 函數(shù) a=['name','age'] b=['張三',18] c=zip(a,b) c=[ ('name','張三'), ('age',18) ] """ if __name__ == '__main__': get_total_pages()
最終的運(yùn)行結(jié)果是:
總結(jié)
本文以古詩文網(wǎng)為例演示了如何通過正則表達(dá)式來爬取網(wǎng)站數(shù)據(jù)。?
以上就是Python用正則表達(dá)式實(shí)現(xiàn)爬取古詩文網(wǎng)站信息的詳細(xì)內(nèi)容,更多關(guān)于Python正則表達(dá)式爬取網(wǎng)站信息的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
通過Python實(shí)現(xiàn)Payload分離免殺過程詳解
這篇文章主要介紹了通過Python實(shí)現(xiàn)Payload分離免殺過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07使用Pandas實(shí)現(xiàn)MySQL窗口函數(shù)的解決方法
本文主要介紹 MySQL 中的窗口函數(shù)row_number()、lead()/lag()、rank()/dense_rank()、first_value()、count()、sum()如何使用pandas實(shí)現(xiàn),同時二者又有什么區(qū)別,感興趣的朋友一起看看吧2023-02-02Pandas數(shù)據(jù)分析-pandas數(shù)據(jù)框的多層索引
這篇文章主要介紹了Pandas數(shù)據(jù)分析-pandas數(shù)據(jù)框的多層索引,pandas數(shù)據(jù)框針對高維數(shù)據(jù),也有多層索引的辦法去應(yīng)對具體詳細(xì)的內(nèi)容介紹需要的小伙伴可以參考一下2022-08-08python 讀取excel文件生成sql文件實(shí)例詳解
這篇文章主要介紹了python 讀取excel文件生成sql文件實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05Python基礎(chǔ)學(xué)習(xí)之類與實(shí)例基本用法與注意事項(xiàng)詳解
這篇文章主要介紹了Python基礎(chǔ)學(xué)習(xí)之類與實(shí)例基本用法與注意事項(xiàng),結(jié)合實(shí)例形式詳細(xì)分析了Python面相對象程序設(shè)計中關(guān)于類的定義與實(shí)例化對象相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-06-06解決pycharm下os.system執(zhí)行命令返回有中文亂碼的問題
今天小編就為大家分享一篇解決pycharm下os.system執(zhí)行命令返回有中文亂碼的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07python讓圖片按照exif信息里的創(chuàng)建時間進(jìn)行排序的方法
這篇文章主要介紹了python讓圖片按照exif信息里的創(chuàng)建時間進(jìn)行排序的方法,涉及Python操作圖片exif獲取信息的技巧,需要的朋友可以參考下2015-03-03python如何通過twisted搭建socket服務(wù)
這篇文章主要介紹了python如何通過twisted搭建socket服務(wù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-02-02