scrapy抓取国家社科基金项目数据库

Posted pythoner6833

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scrapy抓取国家社科基金项目数据库相关的知识,希望对你有一定的参考价值。

1.明确任务

目标网站:http://fz.people.com.cn/skygb/sk/index.php/Index/seach

抓取任务:抓取近五年某关键词(例如"能源"、”大数据“等)的搜索结果,抓取内容包括项目编号、项目名称、学科分类等十一个字段。

2.网站分析

利用Fiddler工具分析,输入关键词,指定年份后,点击搜索,针对有多页码搜索结果点击下一页,发现此过程共包括一个POST请求和一个GET请求;其中,指定关键词和年份点击搜索的过程为POST请求,点击下一页的过程为GET请求。

POST请求参数:

formdata = {
        xmname: ‘‘,
        xktype: 0,
        xmtype: 0,
        cglevel: 0,
        cbdate : 0,
        cgxs: 0,
        lxtime: ‘‘,
        ssxt: 0,
        zyzw: 0,
        dwtype: 0,
        jxdata: 0,
        szdq: 0,
        pznum: ‘‘,
        cgname: ‘‘,
        jxnum: ‘‘,
        cbs: ‘‘,
        xmleader: ‘‘,
        hj: ‘‘,
        gzdw: ‘‘,
        zz: ‘‘
    }

POST请求目标URL:http://fz.people.com.cn/skygb/sk/index.php/Index/seach

GET请求只需要指定参数p即可,因此构造GET请求url为:

n_url = self.url + ? + xmname={}&p={}.format(formdata[xmname], self.page)

其中,xmname为搜索关键词,p为第几页的页码。

3.代码编写

3.1 创建scrapy爬虫项目

创建项目,名为ProSearch,使用命令:

scrapy startproject ProSearch http://fz.people.com.cn

3.2 明确抓取字段

创建爬虫项目后,编写items.py文件,明确待抓取的字段

# -*- coding: utf-8 -*-
import scrapy
class ProsearchItem(scrapy.Item):

    # 关键词
    keyword = scrapy.Field()
    # 项目编号
    pronums = scrapy.Field()
    # 项目类别
    protype = scrapy.Field()
    # 学科类别
    subtype = scrapy.Field()
    # 项目名称
    proname = scrapy.Field()
    # 立项时间
    protime = scrapy.Field()
    # 负责人
    leaders = scrapy.Field()
    # 工作单位
    workloc = scrapy.Field()
    # 单位类别
    orgtype = scrapy.Field()
    # 所在省市
    provloc = scrapy.Field()
    # 所属系统
    systloc = scrapy.Field()

3.3 生成爬虫文件

在cmd窗口进入到ProSearch项目后,生成爬虫文件。使用命令:

scrapy genspider SearchPro

3.4 编写爬虫逻辑

生成爬虫文件后,来到spiders文件夹下的SearchPro.py文件,开始辨写爬虫逻辑。

# -*- coding: utf-8 -*-
import scrapy
from ProSearch.items import ProsearchItem

class SearchproSpider(scrapy.Spider):
    
    name = SearchPro  # 爬虫名称
    allowed_domains = [fz.people.com.cn]
    # start_urls = [‘http://fz.people.com.cn/skygb/sk/index.php/Index/seach‘]
    page = 1

    # 指定检索关键词
    keywords = [可持续, 互联网, 大数据, 能源]
    # 角标
    index = 0
    # 年份
    years = 2018

    # POST提交参数
    formdata = {
        xmname: ‘‘,
        xktype: 0,
        xmtype: 0,
        cglevel: 0,
        cbdate : 0,
        cgxs: 0,
        lxtime: ‘‘,
        ssxt: 0,
        zyzw: 0,
        dwtype: 0,
        jxdata: 0,
        szdq: 0,
        pznum: ‘‘,
        cgname: ‘‘,
        jxnum: ‘‘,
        cbs: ‘‘,
        xmleader: ‘‘,
        hj: ‘‘,
        gzdw: ‘‘,
        zz: ‘‘
    }

    # 参数提交的url
    url = "http://fz.people.com.cn/skygb/sk/index.php/Index/seach"

    def start_requests(self):
        """
        POST请求实现一般是重写start_requests函数,指定第一个关键词为默认检索关键词
        :return: 
        """
        self.formdata[xmname] = 可持续
        self.formdata[lxtime] = str(self.years)
        yield scrapy.FormRequest(
            url=self.url,
            formdata=self.formdata,
            callback=self.parse,
            meta={formdata: self.formdata}
        )

    def parse(self, response):
        """
        解析数据
        :param response: 
        :return: 
        """
        if response.meta[formdata]:
            formdata = response.meta[formdata]

        # 每行数据所在节点
        try:
            node_list = response.xpath("//div[@class=‘jc_a‘]/table/*")[1:]
        except:
            print("关键词‘{}’无搜索结果!".format(formdata[xmname]))
        for node in node_list:
            # 提取数据
            item = ProsearchItem()
            # 关键词
            item[keyword] = formdata[xmname]
            # 项目编号
            item[pronums] = node.xpath(./td[1]/span/text()).extract_first()
            # 项目类别
            item[protype] = node.xpath(./td[2]/span/text()).extract_first()
            # 学科类别
            item[subtype] = node.xpath(./td[3]/span/text()).extract_first()
            # 项目名称
            item[proname] = node.xpath(./td[4]/span/text()).extract_first()
            # 立项时间
            item[protime] = node.xpath(./td[5]/span/text()).extract_first()
            # 负责人
            item[leaders] = node.xpath(./td[6]/span/text()).extract_first()
            # 工作单位
            item[workloc] = node.xpath(./td[8]/span/text()).extract_first()
            # 单位类别
            item[orgtype] = node.xpath(./td[9]/span/text()).extract_first()
            # 所属省市
            item[provloc] = node.xpath(./td[10]/span/text()).extract_first()
            # 所属系统
            item[systloc] = node.xpath(./td[11]/span/text()).extract_first()
            yield item

        # 匹配下一页的数据
        if 下一页 in response.xpath("//div[@class=‘page clear‘]/a").extract():
            self.page += 1
            n_url = self.url + ? + xmname={}&p={}.format(formdata[xmname], self.page)
            yield scrapy.Request(url=n_url, callback=self.parse, meta={formdata: formdata})

        # 匹配其他年份的数据
        searcy_year = int(formdata[lxtime])
        if not searcy_year <= 2014:
            searcy_year -= 1
            formdata[lxtime] = str(searcy_year)
            print("检索关键词:{}!".format(formdata[xmname]))
            yield scrapy.FormRequest(
                    url=self.url,
                    formdata=formdata,
                    callback=self.parse,
                    meta={formdata: formdata}
            )
        # 其他关键词搜索
        else:
            self.index += 1
            if not self.index > len(self.keywords)-1:
                keyword = self.keywords[self.index]
                print("更新检索关键词为:{}".format(keyword))

                formdata[xmname] = keyword
                formdata[lxtime] = str(self.years)

                yield scrapy.FormRequest(
                        url=self.url,
                        formdata=formdata,
                        callback=self.parse,
                        meta={formdata: formdata}
                )

3.5 编写数据保存逻辑

本项目用excel对数据进行保存。在pipelines.py文件中编写数据保存的逻辑。

# -*- coding: utf-8 -*-
from openpyxl import Workbook

class ProsearchPipeline(object):

    def __init__(self):
        # 创建excel表格保存数据
        self.workbook = Workbook()
        self.booksheet = self.workbook.active
        self.booksheet.append([关键词, 项目编号, 项目类别, 学科类别, 项目名称, 立项时间, 负责人, 工作单位, 单位类别, 所在省市, 所属系统])

    def process_item(self, item, spider):
        
        DATA = [
            item[keyword], item[pronums], item[protype], item[subtype], item[proname], item[protime], item[leaders], item[workloc], item[orgtype], item[provloc], item[systloc]
        ]

        self.booksheet.append(DATA)
        self.workbook.save(./data/ProSearch.xls)
        return item

3.6 其他细节

到此基本内容完成,设置一下settings.py文件对细节进行处理基本爬虫就可以运行了。

处理一:打开pipline通道

处理二:添加随机请求头并打开下载中间件

处理三:添加重拾、延时、log级别等

处理四:编写脚本main.py文件

scrapy默认使用命令行进行创建、生成、爬去等任务,可尝试在整个项目下编写一个main.py文件,将爬去命令添加到py文件中,直接在编辑器中F5运行。

技术分享图片

下次每次运行main.py文件就可以直接运行了。

 4.完整代码

 完整代码参见github

 

 

以上是关于scrapy抓取国家社科基金项目数据库的主要内容,如果未能解决你的问题,请参考以下文章

Python之Scrapy安装

Python爬虫实战,Scrapy实战,抓取并分析天气数据

实战scrapy抓取站长图片数据

Python 和 Scrapy,并试图将抓取的数据放入 MariaDB/MYSQL 数据库

使用 scrapy 抓取网站

分布式爬虫:使用Scrapy抓取数据