方法/步驟
創(chuàng)新互聯(lián)建站,專注為中小企業(yè)提供官網(wǎng)建設(shè)、營銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站設(shè)計、展示型網(wǎng)站建設(shè)、網(wǎng)站制作等服務(wù),幫助中小企業(yè)通過網(wǎng)站體現(xiàn)價值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營銷推廣問題。
在做爬取數(shù)據(jù)之前,你需要下載安裝兩個東西,一個是urllib,另外一個是python-docx。
請點擊輸入圖片描述
然后在python的編輯器中輸入import選項,提供這兩個庫的服務(wù)
請點擊輸入圖片描述
urllib主要負責抓取網(wǎng)頁的數(shù)據(jù),單純的抓取網(wǎng)頁數(shù)據(jù)其實很簡單,輸入如圖所示的命令,后面帶鏈接即可。
請點擊輸入圖片描述
抓取下來了,還不算,必須要進行讀取,否則無效。
請點擊輸入圖片描述
5
接下來就是抓碼了,不轉(zhuǎn)碼是完成不了保存的,將讀取的函數(shù)read轉(zhuǎn)碼。再隨便標記一個比如XA。
請點擊輸入圖片描述
6
最后再輸入三句,第一句的意思是新建一個空白的word文檔。
第二句的意思是在文檔中添加正文段落,將變量XA抓取下來的東西導進去。
第三句的意思是保存文檔docx,名字在括號里面。
請點擊輸入圖片描述
7
這個爬下來的是源代碼,如果還需要篩選的話需要自己去添加各種正則表達式。
關(guān)于知乎驗證碼登陸的問題,用到了Python上一個重要的圖片處理庫PIL,如果不行,就把圖片存到本地,手動輸入。
通過對知乎登陸是的抓包,可以發(fā)現(xiàn)登陸知乎,需要post三個參數(shù),一個是賬號,一個是密碼,一個是xrsf。
這個xrsf隱藏在表單里面,每次登陸的時候,應(yīng)該是服務(wù)器隨機產(chǎn)生一個字符串。所有,要模擬登陸的時候,必須要拿到xrsf。
用chrome (或者火狐 httpfox 抓包分析)的結(jié)果:
所以,必須要拿到xsrf的數(shù)值,注意這是一個動態(tài)變化的參數(shù),每次都不一樣。
拿到xsrf,下面就可以模擬登陸了。
使用requests庫的session對象,建立一個會話的好處是,可以把同一個用戶的不同請求聯(lián)系起來,直到會話結(jié)束都會自動處理cookies。
注意:cookies 是當前目錄的一個文件,這個文件保存了知乎的cookie,如果是第一個登陸,那么當然是沒有這個文件的,不能通過cookie文件來登陸。必須要輸入密碼。
這是登陸的函數(shù),通過login函數(shù)來登陸,post 自己的賬號,密碼和xrsf 到知乎登陸認證的頁面上去,然后得到cookie,將cookie保存到當前目錄下的文件里面。下次登陸的時候,直接讀取這個cookie文件。
這是cookie文件的內(nèi)容
以下是源碼:
運行結(jié)果:
反爬蟲最基本的策略:
爬蟲策略:
這兩個都是在http協(xié)議的報文段的檢查,同樣爬蟲端可以很方便的設(shè)置這些字段的值,來欺騙服務(wù)器。
反爬蟲進階策略:
1.像知乎一樣,在登錄的表單里面放入一個隱藏字段,里面會有一個隨機數(shù),每次都不一樣,這樣除非你的爬蟲腳本能夠解析這個隨機數(shù),否則下次爬的時候就不行了。
2.記錄訪問的ip,統(tǒng)計訪問次數(shù),如果次數(shù)太高,可以認為這個ip有問題。
爬蟲進階策略:
1.像這篇文章提到的,爬蟲也可以先解析一下隱藏字段的值,然后再進行模擬登錄。
2.爬蟲可以使用ip代理池的方式,來避免被發(fā)現(xiàn)。同時,也可以爬一會休息一會的方式來降低頻率。另外,服務(wù)器根據(jù)ip訪問次數(shù)來進行反爬,再ipv6沒有全面普及的時代,這個策略會很容易造成誤傷。(這個是我個人的理解)。
通過Cookie限制進行反爬蟲:
和Headers校驗的反爬蟲機制類似,當用戶向目標網(wǎng)站發(fā)送請求時,會再請求數(shù)據(jù)中攜帶Cookie,網(wǎng)站通過校驗請求信息是否存在Cookie,以及校驗Cookie的值來判定發(fā)起訪問請求的到底是真實的用戶還是爬蟲,第一次打開網(wǎng)頁會生成一個隨機cookie,如果再次打開網(wǎng)頁這個Cookie不存在,那么再次設(shè)置,第三次打開仍然不存在,這就非常有可能是爬蟲在工作了。
反爬蟲進進階策略:
1.數(shù)據(jù)投毒,服務(wù)器在自己的頁面上放置很多隱藏的url,這些url存在于html文件文件里面,但是通過css或者js使他們不會被顯示在用戶看到的頁面上面。(確保用戶點擊不到)。那么,爬蟲在爬取網(wǎng)頁的時候,很用可能取訪問這個url,服務(wù)器可以100%的認為這是爬蟲干的,然后可以返回給他一些錯誤的數(shù)據(jù),或者是拒絕響應(yīng)。
爬蟲進進階策略:
1.各個網(wǎng)站雖然需要反爬蟲,但是不能夠把百度,谷歌這樣的搜索引擎的爬蟲給干了(干了的話,你的網(wǎng)站在百度都說搜不到!)。這樣爬蟲應(yīng)該就可以冒充是百度的爬蟲去爬。(但是ip也許可能被識破,因為你的ip并不是百度的ip)
反爬蟲進進進階策略:
給個驗證碼,讓你輸入以后才能登錄,登錄之后,才能訪問。
爬蟲進進進階策略:
圖像識別,機器學習,識別驗證碼。不過這個應(yīng)該比較難,或者說成本比較高。
參考資料:
廖雪峰的python教程
靜覓的python教程
requests庫官方文檔
segmentfault上面有一個人的關(guān)于知乎爬蟲的博客,找不到鏈接了
本來是想爬取之后作最佳羈絆組合推算,但是遇到知識點無法消化(知識圖譜),所以暫時先不組合了,實力有限
庫的安裝
1.requests? #爬取棋子數(shù)據(jù)
2.json? #棋子數(shù)據(jù)為js動態(tài),需使用json解析
3.BeautifulSoup
實戰(zhàn)前先新建個lol文件夾作為工作目錄,并創(chuàng)建子目錄data,用于存放數(shù)據(jù)。
1.爬取數(shù)據(jù),新建個py文件,用于爬取云頂數(shù)據(jù),命名為data.py
1.1定義個req函數(shù),方便讀取。//需設(shè)定編碼格式,否則會出現(xiàn)亂碼
def Re_data(url):
re = requests.get(url)
re.encoding = 'gbk'
data = json.loads(re.text)
return data['data']
1.2定義個Get函數(shù),用于讀取數(shù)據(jù)并使用保存函數(shù)進行保存數(shù)據(jù),保存格式為json。
def Get_data():
# 獲取數(shù)據(jù)并保存至data目錄
base_url = ''
chess = Re_data(base_url + 'chess.js')
race = Re_data(base_url + 'race.js')
job = Re_data(base_url + 'job.js')
equip = Re_data(base_url + 'equip.js')
Save_data(chess,race,job,equip)
1.3定義save函數(shù)實現(xiàn)讀取的數(shù)據(jù)進行文件保存,保存目錄為工作目錄下的data文件夾。
def Save_data(t_chess,t_race,t_job,t_equip):
with open('./data/chess.json','w') as f:
json.dump(t_chess,f,indent='\t')
with open('./data/race.json','w') as f:
json.dump(t_race,f,indent='\t')
with open('./data/job.json','w') as f:
json.dump(t_job,f,indent='\t')
with open('./data/equip.json','w') as f:
json.dump(t_equip,f,indent='\t')
1.4定義主函數(shù)main跑起來
if __name__ == '__main__':
start = time.time()
Get_data()
print('運行時間:' + str(time.time() - start) + '秒')
至此,數(shù)據(jù)爬取完成。
2.種族和職業(yè)進行組合。
2.1未完成 //未完成,使用窮舉方法進行組合會出現(xiàn)內(nèi)存不夠?qū)е陆M合失敗(for循環(huán)嵌套導致數(shù)組內(nèi)存超限)
//待學習,使用知識圖譜建立組合優(yōu)選,可參考:
期間遇到的問題:
1.爬取棋子數(shù)據(jù)時為動態(tài)js加載,需通過json模塊的loads方法獲取
2.3層for循環(huán)嵌套數(shù)據(jù)量大,導致計算失敗,需優(yōu)化計算方法。
一、爬取我們所需要的一線鏈接
channel_extract.py
這里的一線鏈接也就是我們所說的大類鏈接:
from bs4 import BeautifulSoupimport requests
start_url = ''host_url = ''def get_channel_urls(url):
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.text, 'lxml')
links = soup.select('.fenlei dt a') #print(links)
for link in links:
page_url = host_url + link.get('href')
print(page_url)#get_channel_urls(start_url)channel_urls = '''
'''123456789101112131415161718192021222324252627282930313233343536
那么拿我爬取的58同城為例就是爬取了二手市場所有品類的鏈接,也就是我說的大類鏈接;
找到這些鏈接的共同特征,用函數(shù)將其輸出,并作為多行文本儲存起來。
二、獲取我們所需要的詳情頁面的鏈接和詳情信息
page_parsing.py
1、說說我們的數(shù)據(jù)庫:
先看代碼:
#引入庫文件from bs4 import BeautifulSoupimport requestsimport pymongo #python操作MongoDB的庫import reimport time#鏈接和建立數(shù)據(jù)庫client = pymongo.MongoClient('localhost', 27017)
ceshi = client['ceshi'] #建ceshi數(shù)據(jù)庫ganji_url_list = ceshi['ganji_url_list'] #建立表文件ganji_url_info = ceshi['ganji_url_info']123456789101112
2、判斷頁面結(jié)構(gòu)是否和我們想要的頁面結(jié)構(gòu)相匹配,比如有時候會有404頁面;
3、從頁面中提取我們想要的鏈接,也就是每個詳情頁面的鏈接;
這里我們要說的是一個方法就是:
item_link = link.get('href').split('?')[0]12
這里的這個link什么類型的,這個get方法又是什么鬼?
后來我發(fā)現(xiàn)了這個類型是
class 'bs4.element.Tab1
如果我們想要單獨獲取某個屬性,可以這樣,例如我們獲取它的 class 叫什么
print soup.p['class']
#['title']12
還可以這樣,利用get方法,傳入屬性的名稱,二者是等價的
print soup.p.get('class')#['title']12
下面我來貼上代碼:
#爬取所有商品的詳情頁面鏈接:def get_type_links(channel, num):
list_view = '{0}o{1}/'.format(channel, str(num)) #print(list_view)
wb_data = requests.get(list_view)
soup = BeautifulSoup(wb_data.text, 'lxml')
linkOn = soup.select('.pageBox') #判斷是否為我們所需頁面的標志;
#如果爬下來的select鏈接為這樣:div.pageBox ul li:nth-child(1) a span 這里的:nth-child(1)要刪掉
#print(linkOn)
if linkOn:
link = soup.select('.zz .zz-til a')
link_2 = soup.select('.js-item a')
link = link + link_2 #print(len(link))
for linkc in link:
linkc = linkc.get('href')
ganji_url_list.insert_one({'url': linkc})
print(linkc) else: pass1234567891011121314151617181920
4、爬取詳情頁中我們所需要的信息
我來貼一段代碼:
#爬取趕集網(wǎng)詳情頁鏈接:def get_url_info_ganji(url):
time.sleep(1)
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.text, 'lxml') try:
title = soup.select('head title')[0].text
timec = soup.select('.pr-5')[0].text.strip()
type = soup.select('.det-infor li span a')[0].text
price = soup.select('.det-infor li i')[0].text
place = soup.select('.det-infor li a')[1:]
placeb = [] for placec in place:
placeb.append(placec.text)
tag = soup.select('.second-dt-bewrite ul li')[0].text
tag = ''.join(tag.split()) #print(time.split())
data = { 'url' : url, 'title' : title, 'time' : timec.split(), 'type' : type, 'price' : price, 'place' : placeb, 'new' : tag
}
ganji_url_info.insert_one(data) #向數(shù)據(jù)庫中插入一條數(shù)據(jù);
print(data) except IndexError: pass123456789101112131415161718192021222324252627282930
四、我們的主函數(shù)怎么寫?
main.py
看代碼:
#先從別的文件中引入函數(shù)和數(shù)據(jù):from multiprocessing import Poolfrom page_parsing import get_type_links,get_url_info_ganji,ganji_url_listfrom channel_extract import channel_urls#爬取所有鏈接的函數(shù):def get_all_links_from(channel):
for i in range(1,100):
get_type_links(channel,i)#后執(zhí)行這個函數(shù)用來爬取所有詳情頁的文件:if __name__ == '__main__':# pool = Pool()# # pool = Pool()# pool.map(get_url_info_ganji, [url['url'] for url in ganji_url_list.find()])# pool.close()# pool.join()#先執(zhí)行下面的這個函數(shù),用來爬取所有的鏈接:if __name__ == '__main__':
pool = Pool()
pool = Pool()
pool.map(get_all_links_from,channel_urls.split())
pool.close()
pool.join()1234567891011121314151617181920212223242526
五、計數(shù)程序
count.py
用來顯示爬取數(shù)據(jù)的數(shù)目;
import timefrom page_parsing import ganji_url_list,ganji_url_infowhile True: # print(ganji_url_list.find().count())
# time.sleep(5)
print(ganji_url_info.find().count())
time.sleep(5)
我們在一些沒有反爬蟲機制的生物網(wǎng)站上,可以利用Python做一些“省力”的事情,比方說ID的轉(zhuǎn)換
我們以uniprot為例,進入它的轉(zhuǎn)換頁面 傳送門 ,頁面:
這里介紹下 urllib 這個Python庫,該庫功能非常強大,可以爬取動態(tài)網(wǎng)頁
根據(jù)這個思路,我們看看該網(wǎng)站的網(wǎng)頁結(jié)構(gòu):
url 為ID轉(zhuǎn)換的網(wǎng)址,params是你要爬取的內(nèi)容,存儲為字典形式,那么字典的鍵值代表HTML表單(form)里面 name 的內(nèi)容:
比方說 from:
字典的鍵值與form的name標簽的內(nèi)容對應(yīng)
to也是一樣的:
至于 "format": "tab" 是指我們把爬下來的網(wǎng)頁轉(zhuǎn)換為 tab 格式
當然,這招適用于表單提交的爬蟲,如果爬取的內(nèi)容過多,不妨寫個函數(shù):
參考: 傳送門
在if 里只需要yield "" + item_url.attrs['href']
然后Lsit(最好改可名,在python規(guī)范里,函數(shù)命名是全小寫,而list又是保留字,比如改為display_hrefs)只需要循環(huán)輸出getUrl的結(jié)果就好:
def getUrl(url: str):
....html = urlopen(url)
....for item_url in BeautifulSoup((html.read()).find ('div' , class_='AAA').findAll ("a"):
........if 'href' in item_url.attrs:
............yield "" + item_url.attrs['href']
def display_hrefs(url: str):
....for href in getUrl(url):
........print(href)
if __name__ == '__main__':
....display_hrefs("")
標題名稱:python爬取函數(shù) Python爬取
網(wǎng)頁網(wǎng)址:http://chinadenli.net/article0/hgdoio.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、定制網(wǎng)站、App設(shè)計、用戶體驗、企業(yè)網(wǎng)站制作、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)