scrapy爬蟲初步嘗試

一、scrapy環境的搭建

  1. python版本:python3.5.3
  2. python IDE:pycharm
  3. 用到python庫:virtualenv,virtualenvwrapper,scrapy

下面開始詳細的講解環境搭建的過程,在python3中搭建scrapy爬蟲環境在搭建過程當中,可能會遇到不少問題,因此建議仍是在linux下面去進行爬蟲。css

  • 一、安裝python、pycharm
  • 二、pip install virtualenv virtualenvwrapper這裏,可能使用pip會不成功,那麼須要先安裝pip
  • 三、在安裝完virtualwrapper後,能夠經過添加WORK_ON環境變量,將你的虛擬環境路徑配置進去。以後,即可以使用mkvirtualenv xxxx。建立一個虛擬環境。而後,經過workon,查看你全部的虛擬環境,經過workon XXX進入該虛擬環境。
  • 四、安裝scrapy。這裏很容易出各類錯誤,由於scrapy依賴了不少庫。可能出現的錯誤有
  • 一、timeout。這通常是網絡緣由。因此建議使用鏡像。pip install -i htttps://pypi.douban.com/simple scrapy
  • 二、lxml錯誤。推薦一個網址很重要,裏面有不少Python的libs,注意按照版本下載
  • 三、若是是python2安裝的話,可能會出現vc++9.0 required,若是是3.5.3版本會出現vc++14.0 required錯誤。兩種解決辦法,一、根據cmd中的錯誤提示,去對應連接中下載vc++ for python;還有一個就是去(2)中的那個網站中下載Twisted.whl文件進行安裝,安裝方法是要進入要對應的虛擬環境,而後,去下載文件的目錄中執行pip install 文件名進行安裝。

###2.構建一個scrapy項目python

  • 在上面的安裝成功後,就能夠開始建立一個scrapy項目了。在pycharm中是不能建立一個scrapy項目的。因此,仍是須要在命令窗口進行建立。(全部的操做要在對應的虛擬環境中進行。)linux

    • 一、在電腦中新建一個存放工程的目錄,在命令行中進入這個工程目錄。
    • 二、輸入 scrapy startproject XXXX(項目名)。這樣就建立好了一個scrapy項目。
    • 三、這時候,命令行會提示你,如何去新建一個spider。1.進入項目;2.scrapy genspider example example.com。其中,example,表示spider的名字,example.com就是startulr。完了,你就能夠在pycharm打開你的項目,而且配置interpreters(虛擬環境->lib->python.exe)。模板代碼以下。
# -*- coding: utf-8 -*-
import scrapy
class JobboleSpider(scrapy.Spider):
   name = "jobbole"
   allowed_domains = ["blog.jobbole.com"]
   start_urls = ['http://blog.jobbole.com/111016/']
   def parse(self, response):
       pass

咱們要寫的代碼也主要是parse函數。c++

3.關於scrapy項目的debug

  1. 怎麼樣啓動spider?怎麼樣在pycharm中能夠跟進咱們的spider?

首先,關於spider的啓動,能夠在命令窗口中輸入 scrapy crawl XXX(spider的名字)。可是,怎麼樣在pychram中進行啓動而且調試這裏須要利用到scrapy本身的一個excute方法。我採用的是新建一個main.py文件進行spider的啓動。上代碼:正則表達式

# -*- coding:utf-8 -*-
__author__ = "sucan"
__time__ = "2017/5/7"
#該py的主要功能是爲了讓程序可以debug scrapy工程
from scrapy.cmdline import execute
import sys
import os
#添加工程目錄
#os.path.abspath(__file__):得到當前文件
#os.path.dirname():得到當前文件的父目錄
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
#至關於在cmd中執行 scrapy crawl jobbole(啓動spider)
execute(["scrapy","crawl","jobbole"])

執行main文件就能夠啓動spider,同時,若是在spider文件中的parse方法中打斷點,也是能夠進去的。這樣的話,每次調試,都須要執行一次main,而且訪問一次url。其實scrapy自己也是提供了scrapy shell用於咱們調試,輸出。只須要執行scrapy shell XXX(url),便可。在上述的某過程當中,可能出現缺乏win32api的錯誤。不要怕,只須要pip install pypiwin32就好。shell

4.開始進行爬取

  1. 爬取中,我使用的主要是根據xpath語法,進行爬取。獲取xpath的方法不少,本身能夠經過觀察獲得合適的xpath,能夠從瀏覽器複製。
  2. 爬取前,我建議你們,去把settings中的ROBOTSTXT_OBEY參數設置爲False。
  3. 這裏,我主要是針對伯樂在線的文章進行爬取。爬取的內容主要是文章標題,內容,建立日期,評論數,點贊數,收藏數,以及相關tags。
# -*- coding: utf-8 -*-
import scrapy
import re
from scrapy.http import Request
from urllib import parse
class JobboleSpider(scrapy.Spider):
    name = "jobbole"
    allowed_domains = ["blog.jobbole.com"]
    start_urls = ['http://blog.jobbole.com/all-posts/']
    def parse(self, response):
        '''
        一、在文章列表頁中取到全部的文章url,交給scrapy下載後進行解析
        二、找到下一頁的url並交給scrapy進行下載,下載完成後parse
        :param response: 
        :return: 
        '''
        #在文章列表頁中取到全部的文章url,交給scrapy進行下載後進行解析
        post_urls = response.css("#archive .floated-thumb .post-thumb a::attr(href)").extract()
        for post_url in post_urls:
            yield Request(url=parse.urljoin(response.url,post_url),callback=self.parse_detail)
        #取到下一頁的url交給scrapy進行下載,下載完以後進行parse
        next_url = response.css(".next.page-numbers::attr(href)").extract_first("")
        if next_url:
            yield Request(url=next_url,callback=self.parse)
        pass
    def parse_detail(self,response):
        # 文章標題(這裏有一個小細節,使用extract_first(""),由於若是用extract()[0]可能數組越界報錯)
        title = response.xpath('//div[@class="entry-header"]/h1/text()').extract_first("")
        # 文章建立日期
        create_date = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/text()').extract_first(
            "").strip().replace("·", "").strip()
        # 文章點贊數
        praise_num = int(response.xpath("//span[contains(@class,'vote-post-up')]/h10/text()").extract_first(""))
        # 文章收藏數
        mark_num = response.xpath("//span[contains(@class,'bookmark-btn')]/text()").extract_first("")
        # 在上面取到的mark_num = 1 收藏。而咱們只須要1,因此要利用正則表達式進行過濾
        re_obj = re.match(".*?(\d+).*", mark_num)
        if re_obj:
            mark_num = int(re_obj.group(1))
        else:
            mark_num = 0
        # 文章評論數
        comments_num = response.xpath("//a[@href='#article-comment']/span/text()").extract_first("")
        re_obj = re.match(".*?(\d+).*", comments_num)
        if re_obj:
            comments_num = int(re_obj.group(1))
        else:
            comments_num = 0
        # 文章內容
        content = response.xpath("//div[@class='entry']").extract_first("")
        # 文章tags(分類等)
        tag_list = response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
        tags = ",".join(tag_list)

附帶使用css選擇器提取元素api

#使用css選擇器,提取元素
        title = response.css(".entry-header h1::text").extract()[0]
        create_date = response.css("p.entry-meta-hide-on-mobile::text").extract()[0].strip().replace("·","").strip()
        praise_num = int(response.css("span.vote-post-up h10::text").extract()[0])
        mark_num = response.css(".bookmark-btn::text").extract()[0]
        re_obj = re.match(".*?(\d+).*", mark_num)
        if re_obj:
            mark_num = int(re_obj.group(1))
        comments_num = response.css("a[href='#article-comment'] span::text").extract()[0]
        re_obj = re.match(".*?(\d+).*", comments_num)
        if re_obj:
            comments_num = int(re_obj.group(1))
        tag_list = response.css("p.entry-meta-hide-on-mobile a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
        tags = ','.join(tag_list)
相關文章
相關標籤/搜索