beautifulsoup find函数返回值_再端一碗BeautifulSoup
在上一章我們介紹了如何使用BeautifulSoup抓取安徒生童話故事《丑小鴨》,通過一個簡單的例子,大家應該對于python如何進行爬取網頁內容有了一個初步的認識。在這一章節,我們將延續上一章的內容進行網頁內容的爬取,不過我們將難度提高一點,不再只是抓取一個頁面,而是抓取很多個頁面的內容。
在這里,我們還是以安徒生的童話故事為例進行講解,不過今天的內容是抓取所有的安徒生童話故事。具體內容如下圖所示,鏈接為
安徒生童話故事大全,《安徒生童話》在線閱讀_皮皮少兒閱讀頻道?www.ppzuowen.com抓取一個單頁面很簡單,知道對應的url,然后在瀏覽器的開發者模式下查看需要的內容所在的標簽在哪里,然后定位抓取。那么對于多頁面的抓取如何進行呢?
思路本質上差不多:首先第一步是找到一個主頁面,然后通過主頁面與目標頁面的關聯跳轉到對應頁面。還記得我們的第一課給的那張爬蟲圖嗎?
圖中的每個節點相當一個頁面,節點間是通過蛛絲進行關聯的,這個蛛絲通常是一個超鏈接,即url。通常,如果要訪問整個蛛網有兩種思路:第一種是以一個節點為基準,訪問與它直連的所有的節點,然后再訪問直接的所有節點的所有直連節點,通過這種循環的方式進行訪問,我們稱之為廣度優先搜索;另一種是以一個節點為基準,訪問與它直連的某一個節點,然后再訪問這個直連節點的某一個直連節點,通過這種遞歸的方式進行訪問,我們稱之為深度優先搜索。
通過主頁面與目標頁面間的超鏈接,我們能夠爬取所有的目標內容。理論上,如果服務器的CPU和內存足夠大,我們可以爬取互聯網中所有的頁面數據。當然,實際中限于算力,我們一般會對爬取的內容進行裁剪,在本文中我們只爬取安徒生童話故事。
根據上面的分析,第二步我們需要做的就是找到所有主頁面和目標頁面之間的url,然后再對這些url進行再次訪問,就可以訪問每個頁面的內容,最后進行匯總,就能實現我們今天的預期目標。
很顯然,今天我們要采用的搜索方式是兩種中的廣度優先搜索。至于深度優先搜索,我們在后續的例子中進行詳細介紹。
在理清了思路之后,我們進行實際操作。
第一步,使用chrome在開發者模式下查看我們需要找的url在哪里。
通過分析HTML頁面,我們可以發現我們需要找尋的url在a標簽的href屬性中。并且通過進一步分析,發現我們需要找的url所在的a標簽都有同一個class屬性,這個class屬性值為“title”。
因此第一步定位目標,我們很容易就完成了。事實上,由于前端的開發工程師為了開發的簡便和顯示的統一,對于同類型的內容通常會使用同樣的標簽和css樣式。與此對應,對于我們的爬取也是非常簡便。
雖然我們能夠通過同一個class屬性找到我們的目標url,但是我們發現解析出來的url為“/book/antushengtonghua/178215.html”,而實際的url為“https://www.ppzuowen.com/book/antushengtonghua/178215.html”。
通過對比分析,我們發現只需要對解析出來的url在前面加一個域名“https://www.ppzuowen.com/”即可。字符串拼接對于我們來說再容易不過,剩下的就是把昨天的代碼補充在后面即可。
# 請求庫 import requests # 解析庫 from bs4 import BeautifulSoup# 爬取的網頁鏈接 prefix = r"https://www.ppzuowen.com/" url = r"https://www.ppzuowen.com/book/antushengtonghua/" r = requests.get(url) r.encoding = None result = r.text # 再次封裝,獲取具體標簽內的內容 bs = BeautifulSoup(result, 'html.parser') # 具體標簽 a = {} # 獲取已爬取內容中的script標簽內容 data = bs.find_all('a', {"class": "title"})# 循環打印輸出 for link in data:link = link.get('href')target_link = prefix + linkprint(target_link)由于昨天的代碼可以看作一個單獨的功能,因此我們可以把它定義為一個函數,方便后面調用。
def getStory(url):'''獲取每個童話故事內容:param url::return:'''r = requests.get(url)r.encoding = Noneresult = r.text# 再次封裝,獲取具體標簽內的內容bs = BeautifulSoup(result, 'html.parser')# 具體標簽print("---------解析后的數據---------------")a = {}# 獲取已爬取內容中的p簽內容data = bs.find_all('p')result = ''# 循環打印輸出for tmp in data:if '皮皮作文網' in tmp.text:breakresult += tmp.textreturn result根據以上思路,我們得到的代碼如下:
# 請求庫 import requests # 解析庫 from bs4 import BeautifulSoupdef getStory(url):'''獲取每個童話故事內容:param url::return:'''r = requests.get(url)r.encoding = Noneresult = r.text# 再次封裝,獲取具體標簽內的內容bs = BeautifulSoup(result, 'html.parser')# 具體標簽print("---------解析后的數據---------------")a = {}# 獲取已爬取內容中的p簽內容data = bs.find_all('p')result = ''# 循環打印輸出for tmp in data:if '皮皮作文網' in tmp.text:breakresult += tmp.textreturn result# 爬取的網頁鏈接 prefix = r"https://www.ppzuowen.com/" url = r"https://www.ppzuowen.com/book/antushengtonghua/" r = requests.get(url) r.encoding = None result = r.text # 再次封裝,獲取具體標簽內的內容 bs = BeautifulSoup(result, 'html.parser') # 具體標簽 a = {} # 獲取已爬取內容中的script標簽內容 data = bs.find_all('a', {"class": "title"})# 循環打印輸出 for link in data:link = link.get('href')target_link = prefix + link# print(target_link)result=getStory(target_link)print(result)由于打印的內容較多,在控制臺上顯得的很亂,不方便查看,在這里我們可以使用文件的存起來,文件的名字為童話故事的名字。
修改后的代碼如下:
# 請求庫 import requests # 解析庫 from bs4 import BeautifulSoupdef getStory(url):'''獲取每個童話故事內容:param url::return:'''r = requests.get(url)r.encoding = Noneresult = r.text# 再次封裝,獲取具體標簽內的內容bs = BeautifulSoup(result, 'html.parser')# 具體標簽print("---------解析后的數據---------------")a = {}# 獲取已爬取內容中的p簽內容title=bs.find_all('h2', {"class": "articleH2"})[0].textdata = bs.find_all('p')result = ''# 循環打印輸出for tmp in data:if '皮皮作文網' in tmp.text:breakresult += tmp.textreturn title,result# 爬取的網頁鏈接 prefix = r"https://www.ppzuowen.com/" url = r"https://www.ppzuowen.com/book/antushengtonghua/" r = requests.get(url) r.encoding = None result = r.text # 再次封裝,獲取具體標簽內的內容 bs = BeautifulSoup(result, 'html.parser') # 具體標簽 a = {} # 獲取已爬取內容中的script標簽內容 data = bs.find_all('a', {"class": "title"})# 循環打印輸出 for link in data:link = link.get('href')target_link = prefix + link# print(target_link)result=getStory(target_link)fd=open(result[0]+".txt",'w')fd.write(result[1])fd.close()由于爬取的數據過多,效率不高,我們可以使用多線程進行操作,進一步優化代碼性能。修改后的代碼如下:
# 請求庫 import requests # 解析庫 from bs4 import BeautifulSoup import threading from queue import Queue#定義一個線程安全隊列,用來保存數據 que=Queue()def getStory():'''獲取每個童話故事內容:param url::return:'''while not que.empty():url=que.get()r = requests.get(url)r.encoding = Noneresult = r.text# 再次封裝,獲取具體標簽內的內容bs = BeautifulSoup(result, 'html.parser')# 具體標簽print("---------解析后的數據---------------")a = {}# 獲取已爬取內容中的p簽內容title=bs.find_all('h2', {"class": "articleH2"})[0].textdata = bs.find_all('p')result = ''# 循環打印輸出for tmp in data:if '皮皮作文網' in tmp.text:breakresult += tmp.textwith open(title+".txt", 'w') as fo:fo.write(result)# 爬取的網頁鏈接 prefix = r"https://www.ppzuowen.com/" url = r"https://www.ppzuowen.com/book/antushengtonghua/" r = requests.get(url) r.encoding = None result = r.text # 再次封裝,獲取具體標簽內的內容 bs = BeautifulSoup(result, 'html.parser') # 具體標簽 a = {} # 獲取已爬取內容中的script標簽內容 data = bs.find_all('a', {"class": "title"})# 循環打印輸出 for link in data:link = link.get('href')target_link = prefix + linkque.put(target_link)print(target_link)# 定義多線程 for i in range(10):t = threading.Thread(target=getStory)t.start()t.join()以上我們講解了如何利用廣度優先搜索的方式爬取多個網頁信息。同時,為了提高爬取效率,我們采用多線程優化了代碼,并將結果存入到文件中,方便后期查看。
總結
以上是生活随笔為你收集整理的beautifulsoup find函数返回值_再端一碗BeautifulSoup的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 游戏爱好者的升级秘籍:FX8350处理器
- 下一篇: java 如何将word 转换为ftl_