嘘~ 正在从服务器偷取页面 . . .

行百里者半九十——scrapy 框架(4)


深度爬取——请求传参

目的

爬取 校花网 中港台明星的名字和简介

信息分别在两个页面里


思路分析

我们发现要实现这个目的,我们既要对原页面进行数据爬取,也要对详情页进行明星简介的爬取。

这时候我们似乎可以使用前面学的回调函数的方法,调用一个新的函数方法对详情页进行数据爬取。

不过这个方法还有一个问题,就是怎么保证在原页面爬取的名字数据可以和详情页的一一对应。(不考虑在详情页同时爬取名字和简介信息,不然还怎么介绍请求传参)

解决这个问题的方法就是请求传参,简单来说,就是在回调函数的时候,将已经爬取到的名字作为参数传到被调用的函数中。

听起来似乎听抽象的,那么就直接看代码好了。

代码实现

首先使前期准备工作。

配置文件。


items.py 文件的代码编写

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class DataproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()
    content = scrapy.Field()
    pass

主文件的代码编写

import scrapy
from DataPro.items import DataproItem

class StardataSpider(scrapy.Spider):
    name = 'Data'
    # allowed_domains = ['www.xxx.com']

    start_urls = ['http://www.521609.com/ziliao/gangtai/']

    url = "http://www.521609.com/ziliao/gangtai/index_%s.html"
    page_num = 2

    def parse_detail(self, response): # 爬取详情页
        content = response.xpath('//span[@class="info"]/p//text()').extract()
        item = response.meta['item']
        content = "".join(content)
        item['content'] = content

        yield item

    def parse(self, response):
        # 明星姓名的列表
        start_name_list = response.xpath('//div[@class="page_starlist page_zllist"]/ul/li/a[2]/h3/text()').extract()
        for i in range(len(start_name_list)):
            item = DataproItem()
            start_name = start_name_list[i]
            item["name"] = start_name
            # 根据姓名的位置,判断对应的详情页位置的网址位置,实现一一对应
            path = '//div[@class="page_starlist page_zllist"]/ul/li[%s]/a[2]/@href' % str(i+1)
            src = 'http://www.521609.com/' + response.xpath(path).extract_first()
            
            # meta 实现请求传参,请求传参的形式是字典形式
            yield scrapy.Request(url = src, callback = self.parse_detail, meta = {"item": item})

        if self.page_num <= 22:
            new_url = self.url % str(self.page_num)
            self.page_num += 1
            # 对于翻页的情况,实现回调函数
            yield scrapy.Request(url = new_url, callback = self.parse)

pipelines.py 文件的代码编写

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class DataproPipeline:
    fp = None

    def open_spider(self, spider):
        self.fp = open("资料.txt", "a", encoding = "utf-8")
        print("开始爬取……")

    def process_item(self, item, spider):
        content = item["content"]
        name = item["name"]

        self.fp.write(name + "\n" + content + "\n\n")

        print(name, "爬取成功!")
        return item

    def close_spider(self, spider):
        self.fp.close()
        print("爬取结束!!!")

运行结果



文章作者: New Ass
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 New Ass !
  目录