爬虫2.1-scrapy框架-两种爬虫对比

scrapy框架-两种爬虫对比和大概流程

注:spider.py指使用命令行创建的爬虫主文件

1. 传统spider爬虫

创建scrapy项目,首先进入想创建项目的目录,然后cmd输入:

scrapy startproject projectname # projectname 即是项目名
cd projectname
scrapy genspider spidername “xxxx.com” 

spidername就是爬虫文件名 xxxx.com 用于限定爬虫爬取的范围爬虫名,其与项目名不能相同

为了方便运行,之间在project目录下创建start_project.py 来运行整个项目

~start_project.py
from scrapy import cmdline
cmdline.execute("scrapy crawl qsbk_spider".split())

简单两句话,要使用.split()是因为这里参数值接收列表,分裂之后恰好是列表,然后才能被执行。

回到spider.py(爬虫主要模块,用于解析),这里已经帮我们自动生成了一些参数,在parse函数中,response参数使用xpath语法,得到的是SelectorList类的对象(该类是scrapy框架定义的),然后可以使用for语句遍历其中,获得Selector类,还是可以使用xpath语法获取数据,这里由一个很方便的函数.get() 直接获取字符串,再使用.strip()可以直接获取没有空格换行等的文本。

示例代码
    def parse(self, response):
        contentLeft = response.xpath("//div[@class='col1']/div")
        for content in contentLeft:
            author = content.xpath(".//h2/text()").get().strip()    # get 方法获取Selector中的第一个文本 返回str类型    getall方法获取Selector中的所有文本  返回一个列表
            joke = content.xpath(".//div[@class='content']/span/text()").get().strip()
            info = XXItem(author=author, joke=joke)
            yield info   # 推送到piplines.py中进行下一步的数据存入操作

2. crawl型爬虫

在cmd中创建项目和爬虫

scrapy startproject projectname
cd projectname
scrapy genspider -t crawl spidername "domain_name"

可见创建爬虫时便与传统spider不同,然后进入spider.py

# 项目名为wxapp,爬虫名为wxapp_spider.py
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from wxapp.items import WxappItem  # 导入items中定义好的数据类,方便json格式写入
class WxappSpiderSpider(CrawlSpider):
    name = 'wxapp_spider'
    allowed_domains = ['wxapp-union.com']
    start_urls = ['http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1']  # 从第一页开始
    rules = (
        # Rule 1用于从开始页面向后面找到相同模式的url,所以follw选择True,
        Rule(LinkExtractor
             (allow=r'.+mod=list&catid=2&page=\d+'), follow=True),
        # Rule 2用于在Rule 1模式的页面下,找到真正需要解析数据的url,回调函数一定要改名字。
        Rule(LinkExtractor(allow=r'.+/article-.+\.html'), callback='parse_info', follow=False),)

    def parse_info(self, response):
        title = response.xpath(r"//h1[@class='ph']/text()").get()  #获取标题
        author = response.xpath(r"//p[@class='authors']/a/text()").get()  # 获取作者
        contents = response.xpath(r"//td[@id='article_content']//text()").getall()  
        # 获取内容   因为td下面还有很多标签所以要用//text() 之后再.getall()
        content = ''.join(contents).strip()  
        # 巧妙用法 join将列表中的每一项依次放入  加上.strp() 去掉多余的换行和空格
        info = WxappItem(title=title, author=author, content=content)  #创建info对象
        yield info  # 推送给pipelines.py

在多个规则下,一定要注意callback和follow参数,判断需要在新的页面中继续跟进符合正则的url。

比如获取职位简介列表的url就需要跟进,而职位的详情页面找到相同的url时不需要跟进,按照职位列表往下遍历即可。

所以,crawl型爬虫适合于整站爬取,传统spider型爬虫适合小规模爬取

crawl型爬虫参数讲解

另外需要使用 LinkExtractors链接提取器:
class scrapy.linkextractors.LinkExtractor(
    allow = (),
    deny = (),
    allow_domains = (),
    deny_domains = (),
    deny_extensions = None,
    restrict_xpaths = (),
    tags = ('a','area'),
    attrs = ('href'),
    canonicalize = True,
    unique = True,
    process_value = None
)
主要参数讲解:

allow:允许的url。所有满足这个正则表达式的url都会被提取。
deny:禁止的url。所有满足这个正则表达式的url都不会被提取。
allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
deny_domains:禁止的域名。所有在这个里面指定的域名的url都不会被提取。
restrict_xpaths:严格的xpath。和allow共同过滤链接。

Rule规则类:
定义爬虫的规则类。以下对这个类做一个简单的介绍:

class scrapy.spiders.Rule(
    link_extractor, 
    callback = None, 
    cb_kwargs = None, 
    follow = None, 
    process_links = None, 
    process_request = None
)
主要参数讲解:

link_extractor:一个LinkExtractor对象,用于定义爬取规则。
callback:满足这个规则的url,应该要执行哪个回调函数。因为CrawlSpider使用了parse作为回调函数,因此不要覆盖parse作为回调函数自己的回调函数。
follow:指定根据该规则从response中提取的链接是否需要跟进。
process_links:从link_extractor中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。


3. 循环页面请求

找到循环条件和结束标准
在spider.py中
def parse(self, response):
    ...
    设置好迭代退出的条件
    使用yield scrapy.Request(url, callback=self.parse)  重复调用

示例:
def parse(self, response):
       ..... # 解析数据的函数
        next_url = response.xpath("//ul[@class='pagination']/li[last()]/a/@href").get()
        if re.match(r'/\w*/\w*/\d*/', next_url) is None:
            return
        else:
            yield scrapy.Request(self.base_domain+next_url, callback=self.parse)    
            # 这里 self.base_domain+next_url 就是下一个页面的url,之后回调函数使用它自己,到了最后一页处理完数据 达成if判断条件退出。这里用正则实际上由装逼的意思,判断一下长度就可以了

4. scrapy框架爬虫的大致流程

使用命令行创建爬虫项目

>> scrapy startproject [projectname]
>> cd [projectname]
>> scrapy genspider -t crawl [爬虫名字] [域名]  or  scrapy genspider [爬虫名字] [域名]  

使用IDE打开项目,并在projectname下创建start.py用于启动整个项目,注意scrapy框架只能这样启动。

~ start.py
from scrapy import cmdline
cmdline.execute('scrapy crawl [爬虫名字]'.split())

修改[spidername].py

按需求修改解析函数,如果是crawl型爬虫还需要修改和添加Rule

修改items.py

将需要的参数写好

示例:
class xxItem(scrapy.Item):
    author = scrapy.Field()
    joke = scrapy.Field()

修改pipelines.py

pipelines.py主要用于按需求存储数据。

看需求是否修改或添加中间件---middlewares.py

最后按照需求修改settings.py

settings.py
修改ROBOTSTXT_OBEY = False
打开headers  DEFAULT_REQUEST_HEADERS 加入User-Agent  Cookie   
打开并修改piplines设置  ITEM_PIPELINES
打开延时 DOWNLOAD_DELAY
打开中间件 DOWNLOADER_MIDDLEWARES

实战代码可以看另一个笔记:scrapy框架-图片分类下载

posted @ 2018-12-31 14:51  bitterz  阅读(930)  评论(0编辑  收藏  举报