(二)爬虫框架(3)——CrawlSpiders是什么鬼

CrawlSpider是在spider.Spider基础之上封装的一个类,添加了一些功能。

在Spider中需要把目标URL通过xpath或者正则的方式找到,添加到Request爬取队列中。而在CrawlSpider中,可以通过配置规则,自动的获取页面上所有匹配的URL,并且自动添加到Request爬取队列中。
爬取汽车之家_电动车搜索的数据,看一下是如何自动匹配URL。

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class AutohomeSpider(CrawlSpider):
    name = 'autohome'
    allowed_domains = ['car.autohome.com.cn', 'www.autohome.com.cn']
    start_urls = ['https://car.autohome.com.cn/diandongche/list-0-0-0-0-0-0-0-0-1.html']
    pageLink = LinkExtractor(allow=(r"list-0-0-0-0-0-0-0-0-\d+.html"))
    rules = (
        Rule(pageLink, callback="parse_page", follow=True),
    )
    #解析网页不允许使用parse()方法,必须另起名字
    def parse_page(self, response):
      print(response.url)

此时可以看到符合正则匹配的页面就都打印出来了,也就是说明,这些页面都进行了访问。


Rule函数可以配置匹配规则
Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links, process_request)

link_extractor:LinkExtractor对象,用于定义需要提取的链接(正则)。
callback:解析页面时的回调函数,例如parse_other(self, response),函数名不能是parse()。
cb_kwargs:回调函数的参数,不包含response。
follow:布尔值,指定根据该规则从response提取的链接是否需要跟进。如果callback为None,则默认为True,反之为False。
process_links:从link_extractor中获取到链接列表时将会调用该函数,用来过滤URL。
process_request:该规则提取到每个request时都会调用该函数。返回一个request或者None。

LinkExtractor主要是用来提取链接
LinkExtractor(allow=(), deny=(), allow_domains=(), deny_domains=(), deny_extensions=None, restrict_xpaths=(), restrict_css=(), tags=('a', 'area'), attrs=('href'), canonicalize=True, unique=True, process_value=None)

allow:满足括号中的“正则表达式”的值会被提取,如果为空,则全部匹配。
deny:满足括号中的“正则表达式”的值不会被提取。
allow_domains:会被提取的链接的domains
deny_domains:不会被提取的链接的domains
deny_extensions:包含 在提取链接时 应该忽略的扩展的单个值或字符串列表。
restrict_xpaths:xpath选择器
restrict_css:css选择器
tags:在查找要提取的链接时应该考虑的标签列表,默认a标签。
attrs:在查找要提取的链接时应该考虑的属性或属性列表,默认href属性。
canonicalize:每个提取的url使用w3lib.url.canonicalize_url规范化。默认为True。
unique:是否应对提取的链接应用重复过滤。默认为True。
process_value:接收从标签提取的每个值和扫描的属性并且可以修改值并返回新值的函数,或者返回None以完全忽略链接。如果没有给出,process_value默认为。lambda x: x


可以匹配到URL之后,就是提取数据,然后存放到本地。之前的几个例子都是存放到json文件中,阅读的时候感觉很难受,接下来就试着把数据存到MySQL数据库中。
scrapy框架使用了Twisted作为框架,Twisted是一个非常好的异步框架,里面已经封装好了连接数据库等操作。可以直接使用,在Pipeline中开启数据库连接池,Mysql的参数可以写在settings.py中。注意先安装pymysql库。

from twisted.enterprise import adbapi
from . import settings
import pymysql

class FirstCrawlSpiderPipeline(object):
    def __init__(self):
        #设置Mysql的参数
        dbparms = dict(
            host=settings.MYSQL_HOST,
            db=settings.MYSQL_DB,
            user=settings.MYSQL_USER,
            passwd=settings.MYSQL_PASSWORD,
            charset=settings.MYSQL_CHARSET,
            cursorclass=pymysql.cursors.DictCursor,
            use_unicode=True
        )
        #开启数据库连接池
        self.db_pool = adbapi.ConnectionPool("pymysql", **dbparms)
    #处理数据
    def process_item(self, item, spider):
        query = self.db_pool.runInteraction(self.do_insert, item)
        query.addErrback(self.on_error, spider)
    #异步执行insert操作
    def do_insert_line(self, cursor, item):
        insert_sql = """INSERT INTO table_test(`id`, `name`) VALUES (%s,%s)"""
        args = (item["id"], item["name"])
        cursor.execute(insert_sql, args )
    #sql异常处理
    def on_error(self, failure, spider):
        print(failure)
    #执行结束后关闭连接池
    def close_spider(self, spider) :
        self.db_pool.close()
#MYSQL
MYSQL_HOST = '127.0.0.1'   #主机
MYSQL_PORT = 3306
MYSQL_DB = 'car_home'   #数据库名称
MYSQL_USER = 'root'           #用户名
MYSQL_PASSWORD = 'root'   #密码
MYSQL_CHARSET = 'utf8mb4'     #编码格式

OK,此时可以把数据存到数据库里面了,还有一个问题,就是如果有异常,现在是打印在控制台上,那每一次启动爬虫就会清空控制台,所以需要日志文件。scrapy是提供了日志的功能,在setting.py中配置,然后结合logging库进行使用即可。现在就改一下pipeline中的on_error函数,把异常信息记录到日志文件中。

# 日志输出
LOG_LEVEL = 'INFO'                #日志最低等级
LOG_FILE = "LOG.log"              #日志文件名称
LOG_ENABLED = True                #开启日志
LOG_ENCODING = 'UTF-8'            #编码格式
LOG_STDOUT = False                #是否将print()输出到日志中,默认为false
def on_error(self, failure, spider):
    """
        打印记录错误信息
    """
    logging.log(msg=failure, level=logging.ERROR)

日志分为五个等级:
**
CRITICAL - 严重错误(critical)
ERROR - 一般错误(regular errors)
WARNING - 警告信息(warning messages)
INFO - 一般信息(informational messages)
DEBUG - 调试信息(debugging messages)
**


完整代码

你可能感兴趣的:((二)爬虫框架(3)——CrawlSpiders是什么鬼)