题目要求
- 使用scrapy,建立爬虫
- 针对新浪股吧,下载自己选择的上海证券市场股票评论,股票代码自选填入随后示范连接处,http://guba.sina.com.cn/?s=bar&name=sh600518
- 爬取10页数据,提取:评论内容,发表时间,发表人这三项内容
- 并将数据以JSON方式存储下来,以备后续实验使用
一、scrapy是什么?
Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。
Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。
二、代码
1.爬虫主要代码
代码如下(示例):
from copy import deepcopy
import scrapy
count=1#全局变量,后面进行保证只爬取10页
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['http://guba.sina.com.cn/?s=bar']
start_urls = ['http://guba.sina.com.cn/?s=bar&name=sh600518']
def parse(self, response):
item={}
list=response.xpath('//*[@id="blk_list_02"]/table/tbody/tr')#获取该页上的所有评论列表
for li in list:
try:
url = li.xpath('./td[3]/a/@href').extract_first()
href='http://guba.sina.com.cn'+url#获取每一个评论的url
item['author']=li.xpath('./td[4]/div/a[1]/text()').extract_first()
if item['author'] is None:
item['author']=li.xpath('./td[4]/div/text()').extract_first()
print(item['author'])
yield scrapy.Request(
href,
callback=self.parse_infor,
meta={"item": deepcopy(item)},
dont_filter=True)
except:
continue
global count
if count<10:
count+=1
href_all='http://guba.sina.com.cn/?s=bar&name=sh600518&type=0&page='+str(count)
print(href_all)
yield scrapy.Request(
href_all,
callback=self.parse,
dont_filter=True)
def parse_infor(self,response):#对每一个的评论的url响应进行处理
item=response.meta['item']
item['content']=response.xpath('//*[@id="thread_content"]/text()').extract_first()
if item['content'] is None:
li=response.xpath('//*[@id="thread_content"]/p/text()').extract_first()
for i in li:
if i is None:
item['content']+=''
else:
item['content']+=i#这里有个问题就是如果i是NoneType判断不出来
item['time']=response.xpath('//*[@id="thread"]/div[2]/div[6]/div[1]/span/text()').extract_first()
item['time'].replace('今天','10月22日')#这里偷了下懒
yield item
pass
2.Pipeline
因为要用json形式保存,所以我们在管道这里重新定义一个管道
代码如下(示例):
from itemadapter import ItemAdapter
from scrapy.exporters import JsonItemExporter
class StockSpiderPipeline:
def process_item(self, item, spider):
return item
class JsonExporterPipleline(object):
def __init__(self):
self.file=open('stockexport.json','wb')
self.exporter=JsonItemExporter(self.file,encoding="utf-8",ensure_ascii=False)
self.exporter.start_exporting()
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self,item,spider):
self.exporter.export_item(item)
return item
这里新定义的管道需要注册
ITEM_PIPELINES = {
#'stock_spider.pipelines.StockSpiderPipeline': 1,
'stock_spider.pipelines.JsonExporterPipleline': 1,
}
3.请求头
对请求头更改,减少被认为是爬虫的概率。
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Language': 'en',
}
总结
最近在使用selenium自动化,所以忽然使用scrapy有些生疏,代码没写注释,希望大家多多理解,毕竟程序员最烦写注释了(逃)。
其实总体上功能比较简单,只是涉及到翻页,和获取每一项的url,并且进入对应网页。scrapy用起来方便的多(因为不会用request)