1、scrapy环境的搭建
- python版本:
- python IDE:
- 用到python库:virtualenv,virtualenvwrapper,scrapy
下面开始详细的讲解环境搭建的过程,在python3中搭建scrapy爬虫环境在搭建过程中,可能会遇到很多问题,所以建议还是在linux下面去进行爬虫。
- 1、安装python、pycharm
- 2、
pip install virtualenv virtualenvwrapper
这里,可能使用pip会不成功,那么需要先安装pip - 3、在安装完virtualwrapper后,可以通过添加WORK_ON环境变量,将你的虚拟环境路径配置进去。之后,便可以使用mkvirtualenv xxxx。创建一个虚拟环境。然后,通过workon,查看你所有的虚拟环境,通过workon XXX进入该虚拟环境。
- 4、安装scrapy。这里很容易出各种错误,因为scrapy依赖了很多库。可能出现的错误有
- 1、timeout。这一般是网络原因。所以建议使用镜像。
pip install -i htttps://pypi.douban.com/simple scrapy
- 2、lxml错误。推荐一个网址
- 3、如果是python2安装的话,可能会出现vc++9.0 required,如果是3.5.3版本会出现vc++14.0 required错误。两种解决办法,1、根据cmd中的错误提示,去对应链接中下载vc++ for python;还有一个就是去(2)中的那个网站中下载Twisted.whl文件进行安装,安装方法是要进入要对应的虚拟环境,然后,去下载文件的目录中执行pip install 文件名进行安装。
###2.构建一个scrapy项目
-
在上面的安装成功后,就可以开始创建一个scrapy项目了。在pycharm中是不能创建一个scrapy项目的。所以,还是需要在命令窗口进行创建。(所有的操作要在对应的虚拟环境中进行。)
- 1、在电脑中新建一个存放工程的目录,在命令行中进入这个工程目录。
- 2、输入 scrapy startproject XXXX(项目名)。这样就创建好了一个scrapy项目。
- 3、这时候,命令行会提示你,如何去新建一个spider。1.进入项目;2.scrapy genspider example example.com。其中,example,表示spider的名字,example.com就是startulr。完了,你就可以在pycharm打开你的项目,并且配置interpreters(虚拟环境->lib->python.exe)。模板代码如下。
# -*- coding: utf-8 -*-import scrapyclass JobboleSpider(scrapy.Spider): name = "jobbole" allowed_domains = ["blog.jobbole.com"] start_urls = ['http://blog.jobbole.com/111016/'] def parse(self, response): pass
我们要写的代码也主要是parse函数。
3.关于scrapy项目的debug
- 怎么样启动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 executeimport sysimport 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就好。
4.开始进行爬取
- 爬取中,我使用的主要是根据xpath语法,进行爬取。获取xpath的方法很多,自己可以通过观察得到合适的xpath,可以从浏览器复制。
- 爬取前,我建议大家,去把settings中的ROBOTSTXT_OBEY参数设置为False。
- 这里,我主要是针对伯乐在线的文章进行爬取。爬取的内容主要是文章标题,内容,创建日期,评论数,点赞数,收藏数,以及相关tags。
# -*- coding: utf-8 -*-import scrapyimport refrom scrapy.http import Requestfrom urllib import parseclass JobboleSpider(scrapy.Spider): name = "jobbole" allowed_domains = ["blog.jobbole.com"] start_urls = ['http://blog.jobbole.com/all-posts/'] def parse(self, response): ''' 1、在文章列表页中取到所有的文章url,交给scrapy下载后进行解析 2、找到下一页的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选择器提取元素
#使用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)