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)
相关文章
相关标签/搜索