爬取流程

Spider类定义如何爬取指定的一个或多个网站,包括是否要跟进网页里的链接和如何提取网页内容中的数据。

爬取的过程是类似以下步骤的循环:

1.通过指定的初始URL初始化Request,并指定回调函数。当Request下载完后,生成Response作为参数传给回调函数。初始的Request是通过start_requests()读取start_urls中的URL来生成的,回调函数为parse()。
2.在回调函数中分析Response的内容,返回Item对象或者Request或包含二者的可迭代容器。返回Request对象经过Scrapy处理,下载相应的内容,并调用设置的回调函数。
3.在回调函数中,可以用选择器(或者Beautiful Soup,lxml这些解析器)来分析网页内容,生成Item。
4.生成的Item可以存入数据库,或存入到文件。

spider类

class scrapy.spiders.Spider:最简单的爬虫类。

方法与属性:
name:爬虫名,要唯一。
allowed_domains:允许爬取的域名列表。
start_urls:初始的URL列表。
custom_settings:参数配置字典,必须是类属性,因为参数配置在实例化前被更新。
crawler:此属性是由from_crawler()设置的。
settings:运行此爬虫的设置。
logger:Python的日志记录器,通过爬虫名创建。
from_crawler(crawler, *args, **kwargs):类方法,用于创建爬虫。crawler是Crawler的实例对象。
start_requests():当打开爬虫时调用此方法。会用初始URL列表创建Request。只调用一次。
parse(response):用于处理Response。
log(message[, level, component]):通过封装logger来发送日志消息。
closed(reason):爬虫关闭时调用此方法。

爬虫参数

爬虫可以接受参数来改变它的行为。这些参数一般用来定义初始URL,或者限定爬取网站的部分内容,也可以用来配置其它任何功能。

在运行crawl命令时,通过-a选项来传递参数(键值对):

scrapy crawl myspider -a category=electronics

然后可以在__init__()初始化函数里获取参数,如:

class MySpider(scrapy.Spider):
    name = 'myspider'
    
    def __init__(self, category=None, *args, **kwargs):  # 直接作为一个函数参数
        super(MySpider, self).__init__(*args, **kwargs)
        self.start_urls = ['http://www.example.com/categories/%s' % category]

而默认的__init__()函数会把这些参数定义为爬虫的属性,因此也可以这样用:

class MySpider(scrapy.Spider):
    name = 'myspider'
    
    def start_requests(self):
        yield scrapy.Request('http://www.example.com/categories/%s' % self.category)  # 作为一个属性
# -*- coding: utf-8 -*-
import scrapy
from wangyiPro.items import WangyiproItem
from selenium import webdriver
class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://news.163.com/']
    model_urls = [] #存放五大板块对应的url
    def __init__(self):
        self.bro = webdriver.Chrome(executable_path=r'C:\Users\lucky\Desktop\爬虫+数据\day07\chromedriver.exe')

    def parse(self, response):
        #解析五个板块对应的页面连接
        li_list = response.xpath('//*[@>)
        indexs = [3,4,6,7,8]
        for index in indexs:
            li = li_list[index]
            #每一个板块的url
            model_url = li.xpath('./a/@href').extract_first()
            self.model_urls.append(model_url)
            #对每一个板块的url发起请求。注意:请求成功后获取的响应对象中存储的响应数据是不包含新闻标题数据(动态加载)
            yield scrapy.Request(url=model_url,callback=self.parse_title)

    #是用来解析每一个板块页面中的新闻标题
    def parse_title(self,response):
        #response是不满足需求,因为该response中没有包含动态加载出来的新闻标题数据
        div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
        for div in div_list:
            new_title = div.xpath('.//div[@class="news_title"]/h3/a/text()').extract_first()

            item = WangyiproItem()
            item['title'] = new_title

            detail_url= div.xpath('.//div[@class="news_title"]/h3/a/@href').extract_first()
            #对新闻详情页发起请求,获取新闻内容
            yield scrapy.Request(detail_url,callback=self.parse_detail,meta={'item':item})

    #用来解析新闻详情页中的新闻内容(不是动态加载)
    def parse_detail(self,response):
        content = response.xpath('//*[@>).extract()
        content = ''.join(content)
        item = response.meta['item']
        item['content'] = content

        yield item
    #程序全部结束的时候被调用
    def closed(self,spider):
        print('结束爬虫!!!')
        self.bro.quit()
案例演示

相关文章: