Python爬虫入门实例九之Scrapy框架爬取股票信息(亲测有效)

写在前面

  这个实例我差不多用了一周的时间,终于把所有bug都抓完了,不过还是有一点点遗憾,就是正则表达式部分写的不够完美(本人目前智力、精力实在有限),如果各位大佬有更好的欢迎评论指教。下面我将把我这几天踩的坑,给各位小伙伴们介绍一下,希望各位能够成功避坑,同时也把我的不足之处给大家说明。好了,话不多说,进入正题。

一、准备工作

  这一部分主要就是选取网站和对网站源代码的查看及观察,具体步骤我在之前的文章写过,有需要的小伙伴可以参考。

传送门: https://blog.csdn.net/weixin_44578172/article/details/109391135

本例选取的是股城网: https://hq.gucheng.com/gpdmylb.html

二、具体步骤

1.建立工程和Spider模板

  首先win+R 输入cmd进入command模式

scrapy startproject 项目名(GuchengStocks)
cd 项目名(GuchengStocks)
scrapy genspider 爬虫名(stocks) 根链接目录(hq.gucheng.com)

2.编写Spider

  这一部分是关键,要编写获取页面和解析页面的代码

import scrapy
import re

class StocksSpider(scrapy.Spider):
    name = "stocks"
    start_urls = ['https://hq.gucheng.com/gpdmylb.html']

    def parse(self, response):
        for href in response.css('a::attr(href)').extract():
            try:
                stock = re.findall(r'[S][HZ]d{6}', href)[0]
                url = 'https://hq.gucheng.com/' + stock
                yield scrapy.Request(url, callback=self.parse_stock, headers={'user-agent': 'Mozilla/5.0'})
                #第二个参数callback给出了处理当前url给出的新的函数即parse_stock
            except:
                continue

    def parse_stock(self, response):
        infoDict = {}
        stockName = response.css('.stock_price.clearfix')
        #stockInfo = response.css('')
        name = response.css('h3').extract()[0]
        keyList = stockName.css('dt').extract()
        valueList = stockName.css('dd').extract()
        for i in range(len(keyList)):
            key = re.findall(r'<dt>.*<', keyList[i])[0][4:-1]
            #除去爬取的字符串中的无用部分,如&nbsp等,网页抓取时会因为编码原因转化成xa0,所以我们需要进行替换
            key = key.replace('u2003', '')
            key = key.replace('xa0', '')
            #dt标签中存在sup标签,可以用''替换掉
            key = key.replace('<sup></sup>', '')
            try:
                val = re.findall(r'>.*<', valueList[i])[0][1:-1]
            except:
                val = '--'
            infoDict[key] = val

        infoDict.update(
            {'股票名称': re.findall('<h3>.*)', name)[0][4:]})
        yield infoDict

3.编写pipelines

  这一部分是在类中定义函数,设置文件的开启和关闭及对应的处理方法

class GuchengstocksInfoPipeline(object):
    #openspider指的是当一个爬虫被调用时对应的pipline启动的方法
    def open_spider(self, spider):
        self.f = open('GuchengStockInfo.txt', 'w')

    #close_spider指的是当一个爬虫关闭时对应的pipline启动的方法
    def close_spider(self, spider):
        self.f.close()

    #对每一个item项进行处理时对应的方法,也是最主体的函数
    def process_item(self, item, spider):
        try:
            line = str(dict(item)) + 'n'
            self.f.write(line)
        except:
            pass
        return item

4.更改settings

  因为我们新建了一个类,没有用系统的默认类,所以要在相应位置更改配置

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    'GuchengStocks.pipelines.GuchengstocksInfoPipeline': 300,
}

5.运行爬虫

键入命令

scrapy crawl 爬虫名(stocks)

之后就可以在项目目录下看到有.txt文件了,文件中就是我们爬取到的数据

三、注意事项

  最后说一下我的采坑经历及不完美的地方

1.文件内容为空

  这是让我最头疼的一个问题,我认为我的逻辑没有问题,但爬取后的结果内容就是为空,这里我用的是css选择器。最后在debug的时候灵光一现,想到是不是我的class属性中包含空格的原因导致选择器发生错误,结果上网一查果然有相关资料。比如我要选择的类的属性是"stock_price clearfix",这样提取失败因为在css选择器中,空格表示取子代元素 所以选择器错误地把"stock_price clearfix"当成两个元素看待了,自然提取不到任何元素。解决方法是把空格用"."代替,即stock_price.clearfix就可以了。

2.内容包含其他标签

  我在成功解决上面问题后,发现爬取的数据中包含了dt的子标签sup,并且我多次更改正则表达式也没能将其去掉,最终选择用replace函数去替换他。

key = key.replace('<sup></sup>', '')

果然解决了(啊,真香~)

3.不足之处

  虽然replace()函数能够帮助解决一些问题,但并不是真正高级码农所为(我还是太菜了),因为我本身比较菜,最近精力也不太够,所以只能先做到这了,以后再慢慢研究完美的正则表达式的方式,当然各位大佬如果能帮忙解决就再好不过了,欢迎评论指教~

  本篇完,如有错误欢迎指出~

引用源自

中国大学MOOC Python网络爬虫与信息提取
https://www.icourse163.org/course/BIT-1001870001
匿名

发表评论

匿名网友