Scrapy框架
什么是scrapy
Scrapy是一個為了爬取網(wǎng)站數(shù)據(jù),提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,我們只需要實現(xiàn)少量的代碼,就能夠快速的抓取。
Scrapy使用了Twisted異步網(wǎng)絡(luò)框架,可以加快我們的下載速度。(Twisted(中文翻譯)扭曲)
入門文檔:https://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html

補充:
阻塞和非阻塞指的是拿到結(jié)果之前的狀態(tài)
異步和同步指的是整個過程
| 功能 | 解釋 | scrapy |
|---|---|---|
| Scrapy Engine(引擎) | 總指揮:負責(zé)數(shù)據(jù)和信號在不同模塊的傳遞 | scrapy已經(jīng)實現(xiàn) |
| Scheduler(調(diào)度器) | 一個隊列,存放引擎發(fā)過來的request請求 | scrapy已經(jīng)實現(xiàn) |
| Downloader(下載器) | 下載把引擎發(fā)過來的requests請求,并返回引擎 | scrapy已經(jīng)實現(xiàn) |
| Spider(爬蟲) | 處理引擎發(fā)來的response,提取數(shù)據(jù),提取url,并交給引擎 | 需要手寫 |
| Item Pipeline(管道) | 處理引擎?zhèn)鬟^來的數(shù)據(jù),比如存儲 | 需要手寫 |
| Downloader Middlewares(下載中間件) | 可以自定義的下載擴展,比如設(shè)置代理 | 一般不用手寫 |
| Spider MiddlewaresSpider(中間件) | 可以自定義requests請求和進行response過濾 | 一般不用手寫 |
文件目錄
scrapy.cfg #項目的配置文件
items.py #提取要爬取的字段,字典保存爬取到的數(shù)據(jù)的容器
middlewares #自定義中間件的地方
pipelines.py #管道,保存數(shù)據(jù)
settings.py #項目的設(shè)置文件 設(shè)置文件,UA,啟動管道
spiders #存儲爬蟲代碼目錄
itcast.py #寫爬蟲的文件
爬蟲步驟:
1.創(chuàng)建一個scrapy項目
scrapy startproject mySpider #mySpider是項目名字2.生成一個爬蟲
scrapy genspider itcast itcast.cn #itcast是爬蟲名字,"itcast.cn"限制爬蟲地址,防止爬到其他網(wǎng)站3.提取數(shù)據(jù)
完善spiders,使用xpath等方法3.保存數(shù)據(jù)
pipelines中保存數(shù)據(jù)
啟動爬蟲
scrapy crawl 爬蟲名字 #crawl(抓取的意思)
啟動爬蟲不打印日志
scrapy crawl 爬蟲名字 --nolog
run.py啟動爬蟲
from scrapy import cmdline
cmdline.execute("scrapy crawl lagou".split())

spider內(nèi)容
spider翻頁
# -*- coding: utf-8 -*-
import scrapy
#導(dǎo)入items
from tencent.items import TencentItem
#自定義spider類,繼承自scrapy.Spider
class ItcastSpider(scrapy.Spider):
name = 'itcast' #爬蟲名字<爬蟲啟動時候使用:scrapy crawl itcast>
#允許爬取的范圍,防止爬蟲爬到了別的網(wǎng)站
allowed_domains = ['tencent.com']
#開始爬取的地址,下載中間件提取網(wǎng)頁數(shù)據(jù)
start_urls = ['https://hr.tencent.com/position.php']
#數(shù)據(jù)提取方法,接收下載中間件傳過來的response(響應(yīng))
def parse(self, response):
#處理start_url地址對應(yīng)的響應(yīng)
#提取數(shù)據(jù)
# reti = response.xpath("http://div[@class='tea_con']//h3/text()").extract()
# print(reti)
#分組,[1:-1]切片,不要第一條數(shù)據(jù)
li_list = response.xpath("http://table[@class="tablelist"]/tr")[1:-1]
for li in li_list:
#在item中定義要爬取的字段,以字典形式傳入
item = TencentItem()
item["name"] = li.xpath(".//h3/text()").extract_first()
item["title"] = li.xpath(".//h4/text()").extract_first()
#yield可以返回request對象,BaseItem(items.py中的類),dict,None
yield item #yield傳到pipeline
#找到下一頁url地址
next_url = response.xpath('//a[@id="next"]/@href').extract_first()
#如果url地址的href="地址"不等于javascript:;
if next_url != "javascript:;":
next_url = "https://hr.tencent.com/"+ next_url
#把next_url的地址通過回調(diào)函數(shù)callback交給parse方法處理
yield scrapy.Request(next_url,callback=self.parse)
提取數(shù)據(jù)
response.xpath('//a[@id="next"]/@href')body = response.text.replace('\n', '').replace('\r', '').replace('\t', '')
re.findall('<a title=".?" href="(.?)"', body)
從選擇器中提取字符串:
- extract() 返回一個包含有字符串數(shù)據(jù)的列表
- extract_first()返回列表中的第一個字符串
注意:
- spider中的parse方法名不能修改
- 需要爬取的url地址必須要屬于allow_domain(允許_域)下的連接
- respone.xpath()返回的是一個含有selector對象的列表
為什么要使用yield?
讓整個函數(shù)變成一個生成器,變成generator(生成器)有什么好處?
每次遍歷的時候挨個讀到內(nèi)存中,不會導(dǎo)致內(nèi)存的占用量瞬間變>高python3中range和python2中的xrange同理
scrapy.Request常用參數(shù)為
callback = xxx:指定傳入的url交給那個解析函數(shù)去處理
meta={"xxx":"xxx"}:實現(xiàn)在不同的解析函數(shù)中傳遞數(shù)據(jù),配合callback用
dont_filter=False:讓scrapy的去重不會過濾當前url,默認開啟url去重
headers:請求頭
cookies:cookies,不能放在headers中,獨立寫出來
method = "GET":請求方式,(GET和POST)
爬取詳細頁和翻頁
# -*- coding: utf-8 -*-
import scrapy
from yangguang.items import YangguangItem
class YgSpider(scrapy.Spider):
name = 'yg'
allowed_domains = ['sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=0']
def parse(self, response):
tr_list = response.xpath("http://div[@class='greyframe']/table[2]/tr/td/table/tr")
for tr in tr_list:
item = YangguangItem()
item["title"] = tr.xpath("./td[2]/a[@class='news14']/@title").extract_first()
item["href"] = tr.xpath("./td[2]/a[@class='news14']/@href").extract_first()
item["publish_date"] = tr.xpath("./td[last()]/text()").extract_first()
#執(zhí)行進入url地址,再把item傳到下面parse_detail,提取詳細頁的內(nèi)容
yield scrapy.Request(item["href"],callback=self.parse_detail,meta={"item":item})
#翻頁
#獲取url地址
next_url = response.xpath("http://a[text()='>']/@href").extract_first()
#如果下一頁url地址不為空,進入下一頁連接
if next_url is not None:
yield scrapy.Request(next_url,callback=self.parse)
#處理詳情頁
def parse_detail(self,response):
#item接收meta傳過來的item,在item字典里繼續(xù)為item添加內(nèi)容
item = response.meta["item"]
#拿到詳細頁的內(nèi)容
item["content"] = response.xpath("http://div[@class='c1 text14_2']//text()").extract()
#拿到詳細頁的圖片地址
item["content_img"] = response.xpath("http://div[@class='c1 text14_2']//img/@src").extract()
#給圖片前面加上http://wz.sun0769.com
item["content_img"] = ["http://wz.sun0769.com" + i for i in item["content_img"]]
#把item傳給pipeline
yield item
items(存儲爬取字段)
import scrapy
#scrapy.Item是一個字典
class TencentItem(scrapy.Item):
#scrapy.Field()是一個字典
url = scrapy.Field()
name = scrapy.Field()
使用pipeline(管道)
from demo1 import settings
import pymongo
class Demo1Pipeline(object):
def __init__(self):
#連接mongodb數(shù)據(jù)庫(數(shù)據(jù)庫地址,端口號,數(shù)據(jù)庫)
client = pymongo.MongoClient(host=settings.MONGODB_HOST, port=settings.MONGODB_PORT)
#選擇數(shù)據(jù)庫和集合
self.db = client[settings.MONGODB_DBNAME][settings.MONGODB_DOCNAME]
def process_item(self, item, spider):
data = dict(item)
self.db.insert(data)
#完成pipeline代碼后,需要在setting中設(shè)置開啟
ITEM_PIPELINES = {
#開啟管道,可以設(shè)置多個管道,'管道地址數(shù)值':越小越先執(zhí)行
'mySpider.pipelines.MyspiderPipeline': 300,
}
# MONGODB 主機環(huán)回地址127.0.0.1
MONGODB_HOST = '127.0.0.1'
# 端口號,默認是27017
MONGODB_PORT = 27017
# 設(shè)置數(shù)據(jù)庫名稱
MONGODB_DBNAME = 'DouBan'
# 存放本次數(shù)據(jù)的表名稱
MONGODB_DOCNAME = 'DouBanMovies'
第二種:
class MyspiderPipeline(object):
def __init__(self):
#連接mongodb數(shù)據(jù)庫(數(shù)據(jù)庫地址,端口號,數(shù)據(jù)庫)
client = pymongo.MongoClient(host=settings.MONGODB_HOST, port=settings.MONGODB_PORT)
#選擇數(shù)據(jù)庫和集合
self.db = client[settings.MONGODB_DBNAME]
#實現(xiàn)存儲方法,item是spider傳過來的,spider就是自己寫的爬蟲
def process_item(self, item, spider):
table = ''
#通過spider參數(shù),可以針對不同的Spider進行處理
#spider.name爬蟲的名字
if spider.name == "itcast":
#如果爬蟲的名字為itcast執(zhí)行這里面的東西
table = self.db.表名
#如果爬蟲的名字為itcast2執(zhí)行這里面的東西
elif spider.name == "itcast2":
table = self.db.表名
table.insert(dict(item))
#也可以通過item參數(shù),可以針對不同的Item進行處理
table = ''
if isinstance(item, 爬蟲名字):
table = self.db.表名
table.insert(dict(item))
mysql存儲
from pymysql import connect
import pymysql
class TxPipeline(object):
def __init__(self):
self.conn=connect(host='localhost',port=3306,db='txzp',user='root',passwd='root',charset='utf8')
self.cc = self.conn.cursor()
def process_item(self, item, spider):
print(item["title"],item["href"],item["number"],item["time"],item["duty"])
aa = (item["title"],item["href"],item["number"],item["time"],item["duty"],item["requirement"])
sql = '''insert into tx values (0,"%s","%s","%s","%s","%s","%s")'''
self.cc.execute(sql%aa)
self.conn.commit()#提交
# self.cc.close() #關(guān)閉游標會報錯
注意
- pipeline中process_item方法名不能修改,修改會報錯
- pipeline(管道)可以有多個
- 設(shè)置了pipelines必須開啟管道,權(quán)重越小優(yōu)先級越高
為什么需要多個pipeline:
- 可能會有多個spider,不同的pipeline處理不同的item的內(nèi)容
- 一個spider的內(nèi)容可能要做不同的操作,比如存入不同的數(shù)據(jù)庫中
簡單設(shè)置LOG(日志)
為了讓我們自己希望輸出到終端的內(nèi)容能容易看一些:
我們可以在setting中設(shè)置log級別
在setting中添加一行(全部大寫):
LOG LEVEL="WARNING"
默認終端顯示的是debug級別的log信息
logging模塊的使用
scrapy中使用logging
#settings中設(shè)置
LOG_LEVEL=“WARNING”
LOG_FILE="./a.log" #設(shè)置日志保存的位置,設(shè)置會后終端不會顯示日志內(nèi)容
#打印logging日志
import logging
#實例化logging,顯示運行文件的名字,不寫不會顯示運行文件的目錄
logging = logging.getLogger(__name__)
#日志輸出打印
logging.warning(item)
#打印內(nèi)容(日志創(chuàng)建時間,運行文件的目錄,日志級別,打印的內(nèi)容)
2018-10-31 15:25:57 [mySpider.pipelines] WARNING: {'name': '胡老師', 'title': '高級講師'}
普通項目中使用logging
具體參數(shù)信息:https://www.cnblogs.com/bjdxy/archive/2013/04/12/3016820.html
#a.py文件
import logging
#level: 設(shè)置日志級別,默認為logging.WARNING
logging.basicConfig(level=logging.INFO,
format=
#日志的時間
'%(asctime)s'
#日志級別名稱 : 當前行號
' %(levelname)s [%(filename)s : %(lineno)d ]'
#日志信息
' : %(message)s'
#指定時間格式
, datefmt='[%Y/%m/%d %H:%M:%S]')
#實例化logging,顯示當前運行文件的名字,不寫不會顯示運行文件的目錄
logging=logging.getLogger(__name__)
if __name__ == '__main__':
#日志級別打印信息
logging.info("this is a info log")
b.py文件使用a.py文件的logging(日志)
#b.py文件
from a import logging #導(dǎo)入a.py中的實例logging
if __name__ == '__main__':
#warning級別大于info也可以打印,debug級別小于info,不可以打印
logger.warning("this is log b")
日志級別:
- debug #調(diào)試
- info #正常信息
- warning #警告
- error #錯誤
如果設(shè)置日志級別為info,warning級別比info大,warning也可以打印,debug比info小不可以打印
如果設(shè)置日志級別為warning,info和debug都比warning小,不可以打印
把數(shù)據(jù)保存到mongodb中
#導(dǎo)入mongodb的包
from pymongo import MongoClient
#實例化client,建立連接
client = MongoClient(host='127.0.0.1',port = 27017)
#選擇數(shù)據(jù)庫和集合
collection = client["tencent"]["hr"]
class TencentPipeline(object):
def process_item(self, item, spider):
#傳過來的數(shù)據(jù)是對象,把item轉(zhuǎn)化為字典
item = dict(item)
#把數(shù)據(jù)存入mongodb數(shù)據(jù)庫
collection.insert(item)
print(item)
return item
scrapy shell
Scrapy shell是一個交互終端,我們可以在未啟動spider的情況下嘗試及調(diào)試代碼,也可以用來測試XPath表達式
使用方法:
命令行輸入:
scrapy shell http://www.itcast.cn/channel/teacher.shtml
常用參數(shù):
response.url:當前響應(yīng)的url地址
response.request.url:當前響應(yīng)對應(yīng)的請求的url地址
response.headers:響應(yīng)頭
response.body:響應(yīng)體,也就是html代碼,默認是byte類型
response.body.decode():變?yōu)樽址愋?response.request.headers:當前響應(yīng)的請求頭
response.xpath("http://h3/text()").extract():調(diào)試xpath,查看xpath可不可以取出數(shù)據(jù)
setting設(shè)置文件
為什么需要配置文件:
- 配置文件存放一些公共的變量(比如數(shù)據(jù)庫的地址,賬號密碼等)
- 方便自己和別人修改
- 一般用全大寫字母命名變量名SQL_HOST='192.168.0.1'
參考地址:https://blog.csdn.net/u011781521/article/details/70188171
#常見的設(shè)置
#項目名
BOT_NAME = 'yangguang'
#爬蟲位置
SPIDER_MODULES = ['yangguang.spiders']
NEWSPIDER_MODULE = 'yangguang.spiders'
#遵守robots協(xié)議,robots.txt文件
ROBOTSTXT_OBEY = True
#下載延遲,請求前睡3秒
DOWNLOAD_DELAY = 3
# 默認請求頭,不能放瀏覽器標識
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
"Cookie": "rfnl=https://www.guazi.com/sjz/dazhong/; antipas=2192r893U97623019B485050817",
}
#項目管道,保存數(shù)據(jù)
ITEM_PIPELINES = {
'yangguang.pipelines.YangguangPipeline': 300,
}
spiders文件使用settings的配置屬性
#第一種
self.settings["MONGO_HOST"]
#第二種
self.settings.get("MONGO_HOST")
pipelines文件使用settings的配置屬性
spider.settings.get("MONGO_HOST")
Scrapy中CrawlSpider類
深度爬蟲
#創(chuàng)建CrawlSpider爬蟲,就多加了-t crawl
scrapy genspider -t crawl cf gov.cn
第一種用法:提取內(nèi)容頁和翻頁
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from tengxun.items import TengxunItem
class TxSpider(CrawlSpider):
name = 'tx'
allowed_domains = ['hr.tencent.com']
#第一次請求的url
start_urls = ['https://hr.tencent.com/position.php']
#rules自動提取url地址
rules = (
# 內(nèi)容頁,交給parse_item處理數(shù)據(jù)
Rule(LinkExtractor(allow=r'position_detail\.php\?id=\d+&keywords=&tid=0&lid=0'), callback='parse_item'),
# 翻頁
Rule(LinkExtractor(allow=r'position\.php\?&start=\d+#a'), follow=True),
)
#處理內(nèi)容頁的數(shù)據(jù)
def parse_item(self, response):
item = TengxunItem()
#爬取標題
item["bt"] = response.xpath('//td[@id="sharetitle"]/text()').extract_first()
#爬取工作要求
item["gzyq"] = response.xpath('//div[text()="工作要求:"]/../ul/li/text()').extract()
yield item
第二種用法:提取標題頁,內(nèi)容,翻頁
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from tengxun.items import TengxunItem
class Tx2Spider(CrawlSpider):
name = 'tx2'
allowed_domains = ['hr.tencent.com']
start_urls = ['https://hr.tencent.com/position.php']
rules = (
#翻頁
Rule(LinkExtractor(allow=r'position\.php\?&start=\d+#a'), callback='parse_item', follow=True),
)
#標題頁內(nèi)容
def parse_item(self, response):
tr_list = response.xpath('//table[@class="tablelist"]/tr')[1:-1]
for tr in tr_list:
item = TengxunItem()
#爬取標題
item['bt'] = tr.xpath('./td/a/text()').extract_first()
#爬取url
item['url'] = tr.xpath('./td/a/@href').extract_first()
item['url'] = "https://hr.tencent.com/" + item['url']
yield scrapy.Request(
item['url'],
callback=self.parse_detail,
meta={"item":item}
)
#爬取內(nèi)容
def parse_detail(self,response):
item = response.meta['item']
item['gzyq'] = response.xpath('//div[text()="工作要求:"]/../ul/li/text()').extract()
yield item
#LinkExtractor 連接提取器,提取url地址
#callback 提取出來的url地址的response會交給callback處理
#follow 當前url地址的響應(yīng)是否重新進過rules來提取url地址
#提取詳細頁的url
#CrawlSpider會自動把url補充完整
Rule的匹配細節(jié)
Rule(LinkExtractor(allow=r'position_detail\.php\?id=\d+&keywords=&tid=0&lid=0'), callback='parse_item'),
#這里把該匹配的東西寫成正則
#?和.別忘了轉(zhuǎn)義\? \.
#LinkExtractor 連接提取器,提取url地址
#callback 提取出來的url地址的response會交給callback處理
#follow 當前url地址的響應(yīng)是否重新進過rules來提取url地址
#提取詳細頁的url
#CrawlSpider會自動把url補充完整
注意點:
- 用命令創(chuàng)建一個crawlspider的模板:scrapy genspider-t crawl 爬蟲名字 域名,也可以手動創(chuàng)建
- CrawiSpider中不能再有以parse為名字的數(shù)據(jù)提取方法,這個方法被CrawlSpider用來實現(xiàn)基礎(chǔ)url提取等功能)
- 一個Rule對象接收很多參數(shù),首先第一個是包含url規(guī)則的LinkExtractor對象,常用的還有calback(制定滿足規(guī)則的url的解析函數(shù)的字符串)和follow(response中提取的鏈接是否需要跟進)
- 不指定callback函數(shù)的請求下,如果follow為True,滿足該rule的url還會繼續(xù)被請求
- 如果多個Rule都滿足某一個url,會從rules中選擇第一個滿足的進行操作
CrawlSpider補充(了解)
LinkExtractor更多常用鏈接
LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm')
allow:滿足括號中"正則表達式"的URL會被提取,如果為空,則全部匹配.
deny:滿足括號中"正則表達式"的URL一定不提取(優(yōu)先級高于allow).
allow_domains:會被提取的鏈接的domains.
deny_domains:一定不會被提取鏈接的domains.
restrict_xpaths:使用xpath表達式,和allow共同作用過濾鏈接,級xpath滿足范圍內(nèi)的uri地址會被提取
rule常見參數(shù):
Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item', follow=False),
LinkExtractor:是一個Link Extractor對象,用于定義需要提取的鏈接.
callback:從link_extractor中每獲取到鏈接時,參數(shù)所指定的值作為回調(diào)函數(shù)
follow:是一個布爾(boolean)值,指定了根據(jù)該規(guī)則從response提取的鏈接是否需要跟進.如果callback為None,follow 默認設(shè)置為True,否則默認為False.
process_links:指定該spider中哪個的函數(shù)將會被調(diào)用,從link_extractor中獲取到鏈接列表時將會調(diào)用該函數(shù),該方法主要用來過濾url.
process_request:指定該spider中哪個的函數(shù)將會被調(diào)用,該規(guī)則提取到每個request時都會調(diào)用該函數(shù),用來過濾request
Scrapy分布式爬蟲

Scrapy_redis之domz
domz相比于之前的spider多了持久化和request去重的功能
domz就是Crawlspider去重和持久化版本
不能分布式
可以分布式的是RedisSpider和RedisCrawlspider
Scrapy redis在scrapy的基礎(chǔ)上實現(xiàn)了更多,更強大的功能,具體體現(xiàn)在:reqeust去重,爬蟲持久化,和輕松實現(xiàn)分布式
官方站點:https://github.com/rmax/scrapy-redis
#spiders文件夾
爬蟲內(nèi)容和自己寫的CrawlSpider沒有任何區(qū)別
settings.py
#寫上下面東西Crawlspider就可以去重了
#還可以持久化爬蟲,關(guān)閉后,在開啟繼續(xù)爬取
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" #去重
SCHEDULER = "scrapy_redis.scheduler.Scheduler" #重寫調(diào)度器(scheduler)
SCHEDULER_PERSIST = True #不清楚緩存,隊列中的內(nèi)容是否持久保存(開啟后爬蟲關(guān)閉后,下次開啟從關(guān)閉的位置繼續(xù)爬取)
ITEM_PIPELINES = {
#將數(shù)據(jù)保存到redis中,屏蔽這條命令
#'scrapy_redis.pipelines.RedisPipeline': 400,
}
#指定redis地址
REDIS_URL = 'redis://127.0.0.1:6379'
#也可以寫成下面形式
#REDIS_HOST = "127.0.0.1"
#REDIS_PORT = 6379
我們執(zhí)行domz的爬蟲,會發(fā)現(xiàn)redis中多了一下三個鍵:
dmoz:requests (zset類型)(待爬取)
Scheduler隊列,存放的待請求的request對象,獲取的過程是pop操作,即獲取一個會去除一個dmoz:dupefilter (set)(已爬取)
指紋集合,存放的是已經(jīng)進入scheduler隊列的request對象的指紋,指紋默認由請求方法,url和請求體組成dmoz:items (list類型)(item信息)
存放的獲取到的item信息,在pipeline中開啟RedisPipeline才會存入
Scrapy_redis之RedisSpider
from scrapy_redis.spiders import RedisSpider
#繼承RedisSpider
class MySpider(RedisSpider):
#指定爬蟲名
name='myspider_redis'
#指定redis中start_urls的鍵,
#啟動的時候只需要往對應(yīng)的鍵總存入url地址,不同位置的爬蟲就會來獲取該url
#所以啟動爬蟲的命令分類兩個步驟:
#(1)scrapy crawl myspider_redis(或者scrapy runspider myspider_redis)讓爬蟲就緒
#(2)在redis中輸入lpush myspider:start_urls"http://dmoztools.net/"讓爬蟲從這個ur開始爬取
redis_key ='myspider:start_urls'
#手動指定allow_domain,執(zhí)行爬蟲范圍
#可以不寫
allow_doamin=["dmoztools.net"]
def parse(self, response):
#普通scrapy框架寫法
...
啟動
#爬蟲名字
scrapy runspider myspider
或(2選1)
#蜘蛛文件名字
scrapy runspider myspider.py
redis運行
#redis 添加 鍵:值 "爬取的網(wǎng)址"
redis-c1i lpush guazi:start_urls "http://ww.guazi.com/sjz/dazhong/"
Scrapy_redis之RedisCrawlSpider
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from scrapy_redis.spiders import RedisCrawlSpider
#繼承RedisCrawlSpider
class MyCrawler(RedisCrawlSpider):
#爬蟲名字
name='mycrawler_redis'
#start_url的redis的鍵
redis_key='mycrawler:start_urls'
#手動制定all_domains,可以不寫
allow_domains=["dmoztools.net"]
#和crawl一樣,指定url的過濾規(guī)則
rules=(
Rule(LinkExtractor(),callback='parse_page',follow=True)
啟動
#爬蟲名字
scrapy runspider myspider
或(2選1)
#蜘蛛文件名字
scrapy runspider myspider.py
redis運行
#redis 添加 鍵:值 "爬取的網(wǎng)址"
redis-c1i lpush guazi:start_urls "http://ww.guazi.com/sjz/dazhong/"
快速啟動爬蟲
from scrapy import cmdline
cmdline.execute("scrapy crawl guazicrawl".split())
# import redis
#
# r=redis.StrictRedis()
# r.lpush("myspider:start_urls",[])
其他參數(shù)
- 如果抓取的url不完整,沒前面的url,可以使用下面方法
import urllib
a = http://www.baidu.com?123
b = ?456
#在程序中a可以使用response.url(響應(yīng)地址)
#在pycharm中parse顏色會加深,不過沒事
b = urllib.parse.urljoin(a,b)
print("b=%s"%b)
#b=http://www.baidu.com?456
存多個url或其他東西,可以用列表存儲
#比如存圖片連接,一個網(wǎng)頁中有很多圖片連接
item["img_list"] =[]
#extend追加的方式,注意后面用.extract()
item["img_list"].extend(response.xpath('//img[@class="BDE_Image"]/@src').extract())