整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Python分布式爬蟲一點也不難!Scrapy+MongoDB爬取QQ音樂實戰

          過前七章的學習,相信大家對整個爬蟲有了一個比較全面的了解 ,其中分別涉及四個案例:靜態網頁爬取動態Ajax網頁爬取Selenium瀏覽器模擬爬取Fillderapp爬取,基本涵蓋了爬蟲的大致套路。本文在此基礎上進一步深耕,使用Scrapy框架構建QQ音樂分布式爬蟲系統,更加接近搜索引擎技術。


          一、前期準備

          1.Scrapy原理概述

          Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是為了爬蟲或者數據采集所設計的, 也可以應用在獲取API所返回的數據或者通用的網絡爬蟲。簡單來說,與普通爬蟲相比,Scrapy“有組織 有紀律”,更容易構建大規模抓取項目。

          下圖即為Scrapy框架的原理架構圖,下面來一一解釋:

          • Engine:引擎,框架的核心,用于觸發事務,處理整個系統的數據流處理。(Scrapy已實現)
          • Spiders:即爬蟲主程序,定義了爬取的邏輯和網頁內容的解析規則,主要負責解析響應并生成結果和新的請求(需要自己編寫)
          • Scheduler:任務調度器,接受引擎發過來的請求并將其加入隊列中,在引擎再次請求時將請求提供給引擎。(需要自己編寫)
          • Downloader:下載器,下載網頁內容,并將下載內容返回給spider進行處理(Scrapy已實現)
          • ItemPipeline:項目管道,負責處理spider從網頁中抽取的數據,主要是負責清洗,驗證和向數據庫中存儲數據(需要自己編寫)
          • Downloader Middlewares:下載中間件,是處于Scrapy的Request和Requesponse之間的處理模塊(Scrapy已實現)
          • Spider Middlewares:spider中間件,主要處理spider輸入的響應和輸出的結果及新的請求middlewares.py里實現(Scrapy已實現)

          有了上文對Scrapy組件的介紹,下面描述一下Scrapy運作流程:

          1. Spider使用yeild將request發送給Engine
          2. Engine對request不做任何處理發送給Scheduler
          3. Engine拿到request,通過Middleware發送給Downloader
          4. Downloader獲取response之后經過Middleware發送給Engine
          5. Engine傳遞給SpiderSpider的parse()方法對response進行解析
          6. Spider將解析出來的items或者requests返回給Engine
          7. Engine將items發送給ItemPipeline,將requests發送給Scheduler
          8. 只有當Scheduler中不存在request時程序才會停止

          2.Scrapy安裝配置

          接下來開始安裝Scrapy,Scrapy已經支持python3,本文環境為win10+Anaconda3,實測安裝沒有出現問題。首先通過pip安裝Scrapy:

          pip install scrapy

          之后進入到python命行并導入,如果沒有出現報錯則初步說明安裝成功。

          import scrapy

          3.Scrapy入門測試

          接著我們通過一個百度分布式爬蟲框架小例子進行測試,首先在cmd中用cd命令切到任一目錄,之后運行:

          scrapy startproject littletest

          然后切換至項目目錄并通過genspider命令加入爬蟲網站:

          cd littletest
          scrapy genspider baidu www.baidu.com

          之后進入目錄查看,目錄結構如下:

          • scrapy. cfg # Scrapy 部署時的配置文件
          • littletest #項目模塊
          • items.py # 定義爬取的數據結構
          • middlewares.py # 定義爬取時的中間件
          • pipelines.py # Pipelines 的定義,定義數據管道
          • settings.py #配置文件,放置基本設置和存儲變量
          • spiders #放置Spiders 的文件夾

          同時我們進入settings.pyROBOTSTXT_OBEY配置項改為False,即不遵守爬蟲協議,否則很多網站無法正常獲取。

          ROBOTSTXT_OBEY = False

          最后進入命令行啟動scrapy爬蟲

          scrapy crawl baidu

          得到結果如下,狀態碼為200且接收字節數大于0,則表明爬取成功!

          3.MongDB安裝配置

          MongoDB 是目前最流行的 NoSQL 數據庫之一,使用的數據類型 BSON(類似 JSON),下載安裝及配置以及鏈接python的pymongo數據庫和最優秀的compass可視化工具安裝及使用可參考作者博客。


          二、QQ音樂爬蟲實戰

          1.網頁分析

          通過打開QQ音樂官網并點擊歌手欄(鏈接傳送門:https://y.qq.com/portal/singer_list.html),并打開DevTools工具,選擇XHR異步并觀察item,發現musicu.fcg一欄返回的json數據中有歌手相關信息。

          因此我們進一步進入該項headers獲取到請求url,繼續點擊下一頁,通過三頁(url如下)查找規律進一步發現sin參數發生變化,規律公式為80*(n-1)n為頁碼。篇幅有限,json數據解析就不再解釋,可參考前文。

          https://u.y.qq.com/cgi-bin/musicu.fcg?-=getUCGI9874589974344781&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8?ice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A-100%2C%22sin%22%3A0%2C%22cur_page%22%3A1%7D%7D%7D
          https://u.y.qq.com/cgi-bin/musicu.fcg?-=getUCGI8205866038561849&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8?ice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A-100%2C%22sin%22%3A80%2C%22cur_page%22%3A2%7D%7D%7D
          https://u.y.qq.com/cgi-bin/musicu.fcg?-=getUCGI8189152987042585&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8?ice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A-100%2C%22sin%22%3A160%2C%22cur_page%22%3A3%7D%7D%7D

          以此類推依次獲取到歌曲下載地址歌曲列表地址歌詞列表地址歌曲評論地址等并配置翻頁參數:

          start_urls = ['https://u.y.qq.com/cgi-bin/musicu.fcg?data=%7B%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer' \
              '%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genr' \
              'e%22%3A-100%2C%22index%22%3A-100%2C%22sin%22%3A{num}%2C%22cur_page%22%3A{id}%7D%7D%7D']  # 歌手地址
          song_down = 'https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&jsonpCallback=MusicJsonCallback&ci' \
                      'd=205361747&songmid={songmid}&filename=C400{songmid}.m4a&guid=9082027038'  # 歌曲下載地址
          song_url = 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?singermid={singer_mid}&order=listen&num={sum}'  # 歌曲列表地址
          lrc_url = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?nobase64=1&musicid={musicid}'  # 歌詞列表地址
          discuss_url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg?cid=205360772&reqtype=2&biztype=1&topid=' \
                        '{song_id}&cmd=8&pagenum=0&pagesize=25'  # 歌曲評論地址

          之后我們開始建立scrapy爬蟲程序。首先切換至個人目錄下面開啟項目:

          scrapy startproject musicspyder
          cd musicspyder
          scrapy genspider qqmusic y.qq.com

          2.spyder.py編寫

          接下來開始對Scrapy組件逐一完善,首先對主要爬蟲程序qqmusic.py進行編寫,在生成類中分別定義爬蟲名允許域名爬取url等變量,并創建解析用戶信息歌曲信息歌詞信息評論信息url信息方法:

          import json
          import scrapy
          from scrapy import Request
          from musicspyder.items import QqMusicItem
          ?
          class MusicSpider(scrapy.Spider):
            name = 'qqmusic'
            allowed_domains = ['y.qq.com']
            start_urls = ['...']
            song_down = '...'
            song_url = '...'
            lrc_url = '...'
            discuss_url = '...'
            # 生成請求并從配置中獲取頁數
            def start_requests(self):
            # 解析用戶信息
            def parse_user(self, response)
            # 解析歌曲信息
            def parse_song(self, response)
            # 解析歌詞信息
            def parse_lrc(self, response)
            # 解析評論信息
            def parse_comment(self, response)
            # 解析url信息
            def parse_url(self, response)

          3.items.py編寫


          之后對items.py進行編寫,在QqMusicItem類中創建MongoDB集合名id字段、歌手名字段、歌曲名字段、歌曲地址字段、歌詞字段、評論字段等變量:

          import scrapy
          from scrapy import Field
          class QqMusicItem(scrapy.Item):
            # mongodb collection
            collection = 'singer'
            id = Field()
            # 歌手名字字段
            singer_name = Field()
            # 歌曲名字段
            song_name = Field()
            # 歌曲地址字段
            song_url = Field()
            # 歌詞字段
            lrc = Field()
            # 評論字段
            comment = Field()

          4.piplines.py編寫


          再對piplines.py進行編寫,新增加IrcText類對歌詞進行解析處理:

          import json
          import pymongo
          import re
          from scrapy.exceptions import DropItem
          from musicspyder.items import QqMusicItem
          # 默認pipline類
          class QqMusicPipeline(object):
              def process_item(self, item, spider):
                  return item
          # 在pipline中新增類用于解析和清洗單詞
          class lrcText(object):
            # 進行正則匹配獲取的單詞
            def process_item(self, item, spider):
          # 保存到Mongo數據庫
          class MongoPipline(object):
            # 構造方法
            def __init__(self, mongo_url, mongo_db):
            # 從settings.py中獲取Mongo rl和庫
            @classmethod
            def from_crawler(cls, crawler):
            # 存儲處理
            def process_item(self, item, spider):
            # 關閉mongodb數據庫
            def close_spider(self, spider):

          之后是middlewares.py代碼編寫,自定義my_useragent類,使用random庫隨機選擇瀏覽器頭:

          import random
          from scrapy import signals
          # 默認中間件
          class MusicspyderSpiderMiddleware(object):
            @classmethod
            def from_crawler(cls, crawler):
            def process_spider_input(self, response, spider):
            def process_spider_output(self, response, result, spider):
            def process_spider_exception(self, response, exception, spider):
            def process_start_requests(self, start_requests, spider):
            def spider_opened(self, spider):
          ?
          # 在中間件中加入useragent防爬
          class my_useragent(object):
            def process_request(self, request, spider):
              user_agent_list = ['...','...',...]
              user_agent = random.choice(user_agent_list)
              request.headers['User_Agent'] = user_agent

          6.settings.py編寫

          最后是settings.py編寫,配置相應的爬取頁數爬取歌手歌曲數量、mongoDB的地址數據庫等變量,并且設置不遵守Robots協議,開啟下載中間件和itempipline:

          # 系統配置變量
          BOT_NAME = 'musicspyder'
          SPIDER_MODULES = ['musicspyder.spiders']
          NEWSPIDER_MODULE = 'musicspyder.spiders'
          MAX_PAGE = 3    # 爬取頁數
          SONGER_NUM = 1      # 爬取歌手歌曲數量
          MONGO_URL = 'mongodb://localhost:27017/'
          MONGO_DB = 'music'  # mongo數據庫
          # 定義robots協議遵守規則為:不遵守
          ROBOTSTXT_OBEY = False
          # 啟用下載中間件
          DOWNLOADER_MIDDLEWARES = {
              # 'musicspyder.middlewares.QqMusicDownloaderMiddleware': 543,
              'musicspyder.middlewares.my_useragent': 544,
          }
          # 啟用pipline中mongodb存儲
          ITEM_PIPELINES = {
              # 'musicspyder.pipelines.QqMusicPipeline': 300,
              'musicspyder.pipelines.lrcText': 300,
              'musicspyder.pipelines.MongoPipline': 302,
          }

          定義上述scrapy組件完成之后我們即可在命令行中輸入以下命令用以啟用qqmusic爬蟲框架:

          scrapy crawl qqmusic

          之后進入mongodb查看爬取結果即可得到響應歌手歌曲信息:


          三、爬蟲系列總結

          至此Scrapy框架爬取QQ音樂講解完成,Python網絡爬蟲數據采集實戰系列也隨之結束,總體來說,爬蟲是一種細致活,需要掌握固定的套路并且去努力尋找網絡數據規律的蛛絲馬跡方能爬取成功,同時也要量力而行,防止對對方服務器造成巨大負載或者己方投入產出不成正比。完整代碼可以在頭條號中私信“QQ音樂”獲得,前文涉及的基礎知識可參考下面鏈接:

          爬蟲所要了解的基礎知識,這一篇就夠了!Python網絡爬蟲實戰系列

          一文帶你深入了解并學會Python爬蟲庫!從此數據不用愁

          Python爬蟲有多簡單?一文帶你實戰豆瓣電影TOP250數據爬取!

          一文弄清Python網絡爬蟲解析庫!內含多個實例講解

          誰說同花順很難爬?一文帶你學會用Python爬取財經動態網頁!

          誰說京東商品很難爬?一文教你用Python構建電商網站爬蟲!

          Python網絡爬蟲實戰之Fiddler抓包app!附代碼

          參考鏈接:

          https://blog.csdn.net/qq_1290259791/article/details/82263014

          https://www.jianshu.com/p/cecb29c04cd2

          https://cuiqingcai.com/4380.html

          們之前用scrapy爬取過某網的段子,還記得怎么爬取嗎?

          爬蟲網站代碼(spiders/duanzi.py):

          import scrapy
          # 這里需要導入items.py文件包
          from duanziPro.items import DuanziproItem
          
          
          class DuanziSpider(scrapy.Spider):
              name = 'duanzi'
              # allowed_domains = ['www.xxx.com']
              start_urls = ['https://duanzixing.com/段子/']
              
              def parse(self, response):
                  # 數據解析名稱和內容
                  article_list = response.xpath('/html/body/section/div/div/article')
                  for article in article_list:
                      title = article.xpath('./header/h2/a/@title').extract_first()
                      note = article.xpath('./p[2]/text()').extract_first()
          
                      # 實例化一個item類型對象,將解析到的數據存儲到該對象中
                      item = DuanziproItem()
                      item['title'] = title
                      item['note'] = note
          
                      # 將item對象提交給管道
                      yield item

          item.py

          import scrapy
          
          class DuanziproItem(scrapy.Item):
              # define the fields for your item here like:
              # name = scrapy.Field()
              title = scrapy.Field()
              note = scrapy.Field()

          管道文件代碼(pipelines.py):

          class DuanziproPipeline:
            	def process_item(self, item, spider):
                print(item)

          執行工程,打印數據如下:

          數據看到了,但這只是一頁,那怎么爬取多頁呢?

          有的同學就說了,這還不簡單,直接加fro循環。

          但有沒有想過,管道的對象傳遞是yield,fro循環肯定行不通。

          所以,這里我們引入了一個新的方式:手動請求發送。


          手動請求發送

          scrapy手動發送請求代碼:

          • GET

          yield scrapy.Request(url,callback)

          callback:制定解析函數,用于解析數據。

          • POST

          yield scrapy.FormRequest(url,callback,formdata)

          formdata:字典,請求參數

          代碼實現

          我們先來創建一個新的工程:

          1. scrapy start hanReqPro
          2. cd hanReqPro
          3. scrapy genspider www.xx.com

          然后修改配置文件等等

          好了后我們先分析下網站。

          我們看到翻頁后的網址是/段子/2/等,那么就可以定義一個url模板

          # 通用的url模板
          url = 'https://duanzixing.com/段子/%d/'

          上面說了,需要一個callback函數,用于解析數據的實現。其實就是我們爬取一頁時的數據解析函數parse:

          def parse(self, response):
              # 數據解析名稱和內容
              article_list = response.xpath('/html/body/section/div/div/article')
              for article in article_list:
                  title = article.xpath('./header/h2/a/@title').extract_first()
                  note = article.xpath('./p[2]/text()').extract_first()
          
                  # 實例化一個item類型對象,將解析到的數據存儲到該對象中
                  item = HandreqproItem()
                  item['title'] = title
                  item['note'] = note
          
                  # 將item對象提交給管道
                  yield item

          第一頁的數據是直接傳遞給了管道,爬取5頁的話,我們需要一個遞歸!

          我們先在函數外定義一個page_num:

          # 因為第一頁有了,所以我們從第二頁開始
          page_num = 2

          然后我們寫遞歸代碼,讓yield scrapy.Request(url,callback)執行指定次數:

          # 直接寫在parse函數里面。放在yield item下面
          				# 爬取剩下的4頁
                  while self.page_num <= 5:  # 結束遞歸的條件
                      new_url = format(self.url % self.page_num)  # 其他頁碼對應的完整url
                      self.page_num += 1
                      # 對新的頁碼對應的url進行請求發送(手動請求GET發送)
                      yield scrapy.Request(url=new_url, callback=self.parse)

          管道中(pipelines.py)我們直接打印item就可以了,主要是看效果

          class HandreqproPipeline:
              # 定義一個數值,記錄接收item的次數。也就是記錄打印了多少條數據
              count = 0
          
              def process_item(self, item, spider):
                  print(item)
                  self.count += 1
                  print(self.count)

          完整代碼:

          import scrapy
          from handReqPro.items import HandreqproItem
          
          
          class DuanziSpider(scrapy.Spider):
              name = 'duanzi'
              # allowed_domains = ['www.xx.com']
              start_urls = ['https://duanzixing.com/段子/']
          
              # 通用url模板
              url = 'https://duanzixing.com/段子/%d/'
              page_num = 2
          		
              # 將段子網中所有頁碼對應的數據進行爬取(前五頁)
              def parse(self, response):
                  # 數據解析名稱和內容
                  article_list = response.xpath('/html/body/section/div/div/article')
                  for article in article_list:
                      title = article.xpath('./header/h2/a/@title').extract_first()
                      note = article.xpath('./p[2]/text()').extract_first()
          
                      # 實例化一個item類型對象,將解析到的數據存儲到該對象中
                      item = HandreqproItem()
                      item['title'] = title
                      item['note'] = note
          
                      # 將item對象提交給管道
                      yield item
          
                      while self.page_num <= 5:
                          new_url = format(self.url % self.page_num)
                          self.page_num += 1
                          yield scrapy.Request(url=new_url, callback=self.parse)

          執行工程~我們就發現打印了60條數據,每頁是12條,總共5頁!


          其他問題

          • 為什么start_urls列表中的url會被自行進行get請求的發送?
            因為列表中的url其實是被start_requests這個父類方法實現的get請求發送
          # 父類方法:這個是該方法的原始實現
              def start_requests(self):
                  for u in self.start_urls:
                      yield scrapy.Request(url=u, callback=self.parse)
          • 如何將start_urls中的url默認進行post請求的發送?

          重寫start_requests(self)父類方法即可

          def start_requests(self):
                      for u in self.start_urls:
                          yield scrapy.FormRequest(url,callback,formdata)

          關注Python濤哥!學習更多Python知識!

          網頁抓取是一種重要的技術,經常在許多不同的環境中使用,尤其是數據科學和數據挖掘。 Python在很大程度上被認為是網絡抓取的首選語言,其原因在于Python的內嵌電池特性。 使用Python,您可以在大約15分鐘內使用不到100行代碼創建一個簡單的抓取腳本。 因此,無論何種用途,網頁抓取都是每個Python程序員必須具備的技能。

          在我們開始動手之前,我們需要退后一步,考慮什么是網頁抓取,什么時候應該使用它,何時避免使用它。

          如您所知,網頁抓取是一種用于從網站自動提取數據的技術。 重要的是要理解,網頁抓取是一種從各種來源(通常是網頁)中提取數據的粗略技術。 如果網站的開發人員足夠慷慨地提供API來提取數據,那么訪問數據將是一種更加穩定和健壯的方式。 因此,根據經驗,如果網站提供API以編程方式檢索其數據,請使用它。 如果API不可用,則只能使用網絡抓取。

          請務必遵守有關您使用的每個網站的網頁抓取的任何規則或限制,因為有些網站不允許這樣做。 有了這個清楚的認識,讓我們直接進入教程。

          在本教程中,我們將抓取http://quotes.toscrape.com/,這是一個列出著名作家名言的網站。

          網頁抓取管道

          我們可以將web-scraping理解為包含3個組件的管道:

          下載:下載HTML網頁

          解析:解析HTML并檢索我們感興趣的數據

          存儲:以特定格式將檢索到的數據存儲在本地計算機中

          下載HTML

          從網頁中提取任何數據,從邏輯上講,我們首先要下載它。 我們有兩種方法可以做到這一點:

          1.使用瀏覽器自動化庫

          您可以使用Selenium等瀏覽器自動化庫從網頁下載HTML。 Selenium允許您打開瀏覽器,比方說Chrome,并根據需要控制它。 您可以在瀏覽器中打開網頁,然后使用Selenium自動獲取該頁面的HTML代碼。

          但是,這種方法有一個很大的缺點 - 它明顯變慢。 原因是運行瀏覽器并在瀏覽器中呈現HTML的開銷。 此方法僅應用于特殊情況 - 我們要抓取的內容在瀏覽器中使用JavaScript代碼,或者要求我們單擊按鈕/鏈接以獲取數據,Selenium可以為我們執行此操作。

          2.使用HTTP庫

          與第一種方法不同,HTTP庫(例如Requests模塊或Urllib)允許您發送HTTP請求,完全不需要打開任何瀏覽器。 這種方法應該始終是首選,因為它比Selenium快得多。

          現在讓我告訴您如何使用Selenium和Requests庫實現管道這個組件:

          使用Requests

          使用以下命令安裝Requests模塊:

          現在您可以在代碼中使用它,如下所示:

          這里,對URL進行HTTP GET請求,這幾乎與下載網頁同義。 然后,我們可以通過訪問requests.get方法返回的結果對象來獲取頁面的HTML源代碼。

          使用Selenium

          您可以通過pip安裝selenium模塊:

          在這里,我們首先創建一個表示瀏覽器的webdriver對象。 這樣做會在運行代碼的計算機上打開Chrome瀏覽器。 然后,通過調用webdriver對象的get方法,我們可以打開URL。 最后,我們通過訪問webdriver對象的page_source屬性來獲取源代碼。

          在這兩種情況下,URL的HTML源都作為字符串存儲在page變量中。

          解析HTML和提取數據

          不必深入計算機科學理論,我們可以將解析定義為分析字符串的過程,以便我們可以理解其內容,從而輕松訪問其中的數據。

          在Python中,有兩個庫可以幫助我們解析HTML:BeautifulSoup和Lxml。 Lxml是一個比BeautifulSoup更低級的框架,我們可以在BeautifulSoup中使用Lxml作為后端,因此對于簡單的HTML解析,BeautifulSoup將是首選的庫。

          但在我們深入分析之前,我們必須分析網頁的HTML,看看我們想要抓取的數據是如何構建和定位的。只有當我們掌握了這些信息時,我們才能從解析的HTML中獲取我們想要的信息。但幸運的是,我們不必在編輯器中打開源代碼,并手動理解每個HTML元素并將其與渲染頁面中的相應數據相關聯。大多數瀏覽器都提供了一個檢查器,比如Chrome的開發人員工具,它使我們只需單擊它們即可快速查看任何元素的HTML代碼。

          要在Chrome中執行此操作,請在Chrome中打開網頁,然后右鍵單擊要抓取的數據,然后選擇“檢查”。在Firefox中,此選項稱為Inspect Element - 這是在做相同的事情,但只是名稱不同。

          您會注意到Chrome窗口底部打開了一個窗格,其中包含您單擊的元素的源代碼。 瀏覽一下源代碼,了解我們想要抓取的數據是如何在HTML代碼中構建的。

          經過一些檢查后你可以理解,http://quotes.toscrape.com/上的每個引用都包含在一個帶有class =“quote”屬性的div中。 在該div中,引用的文本在class =“text”的范圍內,作者的名稱在class =“author”的小標簽中。 當我們實際解析HTML并提取數據時,將需要此信息。

          現在,讓我們開始使用BeautifulSoup解析HTML頁面。 但首先,我們必須安裝它:

          安裝好之后,可以像下面這樣在代碼中調用:

          首先,我們通過將頁面傳遞給BeautifulSoup類構造函數來創建頁面的解析版本。 如您所見,我們還將第二個參數html.parser傳遞給構造函數。 這是Beautiful Soup將用于解析傳遞給它的字符串的解析器的名稱。 你可以使用我們之前談到過的解析器lxml,因為你已經安裝了Lxml庫。

          然后,我們提取包含class =“quote”的頁面中的所有div標簽,因為我們知道這些是包含引用的div。 為此,Beautiful Soup 4提供了find_all功能。 我們將標記名稱和類名稱傳遞給find_all函數,并返回滿足條件的所有標記,即包含引用的標記。

          這里需要注意的一件重要事情是,我們在這里使用樹結構。 變量soup以及引用的每個元素都是樹。 在某種程度上,引用的元素是較大的soup樹的一部分。 無論如何,為避免進入不同的討論,讓我們繼續。

          我們知道引用的文本是帶有class =“text”的span標記,而作者是帶有class =“author”的小標記。 要從quote元素中提取它們,我們再次使用類似的函數find。 find函數使用與find_all函數相同的參數。 唯一的區別是它返回滿足條件的第一個標記,而find_all返回標記列表。 此外,我們希望訪問返回對象的text屬性,該對象包含該標記中包含的文本。

          因此,正如您在代碼中看到的那樣,我們遍歷列表引用的所有元素,并提取引用文本和作者名稱,將它們存儲在名稱為scraped的列表。 在控制臺上打印時,已抓取的列表如下所示:

          存儲檢索的數據

          一旦我們獲得了數據,我們就可以以任何我們想要的格式存儲它,例如CSV文件,SQL數據庫或NoSQL數據庫。 嚴格來說,這一步不應算作抓取過程的一部分,但為了完整起見,我將簡要介紹它。

          我想說最流行的存儲抓取數據的方法是將它們存儲為CSV電子表格,所以我將簡要介紹如何做到這一點。 我不會詳細介紹,因為您應該參考官方的Python文檔。 所以,不用多說,讓我們看看代碼。

          我們可以看到,代碼非常明顯。 我們從打開的quotes.csv文件創建一個CSV編寫器對象,然后使用writerow函數逐個寫入引用。 很明顯,writerow函數接受一個列表作為輸入,然后將其作為一行寫入CSV。

          結論和后續步驟

          本教程應該幫助您了解在學習自己實現簡單的scraper時基本上是什么。 這種抓取應該足以實現簡單的自動化或小規模數據檢索。 但是如果你想有效地提取大量數據,你應該研究一下抓取框架,特別是Scrapy。 它可以幫助您使用幾行代碼編寫非常快速,高效的scraper。 無論你使用什么樣的框架,在那個閃亮的表面下面,框架也使用這些非常基本的抓取原則,所以理解本教程應該可以幫助你為開始抓取的探險建立基礎知識。

          英文原文:https://stackabuse.com/introduction-to-web-scraping-with-python/
          譯者:javylee

          主站蜘蛛池模板: 午夜影院一区二区| 熟妇人妻一区二区三区四区| 又硬又粗又大一区二区三区视频| 色一乱一伦一图一区二区精品| 在线视频精品一区| 99精品国产高清一区二区三区| 亚洲AV无码一区二区乱子仑| 亚洲不卡av不卡一区二区| 女人和拘做受全程看视频日本综合a一区二区视频 | 在线免费视频一区二区| 色一乱一伦一图一区二区精品 | 乱色精品无码一区二区国产盗| 亚洲日本一区二区一本一道| 精品国产一区二区麻豆| 色久综合网精品一区二区| 中文字幕人妻无码一区二区三区| 日本一区二区三区免费高清在线| 无码福利一区二区三区| 中文字幕一区二区三区5566| 精品国产免费一区二区三区| 国产AV一区二区精品凹凸| 国产一区在线电影| 日本一区二区三区不卡视频中文字幕 | 精品一区二区三区在线观看视频| 日韩免费无码一区二区三区| 无码国产精品一区二区免费式直播| 一本大道在线无码一区| 波多野结衣电影区一区二区三区| 亚洲爽爽一区二区三区| 国精产品一区一区三区免费视频 | 夜夜添无码试看一区二区三区| 国产激情无码一区二区| 国产日韩一区二区三区在线播放| 精品国产高清自在线一区二区三区 | 不卡一区二区在线| 久久久国产精品亚洲一区| 成人毛片无码一区二区| 成人午夜视频精品一区| 3D动漫精品啪啪一区二区下载 | 免费观看日本污污ww网站一区| 久久精品国产一区二区|