爬取糗事百科實(shí)驗(yàn)
1. 創(chuàng)建工程
scrapy startproject qsbk
cd qsbk
2. 創(chuàng)建爬蟲(chóng)
scrapy genspider qsbk_spider qiushibaike.com
3. 分析頁(yè)面
入口地址
https://www.qiushibaike.com/text/page/1/
通過(guò)page路由分頁(yè)
4. ### 單頁(yè)面爬取
qsbk_spider.py
# -*- coding: utf-8 -*-
import scrapy
from qsbk.items import QsbkItem
class QsbkSpiderSpider(scrapy.Spider):
name = 'qsbk_spider' # 爬蟲(chóng)名稱
allowed_domains = ['qiushibaike.com'] # 爬取的域名
start_urls = ['https://www.qiushibaike.com/text/page/1/'] # 入口地址
def parse(self, response):
# 獲取所有段子
content_list = response.xpath("http://div[@class='col1 old-style-col1']/div")
# 遍歷列表獲取到每個(gè)段子
for content in content_list:
# 得到作者
author = content.xpath(".//h2/text()").get().strip()
# 得到文字內(nèi)容
content_text = content.xpath('.//div[@class="content"]/span//text()').getall()
# 使用getall獲取的內(nèi)容為列表形式 需要轉(zhuǎn)為字符串
content_text = "".join(content_text).strip()
# 新的item對(duì)象 從item文件中定義 需要配置 ITEM_PIPELINES 參數(shù)
item = QsbkItem(author=author,content = content_text)
# 傳遞這個(gè)對(duì)象給 pipelines
yield item
item.py
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
# 定義每個(gè)元素的存儲(chǔ)模板
class QsbkItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
author = scrapy.Field()
content = scrapy.Field()
- 需要注冊(cè)
ITEM_PIPELINES
配置才能生效
pipelines.py
import json
from scrapy.exporters import JsonItemExporter,JsonLinesItemExporter
# 以行的方式保存每個(gè)json對(duì)象 優(yōu)點(diǎn)可以按行讀取缺點(diǎn)不能一下讀取
class QsbkPipeline:
# 存儲(chǔ)為json文件 需要打開(kāi)一個(gè)文件
# 使用JsonLinesItemExporter或JsonItemExporter 需要wb方式打開(kāi)
def __init__(self):
# 打開(kāi)文件
self.exporter = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding="utf-8", indent=4)
self.fp = open("duanzi.json", 'wb')
# 注冊(cè)文件對(duì)象
def open_spider(self, spider):
# 爬取開(kāi)始時(shí)
pass
def close_spider(self, spider):
# 爬取結(jié)束時(shí)關(guān)閉文件
self.fp.close()
def process_item(self, item, spider):
# 將每一項(xiàng)以行的方式寫(xiě)入文件
self.exporter.export_item(item)
return item
另一種存儲(chǔ)形式
# 按列表方式儲(chǔ)存json 優(yōu)點(diǎn) 可以一下讀取,缺點(diǎn) 不能按行讀取
class QsbkPipeline:
def __init__(self):
self.fp = open("duanzi.json", 'wb')
def open_spider(self, spider):
self.exporter = JsonItemExporter(self.fp, ensure_ascii=False, encoding="utf-8",indent=4)
# 要寫(xiě)入到j(luò)son文件
self.exporter.start_exporting()
def close_spider(self, spider):
self.exporter.finish_exporting()
self.fp.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
還有一種存儲(chǔ)方式就是把爬取到的每一條都存進(jìn)列表然后返回列表給pipelines統(tǒng)一存儲(chǔ)到文件但是占內(nèi)存多
爬取到的數(shù)據(jù)
5. 運(yùn)行爬蟲(chóng)
scrapy crawl qsbk_spider
保存的duanzi.json
通過(guò)行的形式寫(xiě)入可以以行的形式進(jìn)行讀取,缺點(diǎn)是不能一下讀取為字典對(duì)象不滿足json規(guī)則
5. ### 多頁(yè)爬取
6. 分析下一頁(yè)的鏈接在 類名是pagination 的ul的最后一個(gè)li的a標(biāo)簽中
qsbk_spider.py
# -*- coding: utf-8 -*-
import scrapy
from qsbk.items import QsbkItem
class QsbkSpiderSpider(scrapy.Spider):
name = 'qsbk_spider' # 爬蟲(chóng)名稱
allowed_domains = ['qiushibaike.com'] # 爬取的域名
base_url = "https://www.qiushibaike.com" # 定義基礎(chǔ)url 和分頁(yè)url相加
start_urls = [base_url+'/text/page/1/'] # 入口地址
def parse(self, response):
# 獲取所有段子
content_list = response.xpath("http://div[@class='col1 old-style-col1']/div")
# 遍歷列表獲取到每個(gè)段子
for content in content_list:
# 得到作者
author = content.xpath(".//h2/text()").get().strip()
# 得到文字內(nèi)容
content_text = content.xpath('.//div[@class="content"]/span//text()').getall()
# 使用getall獲取的內(nèi)容為列表形式 需要轉(zhuǎn)為字符串
content_text = "".join(content_text).strip()
# 新的item對(duì)象 從item文件中定義 需要配置 ITEM_PIPELINES 參數(shù)
item = QsbkItem(author=author,content = content_text)
# 傳遞這個(gè)對(duì)象給 pipelines
yield item
# 獲取下一頁(yè)的鏈接
next_link = content.xpath('//ul[@class="pagination"]/li[last()]/a/@href').get()
if not next_link:
# 如果沒(méi)有及返回程序結(jié)束 共計(jì)13頁(yè)
return
else:
# 分發(fā)新任務(wù)到
yield scrapy.Request(self.base_url + next_link, callback=self.parse)
運(yùn)行結(jié)果
共計(jì)301行 的json