在知乎上看過很多爬蟲相關,一直沒有動手,現在開始get my hand dirty.
本篇在學習知乎大神xzld的Web crawler with Python - 03.豆瓣電影TOP250基礎上,簡單爬取了糗百上的笑話。
結果.png
任務目標
利用python爬取糗事百科上的笑話。
任務理解
在做任何爬蟲之前,我們首先需要了解一下想要爬取的對象
- 打開:用火狐瀏覽器打開糗事百科,打開開發者工具(F12)
- 查看 :選中任意一條笑話,鼠標右鍵后點擊查看,我們就可以看到該條笑話在HTML中位于的位置
- 觀察 :仔細觀察其標簽,因為之后我們將根據其標簽來定位。
通過觀察我們發現,笑話內容位于<div class=content>的<span>標簽下。
那么我們的任務即轉變為:
在糗事百科的HTML中找到<.div class=content>的<span>標簽的文本內容。
因此,我們將任務即可分為三部分:
- 下載:將糗事百科頁面的HTML內容下載下來,這部分我們將使用requests包
- 解析:根據標簽查找到文本內容并存儲,這部分使用BeautifulSoup包。
- 輸出:將文本內容格式化輸出,這部分我們將使用codecs包。
任務進行
環境準備
import warnings
warnings.filterwarnings('ignore')
import requests
from bs4 import BeautifulSoup
import codecs
引入requests,BeautifulSoup,codecs及warnings包。warnings包主要用來忽略編碼過程中的警告提示,我常喜歡把它寫在編碼前
下載頁面
我們使用requests中的get方法來獲取頁面,
URL="https://www.qiushibaike.com/"
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0'}
html=requests.get(URL,headers=header).content
簡單介紹代碼內容
- 第一行代碼指定網頁
- 第二行代碼指定請求頭User-Agent(表示瀏覽器類型),用來將爬蟲偽裝成瀏覽器。
- 第三行利用requests.get().content 獲取指定網頁源代碼。
注意reuqests.get(URL,headers=header)
中headers不能省略
一般,瀏覽器在向服務器發送請求的時候,會有一個請求頭——User-Agent,它用來標識瀏覽器的類型.當我們使用requests來發送請求的時候,默認的User-Agent是python-requests/2.8.1(后面的數字可能不同,表示版本號),通常我們需要要將User-Agent偽裝成瀏覽器的,來解決某些網頁反爬蟲的問題。這是一種簡單的反爬蟲機制
解析頁面
通過上部我們的得到網頁源代碼,但是看起來非常的亂,毫無頭緒,就像一鍋東北亂燉。然后通過BeautifulSoup,包如其名,總能把亂糟糟的菜熬成很漂亮的一鍋湯,讓你很方便的找到需要的內容。
- 熬湯:通過BeautifulSoup命令間html內容轉換為beautifulsoup格式
soup=BeautifulSoup(html)
如上圖,BeautifulSoup將源代碼很好的處理為了標簽加內容的格式,非常利于我們來查找內容。
- 找菜:湯熬好,就可以根據我們給出的標簽來找菜了
joks=soup.find_all('div',attrs={'class':'content'})
jok_list=[]
for joks in jokss:
jok=joks.find('span').getText()
jok_list.append(jok)
- 第一行利用find_all找到所有標簽為<div class=content>內容
圖片.png - 第二行創建一個空列表jok_list,用來存儲之后找到的笑話
- 第三行建立一個循環,利用find依次查找每一個<div class=content>中的<span>標簽并獲取其中的文本內容,利用append函數存儲到jok_list中
- 加菜:當然我們注意到,糗百涉及到翻頁。我們還需要解決翻頁的問題,這個問題最簡單的方法就是找到下一頁的鏈接,再重復之前的步驟即可。
next_page=soup.find('ul',{'class':'pagination'}).find_all('a')[-1]['href']
next_page=URL[:-1]+next_page
點擊下一頁,查看元素。我們發現下一頁的鏈接再<ul,class=pagination>的最后一個標簽<'a'>下。因為使用find只能返回匹配的第一個對象,因此這里我們使用find_all找到所有匹配對象的列表。再通過soup.find('ul',{'class':'pagination'}).find_all('a')[-1]定位到最后一個對象,即包含下一頁信息的對象.
注意
以第一頁為例得到的結果為* '/8hr/page/2/' ,需要與 URL='https://www.qiushibaike.com/'拼接。但是如果直接連在一起得到結果為
'https://www.qiushibaike.com//8hr/page/2’多了一條‘/’因此,使用URL[-1]+next_page才能得到正確的鏈接。 'https://www.qiushibaike.com/8hr/page/2’ *
存儲
codecs.open('joks','wb',encoding='utf-8') as fp:
fp.write(u'{jok_list}\n'.format(jok_list='\n'.join(jok_llist)))
任務總結
import requests
from bs4 import BeautifulSoup
import warnings
import codecs
warnings.filterwarnings('ignore')
def download_page(url):
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0'}
html=requests.get(URL,headers=header).content
return html
def parsel_html(html):
soup=BeautifulSoup(html)
joks=soup.find_all('div',{'class':'content'})
jok_list=[]
for joks in jokss:
jok=joks.find('span').getText()
jok_list.append(jok)
next_page=soup.find('ul',{'class':'pagination'}).find_all('a')[-1]['href']
if next_page:
return jok_list,URL[:-1]+next_page
return jok_list,None
def main():
URL="https://www.qiushibaike.com/"
with codecs.open('joks','wb',encoding='utf-8') as fp:
while URL:
HTML=download_page(URL)
JOK,URL=parsel_html(HTML)
fp.write(u'{JOK}\n'.format(JOK='\n'.join(JOK)))
if __name__ == '__main__':
main()