用理工科思維看待這個(gè)世界
初學(xué)者狂魔,盡力實(shí)現(xiàn)最小化學(xué)習(xí)系統(tǒng)
主題:Scrapy 實(shí)戰(zhàn),并分別存儲(chǔ)在MySQL 和 Mongodb中
0:目標(biāo)說明
Scrapy 基礎(chǔ)教程
你要的最佳實(shí)戰(zhàn)劉未鵬博客
點(diǎn)我啊-
目標(biāo):獲取劉未鵬博客全站博文
- 文章標(biāo)題:
Title
- 文章發(fā)布時(shí)間:
Time
- 文章全文:
Content
- 文章的鏈接:
Url
- 文章標(biāo)題:
-
思路:
- 分析首頁和翻頁的組成
- 抓取全部的文章鏈接
- 在獲取的全部鏈接的基礎(chǔ)上解析需要的標(biāo)題淫痰,發(fā)布時(shí)間最楷,全文和鏈接
1:目標(biāo)分解
Scrapy
支持xpath
- 全部鏈接獲取
# 首頁和剩余的頁獲取鏈接的xpath有點(diǎn)差異
each_page_data = selector.xpath('//div[@id="index-featured1"]/ul/li/h3[@class="entry-title"]/a/@href').extract()
each_page_data_other = selector.xpath('//div[@id="content"]/div/ul/li/h3[@class="entry-title"]/a/@href').extract()
# 全部的url放在一個(gè)列表里:item_url
- 文章標(biāo)題
title = selector.xpath('//div[@id="content"]/div/h1[@class="entry-title"]/a/text()').extract()
- 文章發(fā)布時(shí)間
time = selector.xpath('//div[@id="content"]/div/div[@class="entry-info"]/abbr/text()').extract()
- 文章全文
content = selector.xpath('//div[@id="content"]/div/div[@class="entry-content clearfix"]/p/text()').extract()
- 文章鏈接
url = selector.xpath('//div[@id="content"]/div/h1[@class="entry-title"]/a/@href').extract()
使用Scrapy 框架的基本教程:
翻譯版教程
-
一般步驟
- 新建項(xiàng)目
- 定義Item :
items.py
文件是定義的抓取目標(biāo) - 編寫spider:
spiders
文件夾是用來編寫爬蟲文件 -
settings.py
文件是用來編寫配置文件比如頭部信息,一些常量待错,比如MySQL用戶籽孙,端口等 -
pipelines.py
文件是用來編寫存儲(chǔ)數(shù)據(jù)操作,比如MySQL數(shù)據(jù)庫的操作火俄,mongodb數(shù)據(jù)庫的操作
Scrapy 框架的原理
經(jīng)典說明文檔
* 引擎scrapy
* 調(diào)度器 scheduler
* 下載器 downloader
* 爬蟲 spider
* 項(xiàng)目管道 pipeline
運(yùn)行流程:
Scrapy運(yùn)行流程大概如下:
首先犯建,引擎從調(diào)度器中取出一個(gè)鏈接(URL)用于接下來的抓取
引擎把URL封裝成一個(gè)請(qǐng)求(Request)傳給下載器,下載器把資源下載下來瓜客,并封裝成應(yīng)答包(Response)
然后适瓦,爬蟲解析Response
若是解析出實(shí)體(Item),則交給實(shí)體管道進(jìn)行進(jìn)一步的處理。
若是解析出的是鏈接(URL),則把URL交給Scheduler等待抓取
2:目標(biāo)實(shí)戰(zhàn)
- 編寫Items 文件定義抓取目標(biāo)
class LiuweipengItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
Title = scrapy.Field() # 標(biāo)題
Time = scrapy.Field() # 發(fā)布時(shí)間
Url = scrapy.Field() # 文章鏈接
Content = scrapy.Field() # 文章內(nèi)容
- 編寫爬蟲程序
# 獲取整個(gè)網(wǎng)站的文章鏈接
class BlogSpider(Spider):
name = "liuweipeng"
start_urls = ["http://mindhacks.cn/","http://mindhacks.cn/page/2/", "http://mindhacks.cn/page/3/", "http://mindhacks.cn/page/4/"]
def parse(self, response):
url_item = []
selector = Selector(response)
each_page_data = selector.xpath('//div[@id="index-featured1"]/ul/li/h3[@class="entry-title"]/a/@href').extract()
each_page_data_other = selector.xpath('//div[@id="content"]/div/ul/li/h3[@class="entry-title"]/a/@href').extract()
url_item.extend(each_page_data)
url_item.extend(each_page_data_other)
for one in url_item:
yield Request(one, callback=self.parse_detail)
#------------------------------------------------------------------------------------------
# 對(duì)獲取的鏈接進(jìn)行內(nèi)容的解析
def parse_detail(self, response):
Item = LiuweipengItem()
selector = Selector(response)
title = selector.xpath('//div[@id="content"]/div/h1[@class="entry-title"]/a/text()').extract()
time = selector.xpath('//div[@id="content"]/div/div[@class="entry-info"]/abbr/text()').extract()
content = selector.xpath('//div[@id="content"]/div/div[@class="entry-content clearfix"]/p/text()').extract()
url = selector.xpath('//div[@id="content"]/div/h1[@class="entry-title"]/a/@href').extract()
print(content)
for title, time, content, url in zip(title, time, content, url):
Item["Title"] = title
Item["Time"] = time
Item["Content"] = content
Item["Url"] = url
yield Item
- 編寫設(shè)置文件(1):存儲(chǔ)mongodb
MONGODB_HOST = '127.0.0.1' # localhost
MONGODB_PORT = 27017 # 端口號(hào)
MONGODB_DBNAME = 'Liuweipeng' # 數(shù)據(jù)庫名
MONGODB_DOCNAME = 'blog' # 集合名
- 編寫管道文件谱仪,存儲(chǔ)數(shù)據(jù)mongodb
import pymongo
import pymysql
from scrapy.conf import settings
class LiuweipengPipeline(object):
def __init__(self):
host = settings['MONGODB_HOST']
port = settings['MONGODB_PORT']
dbName = settings['MONGODB_DBNAME']
client = pymongo.MongoClient(host=host, port=port)
tdb = client[dbName]
self.post = tdb[settings['MONGODB_DOCNAME']] # 初始化設(shè)置數(shù)據(jù)鏈接等信息
def process_item(self, item, spider):
content = dict(item)
self.post.insert(content) # 將抓取的數(shù)據(jù)插入mongodb
效果顯示:
- 存儲(chǔ)方式2:mysql
# 管道文件編寫方式改變?yōu)椋?# 這里導(dǎo)入的是pymysql
def __init__(self):
self.connection = pymysql.connect(host='localhost',
user='root',
password='123456',
port=3306,
db='test',
charset='utf8')
pass
def process_item(self, item, spider):
with self.connection.cursor() as cursor:
sql = "INSERT INTO `blog`(`Title`, `Time`, `Content`, `Url`) VALUES (%s, %s, %s, %s)"
cursor.execute(sql, (item['Title'],item["Time"], item["Content"],item["Url"]))
self.connection.commit()
- 需要在本地創(chuàng)建數(shù)據(jù)表:
# 在test數(shù)據(jù)庫中創(chuàng)建一個(gè)blog的數(shù)據(jù)表玻熙,定義字段如下所示:
CREATE TABLE `blog` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`Title` VARCHAR(255) COLLATE utf8_bin NOT NULL,
`Content` VARCHAR(255) COLLATE utf8_bin NOT NULL,
`Time` VARCHAR(255) COLLATE utf8_bin NOT NULL,
`Url` VARCHAR(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
AUTO_INCREMENT=1 ;
效果顯示2:
完整版代碼:不點(diǎn)不知道bug
3:總結(jié)全文
使用Scrapy
框架實(shí)現(xiàn)抓取博客,并分別使用兩種存儲(chǔ)方式疯攒。
目標(biāo)分析的很詳細(xì)了嗦随。
再補(bǔ)一句:任何實(shí)用性的東西都解決不了你所面臨的實(shí)際問題,但為什么還有看卸例?為了經(jīng)驗(yàn)称杨,為了通過閱讀抓取別人的經(jīng)驗(yàn),雖然還需批判思維看待
崇尚的思維是:
了解這是什么筷转。
知道應(yīng)該怎么做。
學(xué)會(huì)親自動(dòng)手悬而。(事實(shí)上這是我第一次使用Scrapy 框架存儲(chǔ)在mysql中呜舒,還是遇到了好些問題)
關(guān)于本人:
只有一個(gè)職業(yè):學(xué)生
只有一個(gè)任務(wù):學(xué)習(xí)
在這條路上,充滿無盡的困境笨奠,我希望成為一個(gè)精神世界豐滿的人袭蝗。