知識小結(jié)

requests

  • requests模塊:是對urllib的封裝,可以實現(xiàn)urllib的所有功能
  • 并且api調(diào)用更加簡單方便

url, :要請求的目標(biāo)url
params:get請求后面要拼接的參數(shù)

:param method: 要發(fā)起的是什么類型的請求.
:param url: 要請求的目標(biāo)url
:param params: get請求后面要拼接的參數(shù)
:param data: Dictionary, post請求的表單數(shù)據(jù)
:param json: 傳遞json數(shù)據(jù)跟上面的data效果類似
:param headers: (optional) Dictionary 請求頭
:param cookies: (optional) Dict or CookieJar object (設(shè)置cookies信息模擬用戶請求)
:param files: 上傳文件
:param auth: 網(wǎng)站需要驗證的信息(賬號和密碼)
:param timeout: 設(shè)置請求的超時時間
:param allow_redirects: bool,是否允許重定向
:param proxies: (optional) Dictionary (設(shè)置代理)
:param verify: Defaults to True.(忽略證書認(rèn)證,默認(rèn)為True表示不忽略)

  • requests.session():維持會話,可以讓我們在跨請求時保存某些參數(shù)

xpath

xpath:可以在xml中查找信息,對xml文檔中元素進行遍歷和屬性的提取

xml:被設(shè)計的目的是為了傳輸數(shù)據(jù),結(jié)構(gòu)和html非常相識,是一種標(biāo)記語言

xpath常見的語法:

nodename 選取此節(jié)點的所有子節(jié)點
/ 從根節(jié)點開始查找
// 匹配節(jié)點,不考慮節(jié)點的位置
. 選取當(dāng)前節(jié)點
.. 選取當(dāng)前節(jié)點的父節(jié)點
a/@href 取標(biāo)簽的數(shù)據(jù)
a/text() 取標(biāo)簽的文本
a[@class="123"] 根據(jù)class屬性尋找標(biāo)簽
a[@id="123"] 根據(jù)id屬性尋找標(biāo)簽
a[@id="123"][last()] 取最后一個id為123的a標(biāo)簽
a[@id="123"][postion() < 2] 取id為123的前兩個a標(biāo)簽

pyquery

語法規(guī)則類似于Jquery,可以對html文本進行解析

q = PyQuery(html文檔)
pq('css選擇器')
items():獲取到多個標(biāo)簽時,使用items()將PyQuery轉(zhuǎn)換為一個生成器
然后在使用for in 循環(huán)
filter('css選擇器'):過濾
text():獲取標(biāo)簽的文本
attr('屬性名')獲取屬性值

beautifulsoup

作用是從html/xml中提取數(shù)據(jù),會載入整個HTML DOM,比lxml解析器效率要低

re

. :表示匹配除了換行符之外的任意字符
\ :轉(zhuǎn)義字符
[a-z] : 匹配a-z里面的任意一個字符

\d: 匹配數(shù)字 -> [0-9]
\D: 匹配非數(shù)字 [^\d]
\s: 匹配空白字符(空格,\n,\t...)
\S: 匹配非空白字符 
\w: 匹配單詞字符 [A-Za-z0-9_]
\W: 匹配非單子字符

^:匹配以...開頭
$:匹配以....結(jié)尾

():分組
|:或

  • 多字符匹配

*:匹配*前面的字符任意次數(shù)
+: 匹配+號前面的字符至少1次
?: 匹配?前面的字符0次或1次
{m}:匹配{m}前面的字符m次
{m,n}:匹配{m,n}前面的字符m~n次

  • 非貪婪匹配

*?
+?
??
{m,n}?

match 方法:從起始位置開始查找,一次匹配
search 方法:從任何位置開始查找,一次匹配
findall 方法:全部匹配,返回列表
finditer 方法:全部匹配,返回迭代器
split 方法:分割字符串,返回列表
sub 方法:替換

多線程

  • threading.Thread參數(shù)介紹

target:線程執(zhí)行的函數(shù)
name:線程名稱
args:執(zhí)行函數(shù)中需要傳遞的參數(shù),元組類型 另外:注意daemon參數(shù)
如果某個子線程的daemon屬性為False,主線程結(jié)束時會檢測該子線程是否結(jié)束,如果該子線程還在運行,則主線程會等待它完成后再退出;
如果某個子線程的daemon屬性為True,主線程運行結(jié)束時不對這個子線程進行檢查而直接退出,同時所有daemon值為True的子線程將隨主線程一起結(jié)束,而不論是否運行完成。
屬性daemon的值默認(rèn)為False,如果需要修改,必須在調(diào)用start()方法啟動線程之前進行設(shè)置

互斥鎖

當(dāng)多個線程幾乎同時修改某一個共享數(shù)據(jù)的時候,需要進行同步控制

線程同步能夠保證多個線程安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。

互斥鎖為資源引入一個狀態(tài):鎖定/非鎖定

某個線程要更改共享數(shù)據(jù)時,先將其鎖定,此時資源的狀態(tài)為“鎖定”,其他線程不能更改;直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源。互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。

threading模塊中定義了Lock類,可以方便的處理鎖定:

創(chuàng)建鎖

mutex = threading.Lock()

鎖定

mutex.acquire()

釋放

mutex.release()

鎖的好處:

確保了某段關(guān)鍵代碼只能由一個線程從頭到尾完整地執(zhí)行

鎖的壞處:

阻止了多線程并發(fā)執(zhí)行,包含鎖的某段代碼實際上只能以單線程模式執(zhí)行,效率就大大地下降了
由于可以存在多個鎖,不同的線程持有不同的鎖,并試圖獲取對方持有的鎖時,可能會造成死鎖

死鎖問題
在線程間共享多個資源的時候,如果兩個線程分別占有一部分資源并且同時等待對方的資源,就會造成死鎖。

盡管死鎖很少發(fā)生,但一旦發(fā)生就會造成應(yīng)用的停止響應(yīng)

多進程

進程:一個程序運行起來后,代碼+用到的資源 稱之為進程,它是操作系統(tǒng)分配資源的基本單元。

不僅可以通過線程完成多任務(wù),進程也是可以的

multiprocessing模塊就是跨平臺版本的多進程模塊,提供了一個Process類來代表一個進程對象,這個對象可以理解為是一個獨立的進程,可以執(zhí)行另外的事情

Queue的使用

Queue本身是一個消息列隊程序

Queue.qsize():返回當(dāng)前隊列包含的消息數(shù)量;

Queue.empty():如果隊列為空,返回True,反之False ;

Queue.full():如果隊列滿了,返回True,反之False;

Queue.get(block, timeout):獲取隊列中的一條消息,然后將其從列隊中移除,block默認(rèn)值為True;

1)如果block使用默認(rèn)值,且沒有設(shè)置timeout(單位秒),消息列隊如果為空,此時程序?qū)⒈蛔枞ㄍT谧x取狀態(tài)),直到從消息列隊讀到消息為止,如果設(shè)置了timeout,則會等待timeout秒,若還沒讀取到任何消息,則拋出"Queue.Empty"異常;

2)如果block值為False,消息列隊如果為空,則會立刻拋出"Queue.Empty"異常;

Queue.get_nowait():相當(dāng)Queue.get(False);

Queue.put(item,block,timeout):將item消息寫入隊列,block默認(rèn)值為True;

1)如果block使用默認(rèn)值,且沒有設(shè)置timeout(單位秒),消息列隊如果已經(jīng)沒有空間可寫入,此時程序?qū)⒈蛔枞ㄍT趯懭霠顟B(tài)),直到從消息列隊騰出空間為止,如果設(shè)置了timeout,則會等待timeout秒,若還沒空間,則拋出"Queue.Full"異常;

2)如果block值為False,消息列隊如果沒有空間可寫入,則會立刻拋出"Queue.Full"異常;

Queue.put_nowait(item):相當(dāng)Queue.put(item, False);

  1. Queue實例以及在多進程間的使用

multiprocessing.Pool常用函數(shù)解析:

apply_async(func[, args[, kwds]]) :使用非阻塞方式調(diào)用func(并行執(zhí)行,堵塞方式必須等待上一個進程退出才能執(zhí)行下一個進程),args為傳遞給func的參數(shù)列表,kwds為傳遞給func的關(guān)鍵字參數(shù)列表;

close():關(guān)閉Pool,使其不再接受新的任務(wù);

terminate():不管任務(wù)是否完成,立即終止;

join():主進程阻塞,等待子進程的退出, 必須在close或terminate之后使用;

進程與線程的對比

進程、線程對比 功能

進程,能夠完成多任務(wù),比如 在一臺電腦上能夠同時運行多個QQ
線程,能夠完成多任務(wù),比如 一個QQ中的多個聊天窗口

定義的不同

進程是系統(tǒng)進行資源分配基本單位.

線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.

線程自己基本上不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享所在進程所擁有的全部資源

區(qū)別

一個程序至少有一個進程,一個進程至少有一個線程.
線程的劃分尺度小于進程(資源比進程少),使得多線程程序的并發(fā)性高。
進程在執(zhí)行過程中擁有獨立的內(nèi)存單元,而多個線程共享內(nèi)存,從而極大地提高了程序的運行效率
線線程不能夠獨立執(zhí)行,必須依存在進程中

優(yōu)缺點

線程和進程在使用上各有優(yōu)缺點:線程執(zhí)行開銷小,但不利于資源的管理和保護;而進程正相反。

使用場景:

多進程常用來處理計算密集型任務(wù): 計算密集型任務(wù)的特點:是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視頻進行高清解碼等等,全靠CPU的運算能力。計算密集型任務(wù)可以用多任務(wù)完成,但是任務(wù)越多,花在任務(wù)切換的時間就越多,CPU執(zhí)行任務(wù)的效率就越低,所以,要最高效地利用CPU,計算密集型任務(wù)同時進行的數(shù)量應(yīng)當(dāng)?shù)扔贑PU的核心數(shù)。

多線程常用來處理IO密集型任務(wù): IO密集型:涉及到網(wǎng)絡(luò)、磁盤IO的任務(wù)都是IO密集型任務(wù),特點是CPU消耗很少,任務(wù)的大部分時間都在等待IO操作完成(因為IO的速度遠遠低于CPU和內(nèi)存的速度)。但是也要切記,在執(zhí)行多任務(wù)時,并不是越多線程越好。

SELENIUM

Selenium是一個Web的自動化測試工具,最初是為網(wǎng)站自動化測試而開發(fā)的,類型像我們玩游戲用的按鍵精靈,可以按指定的命令自動操作,不同是Selenium 可以直接運行在瀏覽器上,它支持所有主流的瀏覽器(包括PhantomJS這些無界面的瀏覽器)。 Selenium 可以根據(jù)我們的指令,讓瀏覽器自動加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏,或者判斷網(wǎng)站上某些動作是否發(fā)生。

Selenium 自己不帶瀏覽器,不支持瀏覽器的功能,它需要與第三方瀏覽器結(jié)合在一起才能使用。但是我們有時候需要讓它內(nèi)嵌在代碼中運行,所以我們可以用一個叫 PhantomJS 的工具代替真實的瀏覽器。
主要使用的方法和代碼如下

from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException,TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# 要想調(diào)用鍵盤按鍵操作需要引入keys包
from selenium.webdriver.common.keys import Keys

# 加載網(wǎng)頁(使用火狐瀏覽器加載)
# driver = webdriver.Firefox(executable_path='/home/ljh/桌面/driver/geckodriver')
# driver.get('https://www.baidu.com/')

# 加載網(wǎng)頁(使用無頭瀏覽器加載)
# driver = webdriver.PhantomJS(executable_path='/home/ljh/桌面/driver/phantomjs')
# driver.get('https://www.baidu.com/')

# 加載網(wǎng)頁(使用谷歌瀏覽器加載)
# 創(chuàng)建chrome參數(shù)對象
# opt = webdriver.ChromeOptions()
# 把chrome設(shè)置成為無界面模式
# opt.set_headless()
# driver = webdriver.Chrome(
    options=opt, executable_path='/Users/ljh/Desktop/chromedriver'
)
driver = webdriver.Chrome(executable_path='/home/ljh/桌面/driver/chromedriver')
#設(shè)置頁面的加載超時時間
driver.set_page_load_timeout(0.1)

#處理異常
try:
    driver.get('https://www.baidu.com/')
    driver.save_screenshot('prcture.png')
except TimeoutException as err:
    print(err)

#定位和操作
# driver.find_element_by_xpath():根據(jù)xpath定位節(jié)點
# driver.find_element_by_class_name():根據(jù)類名定位節(jié)點
# driver.find_element_by_partial_link_text():根據(jù)部分文本內(nèi)容定位節(jié)點
# driver.find_element_by_css_selector():根據(jù)css選擇器定位節(jié)點
# driver.find_element_by_link_text():根據(jù)完整文本定位節(jié)點

driver.find_element_by_id('kw').send_keys('隔壁老趙')
driver.find_element_by_id('su').click()

#獲取信息
print(len(driver.page_source))
print(driver.get_cookies())
print(driver.current_url)
print(driver.name)

#清空輸入框內(nèi)容
driver.find_element_by_id('kw').clear()
#輸入框重新輸入內(nèi)容
driver.find_element_by_id('kw').send_keys('風(fēng)景')
#模擬回車鍵
driver.find_element_by_id('su').send_keys(Keys.RETURN)
#獲取當(dāng)前的url

#截取網(wǎng)頁頁面(生成當(dāng)前的頁面快照并保存)
driver.save_screenshot('baidu.png')

#前進和后退
time.sleep(2)
driver.back() #后退
time.sleep(2)
driver.forward() #前進

#獲取屬性和獲取文本
time.sleep(2)
href = driver.find_element_by_xpath('//h3[@class="t"]/a').get_attribute('href')
title = driver.find_element_by_xpath('//h3[@class="t"]/a').text
print(href)
print(title)

#關(guān)于cookie相關(guān)操作
cookies_dict = {cookie['name']:cookie['value'] for cookie in driver.get_cookies()}
print(cookies_dict)
print(driver.get_cookie('BIDUPSID'))
# driver.delete_all_cookies()
# driver.delete_cookie()
# driver.add_cookie()


###頁面等待
# 因為selenium加載的頁面和瀏覽器一樣會渲染頁面,并且有些網(wǎng)頁加載需要消耗時間
# 這時在頁面加載出來之前去尋找節(jié)點的話,會報異常,所有我們需要添加等待,有時甚至
# 需要前置等待

# 強制等待
# time.sleep(5)

# 隱士等待(設(shè)置等待時間)
# driver.implicitly_wait(10)

# 是指顯示等待:設(shè)置最大的等待時間
# 直到某一條件成立然后繼續(xù)執(zhí)行
# WebDriverWait(driver,10).until(EC.presence_of_element_located(By.ID,''))

#退出
driver.close() #退出當(dāng)前頁面
driver.quit() #退出瀏覽器

頁面的相關(guān)操作

Selenium 的 WebDriver提供了各種方法來尋找元素,假設(shè)下面有一個表單輸入框如

element = driver.find_element_by_id("passwd-id")
獲取name標(biāo)簽值
element = driver.find_element_by_name("user-name")
獲取標(biāo)簽名值
element = driver.find_elements_by_tag_name("input")
也可以通過XPath來匹配
element = driver.find_element_by_xpath("http://input[@id='passwd-id']")

頁面前進和后退

driver.forward() #前進
driver.back() # 后退

Cookies操作

cookies = driver.get_cookies()

cookie_dict = {i['name']:i['value'] for i in cookies}

Selenium 提供了兩種等待方式,一種是隱式等待,一種是顯式等待。
隱式等待是等待特定的時間,如果節(jié)點沒有立即出現(xiàn),隱士等待將一段時間再進行查找 顯式等待是指定一個最長的等待時間,直到條件成立時繼續(xù)執(zhí)行。如果在設(shè)定時間內(nèi)沒加載出來節(jié)點,則返回異常信息,如果加載出來了則返回節(jié)點

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

顯式等待指定某個條件,然后設(shè)置最長等待時間。如果在這個時間還沒有找到元素,那么便會拋出異常了。

from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 庫,負責(zé)循環(huán)等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 類,負責(zé)條件出發(fā)
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
    ##### 會在這里等待,如果10秒內(nèi) id="myDynamicElement"的標(biāo)簽出現(xiàn)
    則返回,如果不出現(xiàn)則報異常
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(
            (By.ID, "myDynamicElement")
            )
    )
finally:
    driver.quit()

異常處理

  • 請求超時異常處理
from selenium.common.exceptions import TimeoutException

try:
    brower.get(url)
except TimeoutException:
    print('Time out')
  • 找不到標(biāo)簽的異常處理
from selenium.common.exceptions import NoSuchElementException

try:
    brower.find_element_by_id('').click()
    print('有標(biāo)簽')
except NoSuchElementException:
    print('沒有這個標(biāo)簽')  
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時,會觸發(fā)此異常。 O...
    我想起個好名字閱讀 5,385評論 0 9
  • Java繼承關(guān)系初始化順序 父類的靜態(tài)變量-->父類的靜態(tài)代碼塊-->子類的靜態(tài)變量-->子類的靜態(tài)代碼快-->父...
    第六象限閱讀 2,169評論 0 9
  • 一、基本語法 1.1 關(guān)鍵字 1.2 標(biāo)識符 1.3 變 量 1.3.1、變量的概念: 1.3.2、變量的分類 ...
    鴆羽千夜92閱讀 779評論 0 1
  • 在一個方法內(nèi)部定義的變量都存儲在棧中,當(dāng)這個函數(shù)運行結(jié)束后,其對應(yīng)的棧就會被回收,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,431評論 1 14
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口,提供良好的抽象接口。 管理調(diào)度進程,并將多個進程對硬件...
    drfung閱讀 3,560評論 0 5