1. 程式人生 > >scrapy爬取CSDN論壇問題及內容

scrapy爬取CSDN論壇問題及內容

爬蟲相信大家都有所瞭解,我對爬蟲就不做詳細介紹了。本次我決定使用scrapy爬取CSDN論壇釋出的問題以及回答的內容。

首先,我們需要建立一個scrapy專案。

scrapy startproject test1

然後進入scrapy專案中,建立一個爬蟲。

#進入scrapy專案中
cd test1

#建立爬蟲
scrapy genspider csdn_spider  bbs.csdn.net

建立爬蟲時,前兩個引數是固定的,第三個引數是你要建立的爬蟲檔案的名字,第四個引數是你要爬取的網站的網址,此處我們先隨便寫上一個。四個引數缺一不可。

接下來我們開啟我們的專案,找到spider資料夾中我們剛建立的 'csdn_spider.py'檔案。下面我們就要開始我們的爬蟲專案了。

先對CSDN論壇進行分析,我們發現論壇的分頁是比較簡單的,每一頁的網址只有特定地方的數字變了一下。所以我們可以建立一個函式對論壇每一頁的url進行拼接。

#拼接url
def joint_url(url):
    # for i in range(1,101):
    #此處範圍可以先改小點進行測試,測試成功後可以再進行增大範圍的操作。
    return [url.format(i) for i in range(1,10)]

下面分析每一個問題的url。我們會發現每個問題的url是這樣的。

<a href="/topics/392451197" class="topic_title" target="_blank" title="關於讀取EXCEL出現亂碼的問題">關於讀取EXCEL出現亂碼的問題</a>

這個超連結是不完整的,所以我們需要再寫一個函式拼接問題的url。

#拼接各個問題的url
def question_url(url):
    #篩選出符合條件的url(只有滿足條件的才是問題的url)
    if '/topics' in url:
        return "https://bbs.csdn.net"+url
    else:
        return None

網址都得到了,那麼下面就可以爬取網頁,並分析網頁中我們想要得到的內容了。

下面就開始爬蟲的整個流程。

首先,確定要爬取的種子網頁。

因為我們設定了url拼接,所以我們的種子網頁是多個,這裡展示一下。

#匯入類庫
import scrapy
from scrapy import Request


class CsdnspiderSpider(scrapy.Spider):
    #爬蟲名字,用來啟動爬蟲
    name = 'csdn_spider'
    #過濾掉不滿足條件的網址
    allowed_domains = ['bbs.csdn.net']

    def __init__(self):
        #種子網址,與上面定義的拼接函式搭配使用。
        self.urls = 'https://bbs.csdn.net/forums/OL_Script?page={}'

    此處函式名必須是start_requests
    def start_requests(self):
        #迴圈訪問每一頁
        for url_str in joint_url(self.urls):
            #迭代器,引數1:訪問網站url,引數2:回撥函式,函式名必須是parse    
            yield Request(url=url_str,callback=self.parse)

獲得返回的網頁內容後,對內容進行篩選

    #此處函式名必須是parse
    def parse(self, response):
        """
        提取每一頁中的問題
        :param response:
        :return:
        """
        #使用xpath,匹配出問題的連結
        all_title_urls = response.xpath('//td[@class="forums_topic"]/a/@href').extract()

        for one_title in all_title_urls:
            #完整的每個問題的url
            full_url = question_url(one_title)
            if full_url:
                #下面的回撥函式函式名可以是其他的,只有第一個回撥函式名必須是parse。
                yield Request(url=full_url,callback=self.question)

此時,我們需要找到 'item.py'檔案,它的作用就跟Django中 'models.py' 相同。然後在裡面輸入以下程式碼。


class CsdnspiderItem(scrapy.Item):
    title = scrapy.Field()
    content = scrapy.Field()

接下來回到 'csdn_spider.py' 檔案中,首先在最上方需要匯入剛才建立的類。

from test1.items import CsdnspiderItem

再對每一個問題網址裡面的內容進行篩選。

 def question(self,response):
        """
        提取每個問題中的回答內容
        :param response:
        :return:
        """
        # print(response.body)
        try:
            one_question_title = response.xpath('//span[@class="title text_overflow"]/text()').extract()
            one_question_title = one_question_title[0]
        except:
            one_question_title = 'none'
        try:
            one_question_contents = response.xpath('//div[@class="post_body post_body_min_h"]/text()').extract()
        except:
            one_question_contents = 'none'
        contents_str = ''
        for i in one_question_contents:
            contents_str += i

        contents_str = ' '.join(contents_str.split())
        item = CsdnspiderItem()
        item["title"] = one_question_title
        item["content"] = contents_str
        yield item

資料現在已經有了,那麼我們把資料存到哪裡呢?不要著急,scrapy已經為我們考慮到了。開啟 'piplines.py' 檔案,在這裡,我們將進行我們的資料庫儲存操作。這裡我們使用sqlite資料庫。

import sqlite3

class CsdnspiderPipeline(object):
    def __init__(self):
        self.conn = sqlite3.connect('./../csdn.db')
        self.cur = self.conn.cursor()
         self.cur.execute(
            "create table IF NOT EXISTS infos(id integer primary key autoincrement, question text,answer text);")
        self.conn.commit()

    def process_item(self, item, spider):
        self.cur.execute('insert into infos(question,answer) values(?,?)',[item['title'],item['content']])
        self.conn.commit()
        return item

注意,我們還需要去'setting.py'檔案中設定一下才可以使用。

ITEM_PIPELINES = {
   'test1.pipelines.CsdnspiderPipeline': 300,
}

下面,我們在終端中輸入 ‘scrapy crawl csdn_spider’就可以執行爬蟲了。

有的時候,這樣容易被封掉,我們可以使用瀏覽器模擬的操作,找到 ‘middlewares.py’ 檔案,這時scrapy的中介軟體,我們在這裡寫瀏覽器模擬的類。

from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options as FOptions

class SeleniumMiddleware(object):
    def __init__(self):
        self.options = FOptions()
        self.options.add_argument('-headless')  # 無頭模式
        self.browser = webdriver.Firefox(executable_path='E:\FireFox\geckodriver\geckodriver.exe',
                                         firefox_options=self.options)

    def process_request(self,request,spider):
        try:
            print("url is ::::::",request.url)
            self.browser.get(request.url)
        except TimeoutException as e:
            print("超時")
        time.sleep(2)
        return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,
                            encoding="utf-8",request=request)

然後再 'setting.py' 中設定

DOWNLOADER_MIDDLEWARES = {
   'test1.middlewares.SeleniumMiddleware': 543,
}

瀏覽器模擬需要用到的東西,在我的瀏覽器模擬的那個部落格中有講到,這裡就不過多講了。

現在算是一個比較完整的爬蟲專案了。總的來說,比較簡單,適合初學者入門學習。