Scrapy 學習手記

Scrapy蕾羊,Python開發(fā)的一個快速侮叮、高層次的屏幕抓取和web抓取框架避矢,用于抓取web站點并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù)。Scrapy用途廣泛,可以用于數(shù)據(jù)挖掘审胸、監(jiān)測和自動化測試亥宿。--網(wǎng)絡介紹

羅列推薦看的網(wǎng)址:

按教程安裝完(這里推薦且只推薦使用conda方式安裝砂沛,而非其它烫扼,諸如pip)后,常用的命令:

scrapy startproject projectName
scrapy genspider spiderName "xxx.html"
scrapy crawl spiderName
scrapy shell "url"

整體而言碍庵,要做的就是:先設計自己要爬取的item的結(jié)構(gòu)體(items.py)映企,同時設計對應的spider.py,在爬蟲代碼中静浴,將爬到的內(nèi)容填入item的字段后堰氓,將item交給pipeline處理,pipeline將這些爬取到的數(shù)據(jù)存儲到文件苹享,或者是數(shù)據(jù)庫中双絮。
具體流程也一并給出如下:

  1. 爬蟲引擎獲得初始請求開始抓取。
  2. 爬蟲引擎開始請求調(diào)度程序得问,并準備對下一次的請求進行抓取掷邦。
  3. 爬蟲調(diào)度器返回下一個請求給爬蟲引擎。
  4. 引擎請求發(fā)送到下載器椭赋,通過下載中間件下載網(wǎng)絡數(shù)據(jù)。
  5. 一旦下載器完成頁面下載或杠,將下載結(jié)果返回給爬蟲引擎哪怔。
  6. 引擎將下載器的響應通過中間件返回給爬蟲進行處理。
  7. 爬蟲處理響應向抢,并通過中間件返回處理后的items认境,以及新的請求給引擎。
  8. 引擎發(fā)送處理后的 items 到項目管道挟鸠,然后把處理結(jié)果返回給調(diào)度器叉信,調(diào)度器計劃處理下一個請求抓取。
  9. 重復該過程(繼續(xù)步驟1)艘希,直到爬取完所有的 url 請求硼身。

建立爬蟲項目之后,給出爬蟲代碼模板覆享,第一個代碼是最基本的爬蟲佳遂,但是,這份代碼實在是太簡單了撒顿,只能爬一兩個頁面丑罪,如果是要爬多頁數(shù)據(jù),頁里又有多條數(shù)據(jù),可以下面的第二份代碼:

"""第一份代碼"""
import scrapy
class QuotesSpider(scrapy.Spider):
    name = "quotes"
    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = 'quotes-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s' % filename)

"""第二份代碼"""
class MySpider(scrapy.Spider):
    name = 'myspider'
    def start_requests(self):
        urls = ['https://www.xxx.com']
        for url in urls:
            yield scrapy.Request(url=url, callback=self.url_parse)

    def url_parse(self, response):
        """
        url_parser目的是獲取目錄頁面上一個個頁面的網(wǎng)址
        """
        urls = response.xpath('...')
        for url in urls:
            # 對每個頁面進行數(shù)據(jù)提取
            yield scrapy.Request(url, callback=self.data_parse)

        next_page = response.xpath('...').get()
        if next_page is not None:
            yield response.follow(next_page, callback=self.url_parse)


    def data_parse(self, response):
        """
        從最終的頁面獲取數(shù)據(jù)
        """
        data = response.xpath('...')
        l = ItemLoader(item=MyItem(), response=response)
        l.add_value('data', data)
        yield l.load_item()

其中name即當前爬蟲的名稱吩屹,也是今后啟動它的唯一標識跪另。爬蟲回自動執(zhí)行start_requests(self)函數(shù),按代碼對url發(fā)起請求煤搜,這是比較自定義的形式免绿。如果為了偷懶,也可以不重寫start_requests()宅楞,而是用下面這份代碼來代替:

name = "quotes"
start_urls = [
    'http://quotes.toscrape.com/page/1/',
    'http://quotes.toscrape.com/page/2/',
]

這些就不贅述针姿。總的來說厌衙,start_urls負責發(fā)起請求距淫,請求之后的結(jié)果,會放入response函數(shù)中婶希,并運行parse(self, response)函數(shù)榕暇,我們的目的就是從response中,利用各種解析工具喻杈,比如css或者xpath或者正則表達式來提取內(nèi)容彤枢,提取之后,可以放入自定義的item筒饰,丟入pipeline來持久化(比如存入數(shù)據(jù)庫)缴啡,也可以直接parse完寫入文件。

先在items.py 定義自己想要的item:

import scrapy
class Product(scrapy.Item):
    name = scrapy.Field()
    price = scrapy.Field()
    stock = scrapy.Field()
    last_updated = scrapy.Field(serializer=str)

然后在spider中將item_load到pipeline中:

from scrapy.loader import ItemLoader
from myproject.items import Product

l = ItemLoader(item=Product(), response=response)
l.add_value('name', response.xpath('...'))
l.add_value('price', response.xpath('...'))
l.add_value('stock', response.xpath('...'))
l.add_value('last_updated', response.xpath('...'))
yield l.load_item()

那么就需要在pipelines.py中實現(xiàn)對這些items的處理的pipeline瓷们,對于不同的spider业栅,可以用它們的name來進行區(qū)分處理:

class MyPipeline(object):
    def open_spider(self, spider):
        if spider.name == 'spider1':
            self.file = open('file1.txt', 'a+')
       elif spider.name == 'spider2':
            self.file = open('file2.txt', 'a+')

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + '\n'
        self.write(line)
        return item

    def close_spider(self, spider):
        self.file.close()

最后在settings.py中注冊這個pipeline,讓其真正投入生產(chǎn)線:

ITEM_PIPELINES = {
   'myproject.pipelines.MyPipeline': 300,
}

這里規(guī)定的數(shù)字谬晕,決定了組件運行的順序碘裕,數(shù)字越小,越先執(zhí)行攒钳。

實踐相關問題:

可以參考這里
常見的有防止被目標網(wǎng)站禁止(ban):

  • 使用user agent池帮孔,輪流選擇之一來作為user agent。
  • 禁止cookies(參考settings.py的COOKIES_ENABLED)不撑,有些站點會使用cookies來發(fā)現(xiàn)爬蟲的軌跡文兢。
  • 設置下載延遲(2或更高)。參考DOWNLOAD_DELAY設置焕檬。
  • 如果可行禽作,使用Google cache來爬取數(shù)據(jù),而不是直接訪問站點揩页。
  • 使用IP池旷偿。例如免費的 Tor項目 或付費服務ProxyMesh烹俗。
  • 使用高度分布式的下載器(downloader)來繞過禁止(ban),您就只需要專注分析處理頁面萍程。這樣的例子有: Crawlera

其中幢妄,設置隨機請求頭的問題,這個問題非常建議參考博文:一行代碼搞定Scrapy的隨機UserAgent
簡而言之茫负,只需兩步:

  • pip安裝模塊 pip install scrapy-fake-useragent
  • 在settings.py加入這個模塊蕉鸳,讓它進行UserAgent的自動設置。
DOWNLOADER_MIDDLEWARES = {
     # 關閉默認的UA方法忍法,并開啟自己的UA方法
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 
    'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400,  
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末潮尝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饿序,更是在濱河造成了極大的恐慌勉失,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件原探,死亡現(xiàn)場離奇詭異乱凿,居然都是意外死亡,警方通過查閱死者的電腦和手機咽弦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門徒蟆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人型型,你說我怎么就攤上這事段审。” “怎么了闹蒜?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵戚哎,是天一觀的道長。 經(jīng)常有香客問我嫂用,道長,這世上最難降的妖魔是什么丈冬? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任嘱函,我火速辦了婚禮,結(jié)果婚禮上埂蕊,老公的妹妹穿的比我還像新娘往弓。我一直安慰自己,他們只是感情好蓄氧,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布函似。 她就那樣靜靜地躺著,像睡著了一般喉童。 火紅的嫁衣襯著肌膚如雪撇寞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音蔑担,去河邊找鬼牌废。 笑死,一個胖子當著我的面吹牛啤握,可吹牛的內(nèi)容都是我干的鸟缕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼排抬,長吁一口氣:“原來是場噩夢啊……” “哼懂从!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蹲蒲,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤番甩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悠鞍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體对室,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年咖祭,在試婚紗的時候發(fā)現(xiàn)自己被綠了掩宜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡么翰,死狀恐怖牺汤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浩嫌,我是刑警寧澤檐迟,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站码耐,受9級特大地震影響追迟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骚腥,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一敦间、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧束铭,春花似錦廓块、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至懈万,卻和暖如春拴清,著一層夾襖步出監(jiān)牢的瞬間靶病,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工贷掖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫡秕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓苹威,卻偏偏與公主長得像昆咽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牙甫,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359