路飞学城-python爬虫密训-第三章
(一)學(xué)習(xí)心得
?其實(shí)在沒有正式學(xué)習(xí)python編程語言中,就知道模塊是python最重要部分之一。雖然在前面HTTP協(xié)議跟IO多路復(fù)用都沒有接觸學(xué)的也是一知半解,scrapy模塊比resquests模塊功能更加強(qiáng)大。當(dāng)然理解難度也是大了對(duì)于6月份中旬剛開始學(xué)習(xí)python基礎(chǔ)有點(diǎn)難啃。11號(hào)福建福州海經(jīng)歷了7月史上最強(qiáng)一次臺(tái)風(fēng),很遺憾我發(fā)現(xiàn)自己沒有辦法完成最后2次作業(yè),突然間覺得之前自己對(duì)爬蟲認(rèn)知太少,計(jì)算機(jī)知識(shí)儲(chǔ)量太少,希望在這次培訓(xùn)讓自己進(jìn)一步認(rèn)識(shí)到python與爬蟲,99元買了佩奇視頻我也覺得很值得。希望自己下次報(bào)課是自己是做好準(zhǔn)備了,真正跟上線上課堂。別人做到了,我卻沒有做到,說明我需要進(jìn)步學(xué)習(xí)空間還很大。
(二)知識(shí)點(diǎn)總結(jié)
1. 高性能爬蟲相關(guān)
1)http協(xié)議本質(zhì):
方案:
多進(jìn)程 > 多線程 > 單線程
本質(zhì):
sk = socket()
# 阻塞
sk.connect(('www.cnblogs.com',80))
sk.sendall(b"GET /wupeiqi http1.1\r\n.....\r\n\r\n")
sk.sendall(b"POST /wupeiqi http1.1\r\n.....\r\n\r\nuser=alex&pwd=123")
# 阻塞
data = sk.recv(8096)
sk.close()
IO多路復(fù)用:監(jiān)聽多個(gè)socket是否發(fā)生變化
問題:
- 非阻塞
- 監(jiān)聽socket變化
2)什么是異步非阻塞?
- 非阻塞
- 不等待(報(bào)錯(cuò),捕捉異常)
- 代碼:
sk = socket.socket()
sk.setblocking(False)
- 異步:
- 回調(diào),當(dāng)達(dá)到某個(gè)指定的狀態(tài)之后,自動(dòng)調(diào)用特定函數(shù)。
自定義異步非阻塞模塊
基于socket設(shè)置setblocking和IO多路復(fù)用來實(shí)現(xiàn)。
爬蟲發(fā)送Http請(qǐng)求本質(zhì)創(chuàng)建socket對(duì)象;
IO多路復(fù)用"循環(huán)"監(jiān)聽socket是否發(fā)生變化,一旦發(fā)生變化, 我們可以自定義操作(觸發(fā)某個(gè)函數(shù)的執(zhí)行)
- 基于事件循環(huán)
- 基于協(xié)程
本質(zhì):socket+IO多路復(fù)用
使用:
情況一:
import asyncio
import requests
@asyncio.coroutine
def fetch_async(func, *args):
loop = asyncio.get_event_loop()
future = loop.run_in_executor(None, func, *args)
response = yield from future
print(response.url, len(response.content))
tasks = [
fetch_async(requests.get, 'http://www.cnblogs.com/wupeiqi/'),
fetch_async(requests.get, 'http://dig.chouti.com/pic/show?nid=4073644713430508&lid=10273091')
]
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
情況二:
import gevent
from gevent import monkey
monkey.patch_all()
import requests
def fetch_async(method, url, req_kwargs):
print(method, url, req_kwargs)
response = requests.request(method=method, url=url, **req_kwargs)
print(response.url, len(response.content))
# ##### 發(fā)送請(qǐng)求 #####
gevent.joinall([
gevent.spawn(fetch_async, method='get', url='https://www.cnblogs.com/', req_kwargs={}),
gevent.spawn(fetch_async, method='get', url='https://www.baidu.com/', req_kwargs={}),
gevent.spawn(fetch_async, method='get', url='https://www.sogo.com/', req_kwargs={}),
])
# ##### 發(fā)送請(qǐng)求(協(xié)程池控制最大協(xié)程數(shù)量) #####
# from gevent.pool import Pool
# pool = Pool(None)
# gevent.joinall([
# pool.spawn(fetch_async, method='get', url='https://www.python.org/', req_kwargs={}),
# pool.spawn(fetch_async, method='get', url='https://www.yahoo.com/', req_kwargs={}),
# pool.spawn(fetch_async, method='get', url='https://www.github.com/', req_kwargs={}),
# ])
情況三:
from twisted.web.client import getPage, defer
from twisted.internet import reactor
def all_done(arg):
reactor.stop()
def callback(contents):
print(contents)
d_list = []
url_list = ['http://www.bing.com', 'http://www.baidu.com', ]
for url in url_list:
d = getPage(bytes(url, encoding='utf8'))
d.addCallback(callback)
d_list.append(d)
# 用于檢查是否頁面已經(jīng)全部下載完成,如果已下載完成那么,就停止循環(huán)。
dlist = defer.DeferredList(d_list)
dlist.addBoth(all_done) #
reactor.run()
3)什么是協(xié)程?
協(xié)程是 “微線程” ,讓一個(gè)線程 先執(zhí)行某幾行代碼 再調(diào)到某處 執(zhí)行某幾行代碼。
?是“微線程”,不存在;是由程序員人為創(chuàng)造出來并控制程序:先執(zhí)行某段代碼、再跳到某處執(zhí)行某段代碼。
- 如果遇到非IO請(qǐng)求來回切換:性能更低。
- 如果遇到IO(耗時(shí))請(qǐng)求來回切換:性能高、實(shí)現(xiàn)并發(fā)(本質(zhì)上利用IO等待的過程,再去干一些其他的事)
如果 協(xié)程+遇到IO就切換 => 可以實(shí)現(xiàn)并發(fā)
通過yield實(shí)現(xiàn)一個(gè)協(xié)程:
def func1():
print('adsfasdf')
print('adsfasdf')
print('adsfasdf')
yield 1
print('adsfasdf')
print('adsfasdf')
print('adsfasdf')
yield 2
yield 3
yield 4
def func2():
print('adsfasdf')
print('adsfasdf')
print('adsfasdf')
yield 11
yield 12
yield 19
g1=func1()
g2=func2()
g1.send(None)
g1.send(None)
g2.send(None)
通過greenlet模塊:
from greenlet import greenlet
def test1():
print 12
gr2.switch()
print 34
gr2.switch()
def test2():
print 56
gr1.switch()
print 78
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
2.Scrapy模塊
1)安裝scrapy
scrapy是個(gè)什么鬼?
- 幫我們提供一個(gè)可擴(kuò)展功能齊全的爬蟲框架。
安裝:
Linux/mac
- pip3 install scrapy
Windows:
- 安裝twsited
a. pip3 install wheel
b. 下載twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
c. 進(jìn)入下載目錄,執(zhí)行 pip3 install Twisted-xxxxx.whl
- 安裝scrapy
d. pip3 install scrapy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
- 安裝pywin32
e. pip3 install pywin32 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
2)快速使用:
Django:
django-admin startproject mysite
cd mysite
python manage.py startapp app01
# 寫代碼
python manage.py runserver
Scrapy:
創(chuàng)建project:
scrapy startproject xianglong
cd xianglong
scrapy genspider chouti chouti.com
#寫代碼
scrapy crawl chouti --nolog
3)scrapy相關(guān):
?spider,編寫爬蟲程序,去解析并處理請(qǐng)求。
def parse():
- HtmlXPathSelector
- yield item
- yield request
4)item/pipelines
配置:
ITEM_PIPELINES = {
'xianglong.pipelines.XianglongPipeline': 300,
}
使用:
class XianglongPipeline(object):
def process_item(self, item, spider):
self.f.write(item['href']+'\n')
self.f.flush()
return item
def open_spider(self, spider):
"""
爬蟲開始執(zhí)行時(shí),調(diào)用
:param spider:
:return:
"""
self.f = open('url.log','w')
def close_spider(self, spider):
"""
爬蟲關(guān)閉時(shí),被調(diào)用
:param spider:
:return:
"""
self.f.close()
5)去重
配置
DUPEFILTER_CLASS=" xianglong.dupe.MyDupe.MyDupeFilter"
-寫類
class ?MyDupeFilter(BaseDupeFilter):
def_init_(self):
pass
@classmethod
def from_settings(cls,settings):
pass
def request_seen(self,request):
pass
def open(self):#c&n return deferred
pass
def close(self,reason):#c&n??return ?& deferred
pass
6)下載中間件
配置
DOWNLOADER_MIDDLEWARES={" xianglong.middlawaras.UserAgentDownloaderMiddlaware":543}
類
class UserAgentDownloaderMiddlaware(object):
@classmethod
def from_crawler(cls,crawler):
pass
def process_request(self,request,spider):
pass
def process_response(self,request,response,spider):
pass
def process_exception(sef,request,exception,spider):
pass
轉(zhuǎn)載于:https://www.cnblogs.com/christyyao/p/9285995.html
總結(jié)
以上是生活随笔為你收集整理的路飞学城-python爬虫密训-第三章的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DOM 操作
- 下一篇: 【在线报表设计】提升报表外观的15个技巧