下面開始詳細的講解環境搭建的過程,在python3中搭建scrapy爬蟲環境在搭建過程當中,可能會遇到不少問題,因此建議仍是在linux下面去進行爬蟲。css
- 一、安裝python、pycharm
pip install virtualenv virtualenvwrapper
這裏,可能使用pip會不成功,那麼須要先安裝pippip install -i htttps://pypi.douban.com/simple scrapy
###2.構建一個scrapy項目python
在上面的安裝成功後,就能夠開始建立一個scrapy項目了。在pycharm中是不能建立一個scrapy項目的。因此,仍是須要在命令窗口進行建立。(全部的操做要在對應的虛擬環境中進行。)linux
# -*- 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++
首先,關於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
# -*- 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)