歡迎大家關注公眾號【哈希大數據】
前面我們已經介紹了scrapy的安裝、入門教程,以及MongoDB的安裝與配置,本篇將分享如何利用scrapy爬取百度新聞信息,並將爬取到的數據存儲到MongoDB資料庫中。
抓取目標
通過給定關鍵字,爬取百度新聞中搜索到的所有有關新聞信息,新聞標題、新聞連結、新聞來源。
技術路線
利用scrapy框架實現此次爬取,利用parse函數獲得需要抓取的信息,通過items和piplinepipelines的設置實現數據存儲到MongoDB資料庫中,通過middleware設置user_agent降低網站對爬蟲的限制,使得爬取速度可在一個較高的水平上。
目標站點分析
Python爬蟲實戰系列(3)中已經介紹了如何利用chrome瀏覽器獲取對應標籤的XPATH或CSS路徑,本次獲取新聞信息,採用的解析方式是CSS。
程序的結構設計
步驟1:打開命令行窗口,進入想新建項目的目錄
步驟2:在命令行中輸入:scrapy startproject xxxx(項目名稱) 新建一個項目
步驟3:進入項目文件,在命令行中輸入:scrapy genspider <爬蟲名稱> <爬取網址>新建爬蟲
步驟3:更改items.py文件,設置item
步驟4:編寫爬取代碼
步驟5:更改pipelines和middlewares
步驟6:啟動爬蟲,打開命令行進入到項目目錄下,輸入:scrapy crawl <爬蟲名稱>
items.py代碼如下:
# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# http://doc.scrapy.org/en/latest/topics/items.htmlfrom scrapy import Item, Fieldclass mmwzItem(Item):# define the fields for your item here like: # name = Field() article_title = Field() article_url = Field() article_catchroad = Field() article_source = Field()
本例子的爬蟲名稱為:xinwen,爬蟲文件xinwen.py的代碼為:
# -*- coding: utf-8 -*-from urllib.parse import urlencodeimport refrom scrapy import Spider, Requestfrom scrapy_mmwz.items import mmwzItemclass XinwenSpider(Spider):name = "xinwen" keyword = '比特幣' page = 0 #查詢信息 data = { 'word': keyword, 'pn': page, 'cl': '2', 'ct': '1', 'tn': 'news', 'rn': '20', 'ie': 'utf - 8', } # 生成URL的參數部分 params = urlencode(data) base = 'http://news.baidu.com/ns?' url = base + params allowed_domains = ["news.baidu.com"] start_urls = [url] def parse(self, response): item = mmwzItem() if response.status == 200: news_lists = response.css('#wrapper_wrapper #content_left div.result') page_number = response.css('p#page strong span.pc::text').extract_first() # print(news_lists) print('page_number:', page_number) if news_lists: for news in news_lists: # news_lists是一個生成器,在調用函數是可以用for循環依次獲取結果 lists = { 'article_url': news.css('.c-title a::attr(href)').extract_first(), 'article_title': news.css('.c-title a::text').extract_first(), 'article_catchroad': 'baidu', 'article_source': re.search(re.compile('(.*?)\\xa0', re.S), news.css('p.c-author::text').extract_first()).group(1) } for field in item.fields: if field in lists.keys(): item[field] = lists.get(field) # 它相當於return只不過一次返回一個 yield item print(response.css('p#page a:last-child::text').extract_first()) if response.css('p#page a:last-child::text').extract_first() == '下一頁>': # 獲取下一頁鏈接 next_page = 'http://news.baidu.com' + response.css('p#page a:last-child::attr(href)').extract_first() # 實現循環獲取下一頁內容 yield Request(next_page, callback=self.parse)
通過pipelines設置,將爬取到的數據成功保存到MongoDB資料庫中,設置詳細代碼如下:
# -*- coding: utf-8 -*-# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.htmlimport pymongoclass MongoPipeline(object):collection_name = 'xinwen' def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE', 'items') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def close_spider(self, spider): self.client.close() # def process_item(self, item, spider): # self.db['user'].update({'url_token': item['url_token']}, {'$set': item}, True) # # return item def process_item(self, item, spider): self.db[self.collection_name].insert(dict(item)) return item
這裡需要注意兩點,第一首先安裝pymongo包,第二在settings.py文件做如下設置:
MONGO_URI = 'localhost'MONGO_DATABASE = 'xinwen'
settings.py文件中還有一個需要特別注意的是:
# Obey robots.txt rulesROBOTSTXT_OBEY = False
非常多的網站都有robots協議,不允許爬取本網站信息,如果這個參數設置為True,非常多的網站都不能爬取了。
完整項目代碼請參考我的GitHub:https://github.com/kxylxx/scrapy_testproject
為了方便查看爬取到的信息,這裡給大家推薦一個MongoDB可視化軟體Robo 3T,詳細安裝使用教程請參考:https://www.cnblogs.com/dacongge/p/7346037.html ,感謝大蔥哥的分享。
結果展示及小結
獲取到的數據如下圖所示:
小結:
通過本次實戰希望大家對scrapy框架有更深刻的認識,希望能夠根據該案例設計一個基於scrapy框架的爬蟲程序,以熟悉整個爬取流程。希望大家能夠自己敲寫代碼,在敲代碼的過程中發現問題解決問題。