整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          技術(shù)分享|利用Python和BeautifulSoup進行網(wǎng)頁爬取(新手教程)

          據(jù)觀世界

          在大數(shù)據(jù)、人工智能時代,我們通常需要從網(wǎng)站中收集我們所需的數(shù)據(jù),網(wǎng)絡(luò)信息的爬取技術(shù)已經(jīng)成為多個行業(yè)所需的技能之一。而Python則是目前數(shù)據(jù)科學(xué)項目中最常用的編程語言之一。使用Python與BeautifulSoup可以很容易的進行網(wǎng)頁爬取,通過網(wǎng)站爬蟲獲取信息可以幫助企業(yè)或個人節(jié)省很多的時間和金錢。學(xué)習(xí)本文之后,我相信大部分新手都能根據(jù)自己的需求來開發(fā)出相應(yīng)的網(wǎng)頁爬蟲。

          基礎(chǔ)條件

          • 了解簡單的Python編程規(guī)則(Python 3.x)
          • 了解簡單的網(wǎng)頁Html標(biāo)簽

          如果您是完全的新手也不用擔(dān)心,通過本文您可以很容易地理解。

          安裝所需包

          首先,您需要先安裝好Python 3.x,Python安裝包可以從python.org下載,然后我們需要安裝requests和beautifulsoup4兩個包,安裝代碼如下:

          $ pip install requests

          $ pip install beautifulsoup4

          爬取網(wǎng)頁數(shù)據(jù)

          現(xiàn)在我們已經(jīng)做好了一切準(zhǔn)備工作。在本教程中,我們將演示從沒被墻的維基百科英文版頁面中獲取歷屆美國總統(tǒng)名單。

          轉(zhuǎn)到此鏈接(https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States#Presidents)并右鍵單擊包含有關(guān)美國總統(tǒng)的所有信息的表格,然后單擊"檢查"選項(我用的是Chrome瀏覽器,其他瀏覽器右鍵單擊頁面后也會具有類似或相同的選項)。

          由下圖可知,表格的內(nèi)容位于class屬性為wikitable的table標(biāo)簽下,我們需要了解這些標(biāo)簽信息來獲取我們所需內(nèi)容。

          了解網(wǎng)頁信息之后,我們就可以編寫代碼了。首先,我們要導(dǎo)入我們安裝的包:

          import requests

          from bs4 import BeautifulSoup

          為了獲取網(wǎng)頁數(shù)據(jù)我們要使用requests的get()方法:

          url = "https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States"

          page = requests.get(url)

          檢查http響應(yīng)狀態(tài),來確保我們能正常獲取網(wǎng)頁,如果輸出狀態(tài)代碼為200則為正常:

          print(page.status_code)

          現(xiàn)在我們已經(jīng)獲取了網(wǎng)頁數(shù)據(jù),讓我們看看我們得到了什么:

          print(page.content)

          上面的代碼會顯示http相應(yīng)的全部內(nèi)容,包括html代碼和我們需要的文本數(shù)據(jù)信息。通過使用beautifulsoup的prettify()方法可以將其更美觀的展示出來:

          soup = BeautifulSoup(page.content, 'html.parser')

          print(soup.prettify())

          這會將數(shù)據(jù)按照我們上面"檢查"中看到的代碼形式展示出來:

          目前獲得的是包含我們所需數(shù)據(jù)的網(wǎng)頁源碼,我們接下來要將有用的信息提取出來。上面已經(jīng)知道我們所需的內(nèi)容在class屬性為wikitable的table標(biāo)簽下,因此,接下來我們將使用bs4對象的find方法提取table標(biāo)簽中的數(shù)據(jù),此方法返回bs4對象:

          tb = soup.find('table', class_='wikitable')

          table標(biāo)簽下有很多嵌套標(biāo)簽,通過網(wǎng)頁檢查中的代碼可以發(fā)現(xiàn),我們最終是需要獲得title元素中的文本數(shù)據(jù),而title元素位于a標(biāo)簽下,a標(biāo)簽位于b標(biāo)簽下,b標(biāo)簽位于table標(biāo)簽下。為了獲取所有我們所需的數(shù)據(jù),我們需要提取table標(biāo)簽下的所有b標(biāo)簽,然后找到b標(biāo)簽下的所有a標(biāo)簽,為此,我們使用find_all方法來迭代獲取所有b標(biāo)簽下的a標(biāo)簽:

          for link in tb.find_all('b'):

          name = link.find('a')

          print(name)

          這將獲取所有a標(biāo)簽下的數(shù)據(jù):

          可以看出,這并不是我們所要的最終結(jié)果,其中摻雜著html代碼,不用擔(dān)心,我們只需為上面的代碼添加get_text()方法,即可提取出所有a標(biāo)簽下title元素的文本信息,代碼改動如下:

          for link in tb.find_all('b'):

          name = link.find('a')

          print(name.get_text('title'))

          最終獲得所有總統(tǒng)的名單如下:

          George Washington

          John Adams

          Thomas Jefferson

          James Monroe

          ...

          ...

          Barack Obama

          Donald Trump

          將Python代碼合并在一起:

          import requests

          from bs4 import BeautifulSoup

          url = "https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States"

          page = requests.get(url)

          soup = BeautifulSoup(page.content, 'html.parser')

          tb = soup.find('table', class_='wikitable')

          for link in tb.find_all('b'):

          name = link.find('a')

          print(name.get_text('title'))

          僅僅9行代碼,我們就實現(xiàn)了網(wǎng)頁信息的爬取,我相信您從中已經(jīng)學(xué)到了Python、html的基礎(chǔ)知識,并且已經(jīng)懂得了網(wǎng)頁爬蟲的基本原理,如果想更深入的學(xué)習(xí)網(wǎng)頁爬蟲,你可以嘗試對以上代碼進行改進,嘗試爬取更多的網(wǎng)站,歡迎與我留言交流。

          crapy無疑是優(yōu)秀的爬蟲框架,它使用的是類似Requests的方式來爬取網(wǎng)頁,也就是說它爬取的靜態(tài)頁面,但是現(xiàn)實卻是大部分的網(wǎng)站都是動態(tài)的,我們看到的正常頁面都是瀏覽器渲染后的結(jié)果,如果直接使用scrapy爬取網(wǎng)頁很可能得不到期望的數(shù)據(jù)。一種想當(dāng)然的方式,就是通過自定義Middleware使用類似selenium這種模擬瀏覽器行為的方式來直接拿到渲染好的html內(nèi)容,這樣當(dāng)然是可行的,scrapy也可以輕松和selenium對接,不足之處是增加了資源的消耗。

          還有一種直達本質(zhì)的方式,就是找到數(shù)據(jù)的源頭,有的通過ajax請求獲取數(shù)據(jù)源,有的將數(shù)據(jù)源放到j(luò)s代碼中,通過瀏覽器開發(fā)工具分析交互過程找到數(shù)據(jù)源頭后,如果是ajax請求就直接請求對應(yīng)的接口就可以拿到數(shù)據(jù),本文將介紹數(shù)據(jù)源在js文件中的提取方法

          舉個例子

          這里以某文庫搜索結(jié)果為例,如果直接scrapy爬取頁面是看不到下圖中的搜索結(jié)果的,分析頁面結(jié)構(gòu)發(fā)現(xiàn)源頭數(shù)據(jù)在script腳本中,腳本中基本上就是類似json的數(shù)據(jù)對象,只要拿到j(luò)s腳本的對象數(shù)據(jù)就等于得到了搜索結(jié)果。

          安裝chompjs

          python是可以解析js腳本并獲取其中的數(shù)據(jù)對象的,這里推薦chompjs這個庫,chompjs可以直接將js中的數(shù)據(jù)對象返回給python,非常的方便,使用前需要使用pip install chompjs安裝此庫。需要注意的是,chompjs的核心代碼使用c來編寫,因此安裝chompjs需要事先安裝c++構(gòu)建工具。

          1. 如果事先沒有安裝c++構(gòu)建工具會報錯

          2. 訪問上面錯誤提示中的鏈接下載c++構(gòu)建工具并安裝

          安裝成功之后再次執(zhí)行pip install chompjs安裝成功

          scrapy shell

          scrapy shell可以使用交互方式快速驗證提取數(shù)據(jù)的代碼,不需要一次次地運行爬蟲驗證,非常的高效,接下來就演示如何使用scrapy shell把js中的數(shù)據(jù)提取出來。
          啟動scrapy shell

          scrapy shell "https://wenku.baidu.com/search?word=python&lm=0&od=0&fr=top_home&ie=utf-8&_wkts_=1711155481643&wkQuery=python"
          
          

          從返回的結(jié)果來看,response已經(jīng)獲取到了爬取的頁面內(nèi)容,接下來主要使用response進行數(shù)據(jù)提取

          我們已經(jīng)知道數(shù)據(jù)源在script中,直接使用response.css('script')可以獲取所有的script,我們需要的是第二個script中的腳本

          直接取出script中的js腳本,response.css("script::text")[1].get()

          最后就是導(dǎo)入chompjs庫,執(zhí)行js代碼并獲取返回的數(shù)據(jù)對象

          import chompjs
          data = chompjs.parse_js_object(js_code)

          data是dict字典對象,需要的數(shù)據(jù)在'sulaData'這個key中,至此,大功告成啦。

          簡單做個總結(jié),我認(rèn)為使用scrapy寫爬蟲根本不需要用到像selenium這樣的模擬瀏覽器下載器,解決的辦法就是找到數(shù)據(jù)的源頭,沒有數(shù)據(jù)源動態(tài)網(wǎng)站也無從渲染。不過,這里忽略了一個重要的環(huán)節(jié),就是登錄,不同平臺登錄機制也不同,各種各樣的驗證碼讓人頭疼,正面硬剛很可能碰的頭破血流,因此我不建議把登錄部分寫在爬蟲里,一種更好的方案是單獨開發(fā)一個cookie池服務(wù),cookie池服務(wù)負責(zé)管理所有平臺的用戶登錄,不能自動登錄的就提供手工登錄,并通過web api提供隨機獲取cookie,scrapy通過調(diào)用cookie池的api來獲取cookie實現(xiàn)模擬已登錄用戶狀態(tài)。

          eautifulsoup介紹:

          1. 是一個高效的網(wǎng)頁解析庫,可以從HTML或XML文件中提取數(shù)據(jù)
          2. 支持不同的解析器,比如,對HTML解析,對XML解析,對HTML5解析
          3. 就是一個非常強大的工具,爬蟲利器
          4. 一個靈活又方便的網(wǎng)頁解析庫,處理高效,支持多種解析器
          5. 利用它就不用編寫正則表達式也能方便的實現(xiàn)網(wǎng)頁信息的抓取


          第一步:安裝BeautifulSoup4,lxml

           pip install BeautifulSoup4
              BeautifulSoup 是一個可以從HTML或XML文件中提取數(shù)據(jù)的Python庫
          pip install lxml
              lxml 是一種使用 Python 編寫的解析庫,可以迅速、靈活地處理 XML 和 HTML


          第二步:導(dǎo)包,from bs4 import BeautifulSoup


          第三步:實例化對象

          html = """
          <html>
              <head>
                  <title>The Dormouse's story</title>
              </head>
              <body>
                  <p class="story">
                      Once upon a time there were three little sisters; and their names were
                      <a href="http://example.com/elsie" class="sister" id="link1">
                          <span>Elsie</span>
                      </a>
                      <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> 
                      and
                      <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
                      and they lived at the bottom of a well.
                  </p>
                  <p class="story">...</p>
          """
          soup = BeautifulSoup(html, 'lxml')  # h:要解析的內(nèi)容  lxml:解析器
          知識補充:print(soup.prettify())  # 代碼補全


          第四步:打印

          一、通過標(biāo)簽選取,會返回包含標(biāo)簽本身及其里面的所有內(nèi)容

          # print(soup.head) # 包含head標(biāo)簽在內(nèi)的所有內(nèi)容
          # print(soup.p) # 返回匹配的第一個結(jié)果

          1.print(soup.head)打印結(jié)果:

          <head>

          <title>The Dormouse's story</title>

          </head>

          2.print(soup.p)打印結(jié)果:

          <p class="title" name="dromouse"><b><span>The Dormouse's story</span></b></p>


          二、打印標(biāo)簽中間的文本內(nèi)容,不包含<>

          # .string是屬性,作用是獲取字符串文本
          print(soup.html.head.title.string)
          print(soup.title.string)

          打印結(jié)果都為:The Dormouse's story


          三、打印標(biāo)簽名

           .name --獲取標(biāo)簽本身名稱  
           print(soup.title.name)

          打印結(jié)果為:title


          四、打印屬性的值

          .attrs[]  --通過屬性拿屬性的值 
          print(soup.p.attrs['name'])# 獲取p標(biāo)簽name屬性的屬性值
          print(soup.a.attrs['id']) # 獲取p標(biāo)簽id屬性的屬性值
          
          print(soup.a['id']) #第二種寫法
          print(soup.p['class']) # 以列表得形式保存
          print(soup.a['href'])  # 也是只返回第一個值

          1.print(soup.p.attrs['name'])打印結(jié)果:

          dromouse

          2.print(soup.p.attrs['id'])和print(soup.a['id'])打印結(jié)果:

          link1

          3.print(soup.p['class'])打印結(jié)果:

          ['title', 'asdas']

          4.print(soup.a['href'])打印結(jié)果:

          http://example.com/elsie


          五、打印父標(biāo)簽下的所有子標(biāo)簽

          .contents 獲取標(biāo)簽子節(jié)點,以列表形式返回
          .children 獲取子節(jié)點,返回的是一個list類型的迭代器
          
          print(soup.body.contents)  # a是p的子節(jié)點,獲取P標(biāo)簽所有子節(jié)點內(nèi)容 返回一個list
          print(soup.body.children) #返回的是一個list類型的迭代器

          1.print(soup.body.contents)的打印結(jié)果:

          ['\n', <p class="title asdas" name="dromouse"><b><span>The Dormouse's story</span></b></p>, '\n', <p class="story">Once upon a time there were three little sisters; and their names were

          <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,

          <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and

          <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;

          and they lived at the bottom of a well.</p>, '\n', <p class="story">...</p>, '\n']

          2.print(soup.body.children)的打印結(jié)果:

          <list_iterator object at 0x000002035ECC7088>


          .children 獲取子節(jié)點講解

          1.和for循環(huán)一起使用

          for i in soup.p.children:
          print(i)

          打印結(jié)果:


          主站蜘蛛池模板: 伊人色综合一区二区三区影院视频| 国精产品一区一区三区MBA下载 | 免费观看一区二区三区| 日韩AV无码一区二区三区不卡毛片| 中文字幕无码不卡一区二区三区 | 中文字幕一区二区三区在线观看| 无码国产精品一区二区免费式直播| 无码视频一区二区三区| 久久99国产精一区二区三区| 日韩精品一区二区三区国语自制 | 亚洲av无码一区二区三区不卡| 好爽毛片一区二区三区四| 久久一区二区明星换脸| 午夜福利无码一区二区| 日韩电影一区二区三区| 日韩精品一区二区三区不卡| 亚洲综合一区国产精品| 无码日韩精品一区二区三区免费 | 色噜噜AV亚洲色一区二区| 国产一区二区三区露脸| 日本一道高清一区二区三区| 亚洲bt加勒比一区二区| 一区二区在线电影| 国产福利视频一区二区| 精品人妻少妇一区二区三区在线 | 香蕉久久一区二区不卡无毒影院| 亚洲性日韩精品一区二区三区| 日韩福利视频一区| 福利国产微拍广场一区视频在线| 久久久精品人妻一区二区三区蜜桃| 一本AV高清一区二区三区| 国产午夜精品一区二区| 中文字幕一区二区三区四区 | 人妻无码一区二区不卡无码av| 国产精品一区二区久久国产| 日本一区二区三区精品中文字幕| 熟女大屁股白浆一区二区| 无码少妇一区二区三区| 99久久精品日本一区二区免费 | 波多野结衣高清一区二区三区| 中文字幕一区日韩在线视频|