下面开始详细的讲解环境搭建的过程,在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)