摘要:前言新接觸爬蟲,經(jīng)過一段時間的實(shí)踐,寫了幾個簡單爬蟲,爬取豆瓣電影的爬蟲例子網(wǎng)上有很多,但都很簡單,大部分只介紹了請求頁面和解析部分,對于新手而言,我希望能夠有一個比較全面的實(shí)例。
0.前言
新接觸爬蟲,經(jīng)過一段時間的實(shí)踐,寫了幾個簡單爬蟲,爬取豆瓣電影的爬蟲例子網(wǎng)上有很多,但都很簡單,大部分只介紹了請求頁面和解析部分,對于新手而言,我希望能夠有一個比較全面的實(shí)例。所以找了很多實(shí)例和文章,并整合在一起,在現(xiàn)有豆瓣爬蟲的基礎(chǔ)上,增加了一些內(nèi)容,算是比較全的內(nèi)容了。主要包括項(xiàng)目建立、請求頁面、xpath解析、自動翻頁、數(shù)據(jù)輸出、編碼處理等等。。
系統(tǒng)環(huán)境System Version:Ubuntu 16.04
Python Version:3.5.2
Scrapy Version:1.5.0
執(zhí)行如下命令建立scrapy爬蟲項(xiàng)目
scrapy startproject spider_douban
命令執(zhí)行完成后,建立了spider_douban文件夾,目錄結(jié)構(gòu)如下:
. ├── scrapy.cfg └── spider_douban ├── __init__.py ├── items.py ├── middlewares.py ├── pipelines.py ├── settings.py └── spiders ├── douban_spider.py └── __init__.py2.建立爬蟲數(shù)據(jù)模型
打開./spider_douban/items.py文件,編輯內(nèi)容如下:
import scrapy class DoubanMovieItem(scrapy.Item): # 排名 ranking = scrapy.Field() # 電影名稱 movie_name = scrapy.Field() # 評分 score = scrapy.Field() # 評論人數(shù) score_num = scrapy.Field()3.新建爬蟲文件
新建./spiders/douban_spider.py文件,編輯內(nèi)容如下:
from scrapy import Request from scrapy.spiders import Spider from spider_douban.items import DoubanMovieItem class DoubanMovieTop250Spider(Spider): name = "douban_movie_top250" start_urls = { "https://movie.douban.com/top250" } """ headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36", } def start_requests(self): url = "https://movie.douban.com/top250" yield Request(url, headers=self.headers) """ def parse(self, response): item = DoubanMovieItem() movies = response.xpath("http://ol[@class="grid_view"]/li") print(movies) print("=============================================") for movie in movies: item["ranking"] = movie.xpath( ".//div[@class="pic"]/em/text()").extract()[0] item["movie_name"] = movie.xpath( ".//div[@class="hd"]/a/span[1]/text()").extract()[0] item["score"] = movie.xpath( ".//div[@class="star"]/span[@class="rating_num"]/text()" ).extract()[0] item["score_num"] = movie.xpath( ".//div[@class="star"]/span/text()").re(r"(d+)人評價")[0] yield item next_url = response.xpath("http://span[@class="next"]/a/@href").extract() if next_url: next_url = "https://movie.douban.com/top250" + next_url[0] yield Request(next_url)爬蟲文件各部分功能記錄
douban_spider.py文件主要有幾部分構(gòu)成。
導(dǎo)入模塊from scrapy import Request from scrapy.spiders import Spider from spider_douban.items import DoubanMovieItem
Request類用于請求要爬取的頁面數(shù)據(jù)
Spider類是爬蟲的基類
DoubanMovieItem是我們第一步建立的爬取數(shù)據(jù)模型
基于spider類定義的爬蟲類DoubanMovieTop250Spider中,首先定義爬蟲的基本信息:
name:在項(xiàng)目中爬蟲的名稱,可以在項(xiàng)目目錄中執(zhí)行scrapy list獲取已經(jīng)定義的爬蟲列表
start_urls:是爬取的第一個頁面地址
headers:是向web服務(wù)器發(fā)送頁面請求的時候附加的user-agent消息,告訴web服務(wù)器是什么類型的瀏覽器或設(shè)備在請求頁面,對于不具備簡單反爬機(jī)制的網(wǎng)站,headers部分可以省略。
為了迷惑web服務(wù)器,一般會在爬蟲發(fā)送web請求的時候定義user-agent信息,這里有兩種寫法。
header的第一種定義:
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36", } def start_requests(self): url = "https://movie.douban.com/top250" yield Request(url, headers=self.headers)
可以看到,這種寫法中,start_urls定義沒有了,轉(zhuǎn)而定義了start_requests函數(shù),開始的url寫到了函數(shù)里。同時,定義了headers字典,在發(fā)送Request請求的時候,將headers字典一并發(fā)送。這種寫法簡單直觀,缺點(diǎn)是在一個爬蟲項(xiàng)目執(zhí)行期間,所有請求都是一個User-Agent屬性。
header的第二種定義:
start_urls = { "https://movie.douban.com/top250" }
簡單、直接的定義start_urls屬性,而Request中的header屬性通過其他方法另外定義,容后再說。
parse處理函數(shù)逐句分解說明
1.基于我們定義的DoubanMovieItem類創(chuàng)建item實(shí)例
item = DoubanMovieItem()
2.解析頁面 - 獲取內(nèi)容框架
通過分析頁面源碼,我們能夠看到,頁面中的電影信息是保存在了標(biāo)簽中,這個
標(biāo)簽有一個獨(dú)特的樣式表grid_view,而每一個多帶帶的電影信息保存在了標(biāo)簽中,下面代碼獲取class屬性為grid_view的
標(biāo)簽下的所有標(biāo)簽內(nèi)容。
movies = response.xpath("http://ol[@class="grid_view"]/li")
3.解析頁面 - 獲取分項(xiàng)
在每一個標(biāo)簽中,還有內(nèi)部結(jié)構(gòu),通過xpath()解析,將每一項(xiàng)內(nèi)容解析出來,賦值給item實(shí)例中的各個字段。通過查看movie.douban.com/top250頁面的源碼可以很容易找到這個標(biāo)簽定義的內(nèi)容。如果我們通過type()函數(shù)查看movies的變量類型,可以發(fā)現(xiàn)他的類型是標(biāo)簽中的每一個標(biāo)簽都是這個列表中的一項(xiàng),那么就可以對movies做迭代。
首先看看標(biāo)簽中的頁面結(jié)構(gòu):
可以看到要提取數(shù)據(jù)的各部分所在標(biāo)簽位置:
排名:class屬性為pic的標(biāo)簽下,,標(biāo)簽中...
電影名:class屬性為hd的標(biāo)簽下,標(biāo)簽中的第一個標(biāo)簽...
評分:class屬性為star的標(biāo)簽下,class屬性為rating_num的標(biāo)簽中...
評論人數(shù):class屬性為star的標(biāo)簽下,標(biāo)簽中。由于使用了re正則表達(dá)式,所以沒有特別指定是哪一個標(biāo)簽。回到代碼部分,對之前定義的movies做迭代,逐項(xiàng)獲取要抓取的數(shù)據(jù)。
for movie in movies: item["ranking"] = movie.xpath( ".//div[@class="pic"]/em/text()").extract()[0] item["movie_name"] = movie.xpath( ".//div[@class="hd"]/a/span[1]/text()").extract()[0] item["score"] = movie.xpath( ".//div[@class="star"]/span[@class="rating_num"]/text()" ).extract()[0] item["score_num"] = movie.xpath( ".//div[@class="star"]/span/text()").re(r"(d+)人評價")[0] yield item4.Url跳轉(zhuǎn)(翻頁)
如果到此為止,我們可以將https://movie.douban.com/top250頁面中的第一頁內(nèi)容爬取到,但只有25項(xiàng)記錄,要爬取全部的250條記錄,就要執(zhí)行下面代碼:
next_url = response.xpath("http://span[@class="next"]/a/@href").extract() if next_url: next_url = "https://movie.douban.com/top250" + next_url[0] yield Request(next_url)首先通過xpath解析了頁面中后頁的鏈接,并賦值給next_url變量,如果我們當(dāng)前在第一頁,那么解析后頁的鏈接就是?start=25&filter=。將解析的后頁鏈接與完整url連接形成完整的地址,再次執(zhí)行Request(),就實(shí)現(xiàn)了對全部250條記錄的爬取。注意:通過xpath解析出的結(jié)果是列表,所以在引用的時候?qū)懗?b>next_url[0]。
4.處理隨機(jī)Head屬性(隨機(jī)User-Agent)實(shí)現(xiàn)隨機(jī)的head屬性發(fā)送。主要改兩個文件:
settings.pyUSER_AGENT_LIST = [ "zspider/0.9-dev http://feedback.redkolibri.com/", "Xaldon_WebSpider/2.0.b1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)", "Mozilla/5.0 (compatible; Speedy Spider; http://www.entireweb.com/about/search_tech/speedy_spider/)", "Speedy Spider (Entireweb; Beta/1.3; http://www.entireweb.com/about/search_tech/speedyspider/)", "Speedy Spider (Entireweb; Beta/1.2; http://www.entireweb.com/about/search_tech/speedyspider/)", "Speedy Spider (Entireweb; Beta/1.1; http://www.entireweb.com/about/search_tech/speedyspider/)", "Speedy Spider (Entireweb; Beta/1.0; http://www.entireweb.com/about/search_tech/speedyspider/)", "Speedy Spider (Beta/1.0; www.entireweb.com)", "Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)", "Speedy Spider (http://www.entireweb.com/about/search_tech/speedyspider/)", "Speedy Spider (http://www.entireweb.com)", "Sosospider+(+http://help.soso.com/webspider.htm)", "sogou spider", "Nusearch Spider (www.nusearch.com)", "nuSearch Spider (compatible; MSIE 4.01; Windows NT)", "lmspider (lmspider@scansoft.com)", "lmspider lmspider@scansoft.com", "ldspider (http://code.google.com/p/ldspider/wiki/Robots)", "iaskspider/2.0(+http://iask.com/help/help_index.html)", "iaskspider", "hl_ftien_spider_v1.1", "hl_ftien_spider", "FyberSpider (+http://www.fybersearch.com/fyberspider.php)", "FyberSpider", "everyfeed-spider/2.0 (http://www.everyfeed.com)", "envolk[ITS]spider/1.6 (+http://www.envolk.com/envolkspider.html)", "envolk[ITS]spider/1.6 ( http://www.envolk.com/envolkspider.html)", "Baiduspider+(+http://www.baidu.com/search/spider_jp.html)", "Baiduspider+(+http://www.baidu.com/search/spider.htm)", "BaiDuSpider", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0) AddSugarSpiderBot www.idealobserver.com", ] DOWNLOADER_MIDDLEWARES = { "spider_douban.middlewares.RandomUserAgentMiddleware": 400, "scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware": None, }USER_AGENT_LIST定義了一些瀏覽器user-agent屬性,網(wǎng)上有很多,可以找來直接加進(jìn)去,需要注意的是有些user-agent信息是移動設(shè)備(手機(jī)或平板)的,如果不注意的話,可能請求到的數(shù)據(jù)與你看到的數(shù)據(jù)有較大差異;
middlewares.py
DOWNLOADER_MIDDLEWARES定義了下載器中間件,它在發(fā)送頁面請求數(shù)據(jù)的時候被調(diào)用。from spider_douban.settings import USER_AGENT_LIST import random class RandomUserAgentMiddleware(): def process_request(self, request, spider): ua = random.choice(USER_AGENT_LIST) if ua: request.headers.setdefault("User-Agent", ua)在RandomUserAgentMiddleware()中,每次發(fā)送請求數(shù)據(jù),會在USER_AGENT_LIST中隨機(jī)選擇一條User-Agent記錄。
5.結(jié)果保存編輯pipelines.py文件:
from scrapy import signals from scrapy.contrib.exporter import CsvItemExporter class SpiderDoubanPipeline(CsvItemExporter): def __init__(self): self.files = {} @classmethod def from_crawler(cls, crawler): print("==========pipeline==========from_crawler==========") pipeline = cls() crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) return pipeline def spider_opened(self, spider): savefile = open("douban_top250_export.csv", "wb+") self.files[spider] = savefile print("==========pipeline==========spider_opened==========") self.exporter = CsvItemExporter(savefile) self.exporter.start_exporting() def spider_closed(self, spider): print("==========pipeline==========spider_closed==========") self.exporter.finish_exporting() savefile = self.files.pop(spider) savefile.close() def process_item(self, item, spider): print("==========pipeline==========process_item==========") print(type(item)) self.exporter.export_item(item) return itemSpiderDoubanPipeline類是建立項(xiàng)目的時候自行建立的,為了保存文件,做了修改。
def from_crawler(cls, crawler):如果存在,則調(diào)用此類方法從Crawler創(chuàng)建pipeline實(shí)例。它必須返回一個新的pipeline實(shí)例。抓取對象提供對所有Scrapy核心組件的訪問,如settings和signals; 這是pipeline訪問它們并將其功能掛接到Scrapy的一種方式。
在此方法中,定義了一個數(shù)據(jù)收集器(cls)的實(shí)例:‘pipeline’。
signals:Scrapy使用信號來通知事情發(fā)生。您可以在您的Scrapy項(xiàng)目中捕捉一些信號(使用 extension)來完成額外的工作或添加額外的功能,擴(kuò)展Scrapy。雖然信號提供了一些參數(shù),不過處理函數(shù)不用接收所有的參數(shù) - 信號分發(fā)機(jī)制(singal dispatching mechanism)僅僅提供處理器(handler)接受的參數(shù)。您可以通過 信號(Signals) API 來連接(或發(fā)送您自己的)信號。
connect:鏈接一個接收器函數(shù)(receiver function) 到一個信號(signal)。signal可以是任何對象,雖然Scrapy提供了一些預(yù)先定義好的信號。
def spider_opened(self, spider):當(dāng)spider開始爬取時發(fā)送該信號。該信號一般用來分配spider的資源,不過其也能做任何事。該信號支持返回deferreds。
此方法中,創(chuàng)建了一個文件對象實(shí)例:savefile。
CsvItemExporter(savefile):輸出 csv 文件格式. 如果添加 fields_to_export 屬性, 它會按順序定義CSV的列名.
def spider_closed(self, spider):當(dāng)某個spider被關(guān)閉時,該信號被發(fā)送。該信號可以用來釋放每個spider在 spider_opened 時占用的資源。該信號支持返回deferreds。
def process_item(self, item, spider):每個item pipeline組件都需要調(diào)用該方法,這個方法必須返回一個 Item (或任何繼承類)對象, 或是拋出 DropItem 異常,被丟棄的item將不會被之后的pipeline組件所處理。
啟用pipeline為了讓我們定義的pipeline生效,要在settings.py文件中,打開ITEM_PIPELINES注釋:
ITEM_PIPELINES = { "spider_douban.pipelines.SpiderDoubanPipeline": 300, }6.執(zhí)行爬蟲scrapy crawl douban_movie_top250執(zhí)行爬蟲能夠看到爬取到的數(shù)據(jù)。。。
如果之前pipeline部分代碼沒有寫,也可以用下面的命令,在爬蟲執(zhí)行的時候直接導(dǎo)出數(shù)據(jù):
scrapy crawl douban_movie_top250 -o douban.csv增加-o參數(shù),可以將爬取到的數(shù)據(jù)保存到douban.csv文件中。。
7.文件編碼的問題我在linux服務(wù)器執(zhí)行爬蟲,生成csv文件后,在win7系統(tǒng)中用excel打開變成亂碼。在網(wǎng)上找了一些文章,有的文章直接改變linux文件默認(rèn)編碼,但是感覺這么做會對其他項(xiàng)目產(chǎn)生影響。最后選擇一個相對簡單的方式。按這幾步執(zhí)行就可以:
不要直接用excel打開csv文件。先打開excel,建立空白工作表。
選擇數(shù)據(jù)選項(xiàng)卡,打開獲取外部數(shù)據(jù)中的自文本。
在導(dǎo)入文本文件對話框中選擇要導(dǎo)入的csv文件。
在文本導(dǎo)入向?qū)?- 第1步中,設(shè)置文件原始格式為65001 : Unicode (UTF-8)
繼續(xù)下一步選擇逗號分隔,就可以導(dǎo)入正常文本了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/41418.html
相關(guān)文章
scrapy入門教程——爬取豆瓣電影Top250!
摘要:注意爬豆爬一定要加入選項(xiàng),因?yàn)橹灰馕龅骄W(wǎng)站的有,就會自動進(jìn)行過濾處理,把處理結(jié)果分配到相應(yīng)的類別,但偏偏豆瓣里面的為空不需要分配,所以一定要關(guān)掉這個選項(xiàng)。 本課只針對python3環(huán)境下的Scrapy版本(即scrapy1.3+) 選取什么網(wǎng)站來爬取呢? 對于歪果人,上手練scrapy爬蟲的網(wǎng)站一般是官方練手網(wǎng)站 http://quotes.toscrape.com 我們中國人,當(dāng)然...
scrapy入門:豆瓣電影top250爬取
摘要:本文內(nèi)容爬取豆瓣電影頁面內(nèi)容,字段包含排名,片名,導(dǎo)演,一句話描述有的為空,評分,評價人數(shù),上映時間,上映國家,類別抓取數(shù)據(jù)存儲介紹爬蟲框架教程一入門創(chuàng)建項(xiàng)目創(chuàng)建爬蟲注意,爬蟲名不能和項(xiàng)目名一樣應(yīng)對反爬策略的配置打開文件,將修改為。 本文內(nèi)容 爬取豆瓣電影Top250頁面內(nèi)容,字段包含:排名,片名,導(dǎo)演,一句話描述 有的為空,評分,評價人數(shù),上映時間,上映國家,類別 抓取數(shù)據(jù)存儲 ...
Java爬蟲之下載IMDB中Top250電影的圖片
摘要:介紹在博客爬蟲爬取豆瓣電影圖片中我們利用的爬蟲框架,將豆瓣電影圖片下載到自己電腦上。那么,在的爬蟲的也可以下載圖片嗎答案當(dāng)然是肯定的在本次分享中,我們將利用的包和函數(shù)來實(shí)現(xiàn)圖片的下載。 介紹 ??在博客:Scrapy爬蟲(4)爬取豆瓣電影Top250圖片中我們利用Python的爬蟲框架Scrapy,將豆瓣電影Top250圖片下載到自己電腦上。那么,在Java的爬蟲的也可以下載圖片嗎?答...
scrapy爬取豆瓣Top250電影
摘要:這次我們爬取的內(nèi)容準(zhǔn)備步驟找到格式網(wǎng)頁中需要爬取的數(shù)據(jù)的例如我們需要爬取圖片的這里用的是不會用的同學(xué)請百度然后我們開始建立工程打開然后在你想要建立工程的目錄下面輸入就會自動建立一個工程然后去根目錄建立一個去這個目錄里建立一個注意這里的主爬蟲 這次我們爬取的內(nèi)容 showImg(https://segmentfault.com/img/bVSirX?w=1021&h=521); 準(zhǔn)備步驟...
Python爬蟲之多線程下載豆瓣Top250電影圖片
摘要:本次爬蟲項(xiàng)目將會用到模塊中的類,多線程豆瓣電影圖片。總結(jié)通過上述兩個爬蟲程序的對比,我們不難發(fā)現(xiàn),同樣是下載豆瓣電影,個網(wǎng)頁中的圖片,在沒有使用多線程的情況下,總共耗時約,而在使用多線程個線程的情況下,總共耗時約秒,效率整整提高了約倍。 爬蟲項(xiàng)目介紹 ??本次爬蟲項(xiàng)目將爬取豆瓣Top250電影的圖片,其網(wǎng)址為:https://movie.douban.com/top250, 具體頁面如...
發(fā)表評論
0條評論
WalkerXu
男|高級講師
TA的文章
閱讀更多
Nextarray:美國vps/達(dá)拉斯vps,2核/1GB內(nèi)存/20GB SSD/不限流量/100M
閱讀 1015·2021-10-19 11:42
渾渾噩噩10年,入坑軟件測試,6年干到測試leader,非科班的我也能當(dāng)程序員!
閱讀 2972·2021-09-10 10:51
什么是接口測試?接口測試基礎(chǔ)、案例及Json格式詳解
閱讀 677·2021-09-09 09:33
#消息#Sharktech:推出云托管服務(wù),聯(lián)系客服可獲得$50,白嫖一個月4核/8G的服務(wù)器
閱讀 1760·2021-09-01 10:43
Web前端工程師應(yīng)該懂的的知識點(diǎn)——HTML/CSS
閱讀 2768·2019-08-30 12:43
css偽類選擇器
閱讀 3516·2019-08-30 11:24
CSS 深入理解:overflow: hidden——隱藏溢出、清除浮動、解除坍塌
閱讀 2114·2019-08-30 10:56
DIV 上下左右居中黑科技
閱讀 2777·2019-08-29 11:00