1. 程式人生 > >通過scrapy實現簡單爬蟲

通過scrapy實現簡單爬蟲

Scrapy概述

網路爬蟲,大概很多人都聽說過吧。
它是通過一定的規則,自動抓取網際網路網站上的文章、資訊、圖片等等內容。
常見的應用就是搜尋引擎。

而Scrapy則是實現網路爬蟲的方式之一。

官方描述的Scrapy是一個為了爬取網站資料,提取結構性資料而編寫的應用框架。
可以應用在包括資料探勘,資訊處理或儲存歷史資料等一系列的程式中。

Scrapy安裝配置

Scrapy是需要配置Python環境的。所以我們先通過pycharm新建一個project。
配置git
然後安裝環境:

pip install scrapy

pycharm並不支援直接建立scrapy的project,所以我們需要手動建立:

scrapy startproject SpiderProject

建立模板

scrapy提供了命令讓我們可以根據模板建立spider,這個命令就是genspider
genspider可以直接建立spider的模板,比如我們爬www.ttsla.com

scrapy genspider ttsla www.ttsla.com

可以通過scrapy genspider -h 檢視相關幫助
我們也可以通過scrapy genspider -l 檢視可用模板

如果是windows下還需要裝個win32模組:

pip install -i https://pypi.douban.com/simple pypiwin32

除錯執行

在命令列中除錯選擇器:

scrapy shell www.ttsla.com

這樣我們就可以很方便的在命令列中通過response.css除錯選擇器,並把正確的除錯結果copy到程式碼中。

實現簡單的爬蟲功能需要改三個檔案:

settings.py
items.py
ttlsa.py

settings.py下需要設定ROBOTSTXT_OBEY,否則會過濾掉不符合ROBOTS協議的url:

ROBOTSTXT_OBEY = False

settings.py中還需要配置ITEM_PIPELINES,這一段程式碼預設是禁用的:

ITEM_PIPELINES = {
   'ttlsaSpider.pipelines.TtlsaspiderPipeline': 300,
}

item.py中定義爬蟲爬取結果的結構,可以定義多個,比如標題定義類似於這種:

class TtlsaspiderItem(scrapy.Item):
    title = scrapy.Field()

ttlsa.py這個是我自定義的蜘蛛的名字,名字也可以是其他的,我這裡只是示例。
如果我們之前執行了建立模板的命令,系統會自動生成這個檔案。

其中的parse函式需要自己來寫。要注意相互呼叫的關係。比如最簡單的:

    def parse(self, response):
        item = TtlsaspiderItem()
        nodes = response.css(".entry-header .entry-title a")
        item['標題'] = nodes.css("::text").extract()
        yield item

注意在定義start_urls的時候,要配置好完整的url路徑:

start_urls = ['http://www.ttlsa.com']

配好這三個檔案,我們就可以scrapy crawl ttlsa -o result.csv來跑一下,
會自動生成一個csv檔案
開啟csv檔案來驗證結果。

取資料

通過網站的頁面取資料有兩種方法:xpath和css。
這兩種取資料的方式各有優缺點,可以根據實際情況來分別應用。
通過xpath取出資料,示例如下:

title = response.xpath('//*[@class="grid-8"]/div[1]/div[1]/h1/text()').extract()

通過css取資料,示例如下:

title = response.css(".entry-header .entry-title a::text").extract()

response.xpath會返回一個SelectorList物件,extract後會把selector物件轉換成list型別
如果取出來是一個list,可以通過selector[0]取出值.
xpath的值可以通過chrome瀏覽器的F12的除錯功能找,然後把xpath複製出來。

下面是複雜一些的,取日期,其實方法是一樣的:

date = response.xpath("//*[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·", "").strip()

strip()方法是去空格和換行符;replace()方法是替換。

contains,我們加上contains,就是class中包含了‘vote-post-up’這個字串就匹配了,程式碼如下:

response.xpath("//*[contains(@class, 'vote-post-up')]")

通常這種用法適合class包含了多個字串的時候進行匹配。

有些時候需要通過正則來匹配,以下程式碼我們用xpath通過正則過濾掉了中文,只保留數字:

comments_nums = response.xpath("//a[contains(@href, '#article-comment')]/span/text()").extract()[0].strip()
match_re = re.match(".*?(\d+).*", comments_nums)
if match_re:
    comments_nums = match_re.group(1)

為了方便除錯,我們可以自定義一個main.py,效果和命令列裡輸入命令是一樣的:

from scrapy.cmdline import execute

execute(['scrapy', 'crawl', 'ttlsa'])

export

資料生成以後我們可以匯出。我們需要修改pipelines.py的檔案,可以通過pipeline將資料儲存到json或資料庫等。
Json的匯出可以自定義方法,也可以使用自帶的JsonItemExporter方法:

#使用scrapy內建JsonItemExporter的方法輸出json
class JsonItemExporterPipeline(object):
    def __init__(self):
        self.file = open("result.json", "wb")
        self.export = JsonItemExporter(self.file, ensure_ascii=False, encoding='utf8')
        self.export.start_exporting()

    def close_spider(self):
        self.export.finish_exporting()

    def process_item(self, item, spider):
        self.export.export_item(item)
        return item

匯出到資料庫的方法也是類似的,我們以MySQL為例。我們首先需要裝個mysqlclient
提供一個連結:
https://www.lfd.uci.edu/~gohlke/pythonlibs/#
這裡有非常多適配windows的python庫,搜一下mysql就能找出來,然後直接pip install
注意cp35代表python3.5的版本,win32代表32位的系統。
然後裝mysql建庫建表就不說了,我是直接用docker建庫。建好表以後,可以增加設定一個id欄位作為自增欄位。
編寫pipelines.py,新增自定義類,我這裡就只兩個欄位:

class MysqlPipelines(object):
    def __init__(self):
        self.conn = MySQLdb.connect(host="192.168.99.100", user="root", passwd="root", port=3316, db="article_spider", charset="utf8", use_unicode=True)
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):
        insert_sql = """insert into ttlsa (title, url) values (%s, %s)"""
        self.cursor.execute(insert_sql, (item["title"], item["url"]))
        self.conn.commit()

注意修改settings.py裡的配置檔案

執行main.py除錯。