新手學習爬蟲之創建第一個完整的scrapy工程-糗事百科


創建第一個scrapy工程-糗事百科

最近不少小伙伴兒,問我關於scrapy如何設置headers的問題,時間久了不怎么用,還真有的忘,全靠記憶去寫了,為了方便大家參考,也方便我以后的查閱,這篇文章就誕生了。本章內容從實戰出發讓我們熟悉如何用scrapy寫爬蟲,本篇內容主要是實戰,不講述過多的理論性東西,因為講多了我也不知道。😄

明確目標

首先,我們要明確我們的爬蟲最終的目的是什么,這里我們要做的是爬取糗事百科的熱門分類的前10頁信息。包括發布者和內容,因為入門教程所以我們寫的簡單點主要是熟悉這個過程,這個如何入手呢?

分析鏈接的變化

一般我們會通過點擊下一頁,然后觀察地址欄的信息來總結規律。
第一頁也就是首頁地址為:https://www.qiushibaike.com/
我們點擊下一頁可以發現第二頁的的連接為:https://www.qiushibaike.com/8hr/page/2/
第三頁:https://www.qiushibaike.com/8hr/page/3/
。。。以此類推第十頁的連接為:https://www.qiushibaike.com/8hr/page/10/
由此我們發現規律,從第二頁開始連接可以用https://www.qiushibaike.com/8hr/page/頁數/來表示,有時候我比較喜歡試探,怎么說呢,我們知道這個規律是從第二頁開始的,但是第一頁是沒有這個規律,但是我們不防試一試把第一頁的https://www.qiushibaike.com/改為https://www.qiushibaike.com/8hr/page/1/。然后我們訪問看看ok可以正常顯示。


於是我們就確定了鏈接,也就是頁數改為1-10就可以訪問相應的頁數了。

 

安裝scrapy

我們要確保正確安裝好了scrapy
針對mac和linux直接運行pip安裝即可。

pip install scrapy

但是windows的坑就比較多了,關於windows的安裝請參考我之前寫的這篇文章
:https://www.cnblogs.com/c-x-a/p/8996716.html。這里就不多說了。

創建scrapy工程

好了下面我們開始創建工程首先我們使用scrapy的第一個命令startproject,
使用方法:scrapy startproject xxx xxx就是你的項目名,這里我們給我們的項目起名qiushibaike。

 scrapy startproject qiushibaike

然后我們會發現了多了一個文件名為qiushibaike的文件夾
然后我們通過命令創建一個事例工程
進入qiushibaike

 

cd qiushibaike

然后用下面scrapy的第二個命令genspider
使用方法 scrapy genspider spider_name domain
spider_name就是爬蟲的名字,每一個爬蟲有一個名字這個名字是唯一的,后面運行的時候也是通過這個名字來運行的,下面的qsbk就是我們的爬蟲名字,domain指定爬蟲的域也就是爬蟲的范圍。查找網頁我們發現域名為

scrapy genspider qsbk qiushibaike.com

看到以下命令證明我們成功的創建了項目。

Created spider 'qsbk' using template 'basic' in module:
  qiushibaike.spiders.qsbk

開始編寫spider文件

我們這里使用pycharm把我們的爬蟲工程加載進來。
目錄結構如下


(注意:run.py是我后期自己添加的一個爬蟲入口文件)

 

修改settings.py文件

無視robots協議,將

ROBOTSTXT_OBEY = True

改為

ROBOTSTXT_OBEY = False

修改spider.py

我們先來看看我們訪問的網頁源碼對不對。
把qsbk.py 改為

# -*- coding: utf-8 -*-
import scrapy


class QsbkSpider(scrapy.Spider):
    name = 'qsbk'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['http://qiushibaike.com/']#種子url,列表類型表示支持多個

    def parse(self, response):
        print(response.text)#輸出源碼

創建入口文件運行

在項目的根目錄下創建一個run.py 來運行我們的工程
run.py的內容如下

# -*- coding: utf-8 -*-
@Time : 2018/10/31 11:54 PM
@Author : cxa
@File : run.py.py
@Software: PyCharm
from scrapy.cmdline import execute
execute(['scrapy','crawl','qsbk'])

運行以后我們發現一堆紅色的信息,這些都是scrapy 的日志內容,我們注意找是否有黑色字體的內容,一般print出來的內容是黑色字體和含有error的信息,以此了解我們的爬蟲哪個地方出錯了,


我們找到了error關鍵字,可以得知我們的爬蟲出錯了

 

2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retryDEBUG: Retrying <GET https://www.qiushibaike.com/> (failed 1 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]
2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retryDEBUG: Retrying <GET https://www.qiushibaike.com/> (failed 2 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]
2018-11-01 00:08:38 [scrapy.downloadermiddlewares.retryDEBUG: Gave up retrying <GET https://www.qiushibaike.com/> (failed 3 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]
2018-11-01 00:08:39 [scrapy.core.scraper] ERROR: Error downloading <GET https://www.qiushibaike.com/>
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/scrapy/core/downloader/middleware.py", line 43in process_request
    defer.returnValue((yield download_func(request=request,spider=spider)))
twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed \

按照提示可以知道鏈接被關閉訪問失敗了,這種情況下我們就被反爬了,常見的應對措施是修改headers頭,下面我們就通過修改中間件來修改headers。

修改中間件加入headers信息

首先修改middlewares.py

class UserAgentMiddleware(object):

    def __init__(self, user_agent_list):
        self.user_agent = user_agent_list

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        # 獲取配置文件中的MY_USER_AGENT字段
        middleware = cls(crawler.settings.get('MY_USER_AGENT'))
        return middleware

    def process_request(self, request, spider):
        # 隨機選擇一個user-agent
        request.headers['user-agent'] = random.choice(self.user_agent)

然后在settings啟用我們的中間件和設定MY_USER_AGENT的值:

MY_USER_AGENT = ["Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36",
    "Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/28.0.1500.95+Safari/537.36+SE+2.X+MetaSr+1.0",
    "Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/50.0.2657.3+Safari/537.36"]

DOWNLOADER_MIDDLEWARES = {
   'qiushibaike.middlewares.UserAgentMiddleware': 543,
}

然后我們再次運行,run.py文件。

再次運行

我們成功獲取了源碼,


。然后我們就需要進行解析內容了。

 

解析網頁中所需要的內容

因為這10頁的結構是類似的我們就拿第一頁為例:
在這里我們使用的解析方法為xpath,通過xpath可以解析出我們需要的內容,
打開谷歌瀏覽器的開發者工具,首先通過Elements模塊獲取當前頁所有內容的大概區域我們可以寫這樣的一個xpath。

"//div[@id='content-left']"

然后我們發現一頁25個內容,然后再去在每個內容里進行查找當前的標題和內容。
在qsbk.py文件的parse方法里加入這段內容

 content_left_node=response.xpath("//div[@id='content-left']"#確定發布區的節點區域
        div_node_list=content_left_node.xpath("./div")
        for div_node in  div_node_list:
            title_node=div_node.xpath(".//div[@class='author clearfix']/a[contains(@onclick,'web-list-author-text')]/h2/text()")
            content_node=div_node.xpath(".//div[@class='content']/span[1]")
            content=content_node.xpath('string(.)')
            print("發布者",title_node.extract_first().strip())
            print("發布內容",content.extract_first().strip())

修改scrapy的日志顯示等級方便查看

前面運行過程中我們發現scrapy的日志信息非常的多,不容易找到我們想要的內容,這個時候我們可以通過修改settings.py文件通過修改log的等級,只顯示指定類型的log,打開settings.py我們加上下面的一句來設定log的等級為error
也就是只有錯誤的時候才顯示scrapy的log信息。

LOG_LEVEL = "ERROR"

然后再次運行,看到了我們我們需要的內容發布者和發布內容。
得到了這些我們現在只是打印了下,下面我們就來說如何存儲

保存結果到mongodb

mongodb是一個key-value型的數據庫,使用起來簡單,數據結構是鍵值對類型,在存儲過程中如果表不存在就會創建一個新的表。
下面我們開始來存儲我們的數據。

構造數據

因為我們需要接收一個鍵值對類型的數據,一般用dict,所以我們將代碼改成如下形式。qsbk.py文件新增內容:

            item = {}
            item['name'] = name
            item['info'] = info
            yield item

上面我們構造出了我們需要存儲的數據,然后通過yield傳遞到存儲部分,
下一步我們就要開始創建mongo連接的部分了。

創建mongo連接文件

把pipelines.py 文件改為

import pymongo
from scrapy.conf import settings

class MongoPipeline(object):
    def __init__(self):
        # 鏈接數據庫
        self.client = pymongo.MongoClient(host=settings['MONGO_HOST'], port=settings['MONGO_PORT'])
        if settings.get('MINGO_USER'):
               self.client.admin.authenticate(settings['MINGO_USER'], settings['MONGO_PSW'])
        self.db = self.client[settings['MONGO_DB']]  # 獲得數據庫
        self.coll = self.db[settings['MONGO_COLL']]  # 獲得collection

    def process_item(self, item, spider):
        postItem = dict(item)  # 把item轉化成字典形式
        self.coll.insert(postItem)  # 向數據庫插入一條記錄
        return item 

然后修改settings.py,首先添加mongo的幾個連接參數

MONGO_HOST = "127.0.0.1"  # 主機IP
MONGO_PORT = 27017  # 端口號
MONGO_DB = "spider_data"  # 庫名
MONGO_COLL = "qsbk"  # collection名

然后打開pipe通道

ITEM_PIPELINES = {
   'qiushibaike.pipelines.MongoPipeline': 300,
}

運行查看數據

我這里用的adminmongo,打開adminmogo連接數據庫,可以看到我們數據已經存在了。

結語

到此為止,我們一個簡單完整的scrapy小項目就完成了。 為了方便查看代碼已經上傳git:https://github.com/cxapython/qsbk.git
更多爬蟲學習以及python技巧,請關注公眾號:python學習開發。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM