新建爬蟲項目
scrapy startproject 項目名稱
創(chuàng)建爬蟲文件
scrapy genspider 爬蟲文件名稱 要爬取的目標url的域(baidu.com)
運行爬蟲
scrapy crawl 爬蟲名稱
以jobble為例:
- 創(chuàng)建項目:scrapy startproject jobbleproject
- 進入jobbleproject/jobbleproject/spider目錄,新建爬蟲文件:scrapy genspider jobble jobble.com
- 打開item文件:根據目標網站分析需要提取的數據,在item.py文件中添加需要獲取的字段
class JobboleItem(scrapy.Item):
# define the fields for your item here like:
#標題
title = scrapy.Field()
#創(chuàng)建時間
create_date = scrapy.Field()
#文章地址
url = scrapy.Field()
#id
url_object_id = scrapy.Field()
#文章圖片
front_image_url = scrapy.Field()
#文章圖片地址
front_image_path = scrapy.Field()
# 點贊數
praise_nums = scrapy.Field()
#收藏數
bookmark_nums = scrapy.Field()
# 評論數
comment_nums = scrapy.Field()
#文章內容
content = scrapy.Field()
#標簽
tags = scrapy.Field()
# 插入數據庫語句
- 打開 jobboleproject/spider目錄里的 jobbole.py,默認增加了下列代碼:(也可以自行創(chuàng)建文件并添加以下代碼)
class JobboleSpider(scrapy.Spider):
name = 'jobbole' # 爬蟲名稱
allowed_domains = ['jobbole.com'] # url的域
start_urls = ['http://blog.jobbole.com/all-posts/'] # 目標url(起始URL)
def parse(self, response):
pass
- 在parse方法中做數據的提取(可參考之前介紹的幾種提取數據方法,以下介紹如何使用)
def parse(self, response):
# 獲取url
response.url
# 使用item設置的字段
from jobbleproject.items import JobbleItems
#
# 使用xpath提取數據,scrapy提前封裝好可以直接使用
response.xpath('xpath語法')
# css選擇器
response.css('div.a div#q')
# 通過以上方法得到的是Selector類型,用以上方法轉化成字符串
response.xpath('xpath語法').extact_first('如果沒有提取到數據或數據為空可設置一個默認值') --> 獲取一個并且是第一個
response.css('div.a div#q').extract() -->獲取所有,返回一個列表
# 把獲取到的數據交給管道做下載等任務
yield response.xpath('....')
# 發(fā)起一個請求
"""
url:設置請求的url地址
callback=None:設置請求的回調方法
method='GET'請求方式,默認為get請求
headers=None,設置請求頭,字典類型
cookies=None,設置cookies信息,模擬用戶登錄,字典類型
meta=None:傳遞參數(字典類型)
encoding='utf-8':設置編碼
dont_filter=False,是否要去重,默認為False,表示去重
errback=None,請求失敗后的回調
"""
yield scrapy.Request(firstURL,callback=self.parse_tags_page)
- settings文件:設置請求頭,UA,全局的請求頭,激活管道、cookie、下載中間件,下載延時等等
# 是否遵守robot協(xié)議(默認為True表示遵守)
ROBOTSTXT_OBEY = False
# 是否攜帶cookie值,默認為遵守
COOKIES_ENABLED = False
# UA
DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'
}
# 下載中間件
DOWNLOADER_MIDDLEWARES = {
'jobble.middlewares.ChufangDownloaderMiddleware': 543,
}
# 激活管道
ITEM_PIPELINES = {
'jobble.pipelines.ChufangPipeline': 300,
}
# mysql 數據庫的信息
MYSQL_HOST = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_pwd = 'XXX'
MYSQL_DB = 'jobble'
MYSQL_PORT = 3306
MYSQL_CHARSET = 'utf8'
# 代理
PROXIES = [
{'ip_port': '61.128.208.94:3128','user_pwd': None},
{'ip_port': '61.128.208.94:3128','user_pwd': ‘XXX’}
]
# mongodb數據庫配置信息
MONGO_HOST = '127.0.0.1'
MONGO_PORT = 27017
MONGO_DB = 'jobble'
- 管道piplines:
import scrapy
from jobbleproject.items import JobboleItem
class jobblezprojectPipeline(object):
def __init__(self):
"""
初始化方法
"""
self.client = pymysql.Connect(
'127.0.0.1','root','XXX','jobble',3306,charset='utf8'
)
self.cursor = self.client.cursor()
# self.mongo_client = pymongo.MongoClient(host='127.0.0.1',port=27017)
def open_spider(self,spider):
"""
爬蟲啟動的時候會調用一次
:param spider:
:return:
"""
print('爬蟲開啟')
def process_item(self, item, spider):
"""
做數據持久化
這個方法是必須實現(xiàn)的,爬蟲文件中的所有ITEM
都會經過這個方法
:param item: 爬蟲文件傳遞過來的item對象
:param spider: 爬蟲文件實例化的對象
:return:
"""
# mysql數據庫
sql,data = item.get_insert_sql_data(data_dict)
try:
# self.cursor.execute(sql,list(data_dict.values()))
self.cursor.execute(sql, data)
self.client.commit()
except Exception as err:
print(err)
self.client.rollback()
# 如果有多個管道文件,一定要注意return,item,
# 否則下一個管道無法接收到item
print('經過了管道')
return item
def close_spider(self,spider):
"""
爬蟲結束的時候會調用一次
:param spider:
:return:
"""
self.client.close()
self.cursor.close()
print('爬蟲結束')
mongo
class ChinazprojectPipeline(object):
def __init__(self,host,port,dbname):
# 創(chuàng)建連接
self.mongo_client = pymongo.MongoClient(host=host,port=port)
# 數據庫
self.db = self.mongo_client[dbname]
@classmethod
def from_crawler(cls,crawler):
"""
MONGO_HOST = '127.0.0.1'
MONGO_PORT = 27017
MONGO_DB = 'jobble'
:param crawler:
:return:
"""
host = crawler.settings['MONGO_HOST']
port = crawler.settings['MONGO_PORT']
db = crawler.settings['MONGO_DB']
return cls(host,port,db)
def process_item(self,item,info):
"""
:param item:
:param info:
:return:
"""
# 往哪個集合插入
col_name = item.get_mongo_collectionName()
col = self.db[col_name]
dict_data = dict(item)
try:
col.insert(dict_data)
print('數據插入成功')
except Exception as err:
print('失敗',err)
return item
def close_spider(self,spider):
"""
爬蟲結束的時候會調用一次
:param spider:
:return:
"""
self.mongo_client.close()
print('爬蟲結束')
- middleware:可設置下載中間件,作用:反爬蟲
# 設置UA
class UserAgentDownloadMiddlerware(object):
def process_request(self, request, spider):
from fake_useragent import UserAgent
User_Agent = UserAgent()
random_ua = User_Agent.random
if random_ua:
# print('經過了下載中間件', random_ua)
request.headers['User-Agent'] = random_ua
#代理
class ProxiesDownloadMiddlerware(object):
def process_request(self, request, spider):
import random
import base64
proxies = spider.settings['PROXIES']
proxy = random.choice(proxies)
if proxy['user_pwd'] is None:
# 沒有代理賬戶驗證的代理使用方式
request.meta['proxy'] = proxy['ip_port']
else:
# 對賬戶密碼進行base64編碼
user_pwd = base64.b64encode(proxy['user_pwd'].encode('utf-8')).decode('utf-8')
# 對應到代理服務器的信令格式里
request.headers['Proxy-Authorization'] = 'Basic ' + user_pwd
request.meta['proxy'] = proxy['ip_port']