12.scrapy框架之递归解析和post请求

本文深入讲解Scrapy框架的递归解析、多页爬取及POST请求实现,剖析五大核心组件工作流程,包括引擎、调度器、下载器、爬虫与项目管道。并通过实例演示糗事百科段子爬取,详细介绍如何利用Request方法进行高效的数据抓取。

12.scrapy框架之递归解析和post请求

 

今日概要

  • 递归爬取解析多页页面数据
  • scrapy核心组件工作流程
  • scrapy的post请求发送

今日详情

1.递归爬取解析多页页面数据

- 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储

- 需求分析:每一个页面对应一个url,则scrapy工程需要对每一个页码对应的url依次发起请求,然后通过对应的解析方法进行作者和段子内容的解析。

实现方案:

    1.将每一个页码对应的url存放到爬虫文件的起始url列表(start_urls)中。(不推荐)

    2.使用Request方法手动发起请求。(推荐)

代码展示:

# -*- coding: utf-8 -*-
import scrapy
from qiushibaike.items import QiushibaikeItem # scrapy.http import Request class QiushiSpider(scrapy.Spider): name = 'qiushi' allowed_domains = ['www.qiushibaike.com'] start_urls = ['https://www.qiushibaike.com/text/'] #爬取多页 pageNum = 1 #起始页码 url = 'https://www.qiushibaike.com/text/page/%s/' #每页的url def parse(self, response): div_list=response.xpath('//*[@id="content-left"]/div') for div in div_list: #//*[@id="qiushi_tag_120996995"]/div[1]/a[2]/h2 author=div.xpath('.//div[@class="author clearfix"]//h2/text()').extract_first() author=author.strip('\n') content=div.xpath('.//div[@class="content"]/span/text()').extract_first() content=content.strip('\n') item=QiushibaikeItem() item['author']=author item['content']=content yield item #提交item到管道进行持久化 #爬取所有页码数据 if self.pageNum <= 13: #一共爬取13页(共13页) self.pageNum += 1 url = format(self.url % self.pageNum) #递归爬取数据:callback参数的值为回调函数(将url请求后,得到的相应数据继续进行parse解析),递归调用parse函数 yield scrapy.Request(url=url,callback=self.parse)

2.五大核心组件工作流程:

  • 引擎(Scrapy)
    用来处理整个系统的数据流处理, 触发事务(框架核心)
  • 调度器(Scheduler)
    用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
  • 下载器(Downloader)
    用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
  • 爬虫(Spiders)
    爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
  • 项目管道(Pipeline)
    负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

3.post请求发送

- 问题:在之前代码中,我们从来没有手动的对start_urls列表中存储的起始url进行过请求的发送,但是起始url的确是进行了请求的发送,那这是如何实现的呢?

- 解答:其实是因为爬虫文件中的爬虫类继承到了Spider父类中的start_requests(self)这个方法,该方法就可以对start_urls列表中的url发起请求:

  def start_requests(self): for u in self.start_urls: yield scrapy.Request(url=u,callback=self.parse)

【注意】该方法默认的实现,是对起始的url发起get请求,如果想发起post请求,则需要子类重写该方法。

  -方法: 重写start_requests方法,让其发起post请求:

def start_requests(self): #请求的url post_url = 'http://fanyi.baidu.com/sug' # post请求参数 formdata = { 'kw': 'wolf', } # 发送post请求 yield scrapy.FormRequest(url=post_url, formdata=formdata, callback=self.parse)

 

转载于:https://www.cnblogs.com/kcwxx/p/10272357.html

<think>我们使用Scrapy框架来爬取黑马程序员社区Python+人工智能技术交流板块的帖子信息。步骤:1.创建Scrapy项目2.定义Item3.编写Spider4.设置输出为JSON格式5.运行爬虫具体步骤:1.创建Scrapy项目在命令行中执行:scrapystartprojectheima进入项目目录:cdheima2.定义Item(在items.py中)我们需要定义要爬取的数据结构:标题、作者、发布时间链接。3.编写Spider创建一个名为`heima_spider.py`的爬虫文件。4.设置输出为JSON可以通过运行爬虫时使用`-o`选项输出JSON文件。5.运行爬虫scrapycrawl heima -o posts.json现在,我们详细编写代码。首先,在`items.py`中定义Item: ```pythonimport scrapyclass HeimaItem(scrapy.Item):title= scrapy.Field()#文章标题author =scrapy.Field()#作者publish_time= scrapy.Field()#发布时间link= scrapy.Field()#链接```然后,在`spiders`目录下创建`heima_spider.py`(或使用`genspider`命令生成,但这里手动创建):注意:我们需要分析目标网站的页面结构,这里以黑马程序员社区为例(假设网址为:https://bbs.itheima.com/forum-257-1.html)我们使用XPath或CSS选择器来提取数据。由于网站可能有反爬措施,我们设置合适的User-Agent下载延迟。以下是爬虫代码: ```pythonimport scrapyfrom heima.itemsimport HeimaItemclassHeimaSpider(scrapy.Spider):name= 'heima'allowed_domains= ['bbs.itheima.com']start_urls= ['https://bbs.itheima.com/forum-257-1.html']#起始URL,Python+人工智能板块defparse(self, response):#提取帖子列表posts= response.xpath('//*[@id="threadlisttableid"]/tbody[contains(@id,"normalthread")]')for postin posts:item =HeimaItem()#标题链接title_link= post.xpath('.//a[@class="sxst"]')item['title'] =title_link.xpath('text()').get()item['link'] =response.urljoin(title_link.xpath('@href').get())#作者item['author'] =post.xpath('.//td[@class="by"]/cite/a/text()').get()#发布时间#注意:发布时间可能在em标签内,且可能包含其他文本,需要处理time_str= post.xpath('.//td[@class="by"]/em/text()').get()if time_str:#去除可能的多余空格item['publish_time']= time_str.strip()else:item['publish_time'] =Noneyielditem#分页处理:找到下一页的链接next_page =response.xpath('//a[@class="nxt"]/@href').get()if next_page:next_page_url =response.urljoin(next_page)yieldscrapy.Request(url=next_page_url, callback=self.parse) ```注意:以上代码中的XPath可能需要根据实际网页结构调整。因为不同网站的HTML结构可能不同,我们需要根据目标网站的实际结构来修改。另外,为了遵守robots.txt避免被封禁,我们可以在`settings.py`中设置:ROBOTSTXT_OBEY= False#如果目标网站有robots.txt且禁止爬取,可以设置为False,但请确保合法合规USER_AGENT= 'Mozilla/5.0...'#设置一个合法的User-AgentDOWNLOAD_DELAY=1#下载延迟,避免请求过快最后,运行爬虫scrapy crawlheima-oposts.json这样,爬取的数据就会保存到`posts.json`文件中。注意:在实际操作中,可能需要处理登录、验证码、动态加载等问题,但根据问题描述,我们假设目标网站是静态的。如果遇到动态加载(比如通过JavaScript加载数据),可能需要使用Splash或Selenium中间件,但这里先按静态网站处理。如果目标网站有反爬措施,可能需要设置中间件(如代理、随机User-Agent等)。以上是一个基本的爬虫实现。请根据实际情况调整XPath设置。</think>### 使用Scrapy爬取黑马程序员社区数据并输出JSON 以下是完整实现步骤,包含代码示例详细说明: #### 1. 创建Scrapy项目 ```bash # 创建项目 scrapy startproject heima_spider # 创建爬虫 cd heima_spider scrapy genspider bbs bbs.itheima.com ``` #### 2. 定义数据结构(items.py) ```python import scrapy class HeimaItem(scrapy.Item): title = scrapy.Field() # 文章标题 author = scrapy.Field() # 作者 publish_time = scrapy.Field() # 发布时间 link = scrapy.Field() # 文章链接 ``` #### 3. 编写爬虫逻辑(spiders/bbs.py) ```python import scrapy from heima_spider.items import HeimaItem from datetime import datetime class BbsSpider(scrapy.Spider): name = 'bbs' allowed_domains = ['bbs.itheima.com'] # Python+人工智能板块URL start_urls = ['https://bbs.itheima.com/forum.php?mod=forumdisplay&fid=257'] def parse(self, response): # 提取所有帖子 posts = response.css('tbody[id^="normalthread"]') for post in posts: item = HeimaItem() # 提取标题链接 title_elem = post.css('a.s.xst') item['title'] = title_elem.css('::text').get().strip() item['link'] = response.urljoin(title_elem.attrib['href']) # 提取作者 item['author'] = post.css('td.by cite a::text').get().strip() # 提取发布时间 time_str = post.css('td.by em span::attr(title)').get() if not time_str: time_str = post.css('td.by em::text').get().strip() item['publish_time'] = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S').isoformat() yield item # 分页处理 next_page = response.css('a.nxt::attr(href)').get() if next_page: yield response.follow(next_page, callback=self.parse) ``` #### 4. 配置JSON输出(settings.py) ```python # 添加以下配置 FEED_FORMAT = 'json' FEED_URI = 'posts.json' FEED_EXPORT_ENCODING = 'utf-8' # 遵守robots.txt (建议开启) ROBOTSTXT_OBEY = True # 设置请求延迟防止被封 DOWNLOAD_DELAY = 1 ``` #### 5. 运行爬虫 ```bash scrapy crawl bbs ``` #### 输出结果示例(posts.json) ```json [ { "title": "Python基础教程分享", "author": "编程小白", "publish_time": "2023-08-15T14:30:00", "link": "https://bbs.itheima.com/thread-12345-1-1.html" }, { "title": "人工智能实战项目讨论", "author": "AI达人", "publish_time": "2023-08-14T10:15:00", "link": "https://bbs.itheima.com/thread-12346-1-1.html" } ] ``` ### 关键点说明 1. **数据提取**: - 使用CSS选择器定位元素 - 处理动态时间格式(ISO8601标准化) - 相对链接转绝对链接(`response.urljoin()`) 2. **分页处理**: - 自动识别下一页链接 - 递归调用解析函数 3. **反爬措施**: - 设置下载延迟(`DOWNLOAD_DELAY`) - 遵守robots协议 - 使用随机User-Agent(需安装`scrapy-fake-useragent`包) 4. **数据清洗**: - 文本内容使用`.strip()`去除空白 - 时间格式统一转换 - 空值处理逻辑 > 提示:如果网站结构变化,需调整CSS选择器。可通过Scrapy Shell测试选择器:`scrapy shell 'https://bbs.itheima.com/forum.php?mod=forumdisplay&fid=257'`[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值