包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。
cmd:scrapy genspider xiaoshuo(py名) https://www.xiaoshuodaquan.com/quanben/(URL)
# xiaoshuo.py
import scrapy
class XiaoshuoSpider(scrapy.Spider):
name = 'xiaoshuo'
allowed_domains = ['https://www.xiaoshuodaquan.com/quanben/']
start_urls = ['http://https://www.xiaoshuodaquan.com/quanben//']
def parse(self, response):
pass
从Network header中构建
# 构造请求头, 对setting中的文件内容进行覆盖
custom_settings = {
"DEFAULT_REQUEST_HEADERS": {
'Host': '',
'Connection': 'keep-alive',
'Accept': '*/*',
'Origin': '',
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': '',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': '',
'Accept-Encoding': '',
'Accept-Language': '',
'Cookie': ''
}
}
def form_data_func(self, pageNum):
# 数据
formData = {
'pageNum': str(pageNum),
'pageSize': str(30),
'column': 'szse',
'tabName': 'fulltext',
'plate': 'sz;sh',
'category': 'category_ndbg_szsh',
'seDate': '2017-04-02~2020-04-02',
'isHLtitle': 'true'
}
return formData
# 重写start_requests
def start_requests(self):
# 请求的地址
url = "http://www.cninfo.com.cn/new/hisAnnouncement/query/"
# 模拟表单或Ajax提交post请求
yield scrapy.FormRequest(url, formdata=self.form_data_func(1), callback=self.pageNum_parse)
# item.py
# 定义想要提取的信息
class TutoriaItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
hreflink = scrapy.Field() # 链接
title = scrapy.Field() # 书名
word_cnt = scrapy.Field() # 总字数
# spider: xiaoshuo.py
item = TutoriaItem()
yield item
# Setting.py
USER_AGENT = 'xiaoshuo (+代理IP)'
ROBOTSTXT_OBEY = False
# pipeline优先级设置
ITEM_PIPELINES = {
'juchao.pipelines.clearDataPipeline':1,
# 'scrapy.pipelines.files.FilesPipeline':1,
'juchao.pipelines.JuchaoPipeline': 2,
# 'juchao.pipelines.JuchaoPipeline': 300,
}
FILES_STORE = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'pdf')
class TutoriaPipeline(object):
def __init__(self):
store_file = os.path.dirname(__file__) + 'xiaoshuo.csv'
# print("store_file:", store_file)
self.file = open(store_file, 'w', newline='')
self.writer = csv.writer(self.file)
def process_item(self, item, spider):
# print(item['book_class'])
# if item['book_class'] == '':
# print("****************************")
if item['book_class'] != "" or item['book_class'] != '':
self.writer.writerow((item['book_title'], item['href_link'], item['total_words'], item['brief_introduction']))
return item
def close_spider(self,spider):
self.file.close()
Spiders:爬虫,定义了爬取的逻辑和网页内容的解析规则,主要负责解析响应并生成结果和新的请求
Engine:引擎,处理整个系统的数据流处理,出发事物,框架的核心。
Scheduler:调度器,接受引擎发过来的请求,并将其加入队列中,在引擎再次请求时将请求提供给引擎
Downloader:下载器,下载网页内容,并将下载内容返回给spider
ItemPipeline:项目管道,负责处理spider从网页中抽取的数据,主要是负责清洗,验证和向数据库中存储数据
Downloader Middlewares:下载中间件,是处于Scrapy的Request和Requesponse之间的处理模块
Spider Middlewares:spider中间件,位于引擎和spider之间的框架,主要处理spider输入的响应和输出的结果及新的请求middlewares.py里实现
修改setting.py文件,将ROBOTSTXT_OBEY = True改为False: 拒绝遵守 Robot协议
把需要传递的信息赋值给这个叫meta的变量,但meta只接受字典类型的赋值,因此要把待传递的信息改成“字典”的形式,即:
meta={‘key1’:value1,‘key2’:value2}
如果想在下一个函数中取出value1,只需得到上一个函数的meta[‘key1’]即可,因为meta是随着Request产生时传递的,下一个函数得到的Response对象中就会有meta,即response.meta,取value1则是value1=response.meta[‘key1’]
# item.py
# FilesPipeline处理需要
# 当FilesPipeline处理时,会检测是否有file_urls字段,如果有的话,会将url传送给scarpy调度器和下载器;
# 下载完成之后,会将结果写入item的另一字段files,files包含了文件现在的本地路径(相对于配置FILE_STORE的路径)、文件校验和checksum、文件的url。
file_urls = scrapy.Field()
file = scrapy.Field()
# pipline.py
class JuchaoPipeline(FilesPipeline): # 继承自FilesPipeline
def get_media_requests(self, item, info):
yield scrapy.Request(item['file_urls'], meta = {'secCode':item['secCode'], 'announcementTitle':item['announcementTitle']})
# 修改文件名
def file_path(self, request, response=None, info=None):
# print(response)
secCode = request.meta['secCode']
announcementTitle = request.meta['announcementTitle']
# print(secCode, announcementTitle)
# input()
return '%s_%s.pdf' % (secCode, announcementTitle)