日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

爬虫实战(自用)requests模块、聚焦爬虫(数据解析)、selenium模块

發(fā)布時間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 爬虫实战(自用)requests模块、聚焦爬虫(数据解析)、selenium模块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、requests模塊

一、爬取搜狗首頁的頁面數(shù)據(jù)

import requests # 指定url # 發(fā)起請求,get方法會返回一個響應對象 res=requests.get(r'https://www.sogou.com/') # 獲取響應數(shù)據(jù),text返回字符串類型的響應數(shù)據(jù) str=res.text print(str) # 持久化存儲 with open('./sogou.html','w',encoding='utf-8') as fp:fp.write(str) print('爬取結(jié)束')

結(jié)果:

二、爬取搜狗指定詞條對應的搜索結(jié)果頁面(簡易網(wǎng)頁采集器)


網(wǎng)址中有很多字母數(shù)字,我們只選擇出有用的部分:

這么處理以后,頁面還是一樣的!

粘貼到Pycharm中會自動編碼。(使用中文也沒問題)

UA檢測與UA偽裝

UA:User-Agent(請求載體的身份標識)
我們使用requess.get去請求網(wǎng)頁就不再是以瀏覽器的身份去訪問,而是以爬蟲程序去訪問,門戶網(wǎng)站的服務器會檢測對應請求的載體身份標識,如果檢測到為某一款瀏覽器,這個請求會被當作正常用戶請求。

但是,如果檢測到不是基于瀏覽器訪問,則被視為不正常請求!(爬蟲),則服務器很有可能拒絕該請求!

查詢User-Agent:

所以我們一定要進行UA偽裝!!! 偽裝成某一款瀏覽器。

import requests if __name__=='__main__':# UA偽裝:將user-agent封裝到字典中headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}url='https://www.sogou.com/web'# 處理url攜帶的參數(shù):封裝到字典中(因為要動態(tài)收集)kw=input('enter a word:')param={'query':kw}# 對指定的url發(fā)起的請求對應的url是攜帶參數(shù)的,并且請求過程中處理了參數(shù)# headers代表頭信息(用于UA偽裝)response=requests.get(url=url,params=param,headers=headers)page_text=response.textfileName=kw+'.html'with open(fileName,'w',encoding='utf-8') as fp:fp.write(page_text)print(fileName,'保存成功!!!')

三、破解百度翻譯

比較翻譯前后的url:

https://fanyi.baidu.com/?aldtype=16047#auto/zh/# 翻譯dog https://fanyi.baidu.com/?aldtype=16047#en/zh/dog# 翻譯狗 https://fanyi.baidu.com/?aldtype=16047#zh/en/%E7%8B%97(這里也可以寫成狗)

它實際上是在你輸入內(nèi)容后進行局部頁面刷新(不用你自己刷新)從而實現(xiàn)翻譯。

通過使用谷歌自帶抓包工具,進行抓包,沒輸入一個字符就觀察一次,因為它涉及到局部頁面刷新,屬于ajax請求,所以要在Network中選擇XHR進行查看。


最后發(fā)現(xiàn),是第三個sug中包含了我們輸入的參數(shù)dog,所以我們只需要這個內(nèi)容中的URL地址。

并且可以看到,返回的數(shù)據(jù)為json串。(就是我們想要的數(shù)據(jù))

從Content-Type可以看出響應數(shù)據(jù)的類型!

Post和Get的區(qū)別(使用不同函數(shù))



data和params一樣都用來處理參數(shù)。

上面的kw:dog就代表它的參數(shù)

實際上就是post是要攜帶用戶信息的請求方式,get則是根據(jù)URL直接獲取網(wǎng)頁信息(即某個網(wǎng)址所包含的信息)。

post要獲取的內(nèi)容只靠網(wǎng)址是不能獲取到的,需要提交一些額外的信息,這種信息在不同的網(wǎng)頁中發(fā)揮不同功能。 例如在查詢天氣的網(wǎng)頁,可能就是要輸入城市信息;在登錄某些網(wǎng)頁時,又是賬號和密碼的載體。從這些可以看出get方法獲取到的內(nèi)容是穩(wěn)定的(即每個人打開某個網(wǎng)頁獲得的信息相同),但是使用post需要輸入特定信息,那么得到的網(wǎng)頁內(nèi)容就會有特異性。

post每次獲取某個特定網(wǎng)頁都需要輸入額外信息,但get則直接輸入URL即可(),這樣也能看出post方法更加安全,因為額外信息不會直接暴露在網(wǎng)址上。

(百度翻譯是post,因為需要我們向它傳遞dog這個數(shù)據(jù),它才會返回值)

import requests import json if __name__=="__main__":# 1、指定urlpost_url='https://fanyi.baidu.com/sug'# 2、進行UA偽裝headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 3、post請求參數(shù)處理(同get請求一致)data={'kw':'dog'}# 4、請求發(fā)送response=requests.post(url=post_url,data=data,headers=headers)# 5、獲取響應數(shù)據(jù)(返回的是json)使用.json()返回的是對象# 如果確認服務器響應數(shù)據(jù)是json類型的,才可以使用.json()dic_obj=response.json()# print(dic_obj)# 6、持久化存儲fp=open('./dog.json','w',encoding='utf-8')# 使用json.dump存儲json文件,因為結(jié)果有中文,中文不支持ascii碼,所以要設(shè)置為Falsejson.dump(dic_obj,fp=fp,ensure_ascii=False)print('Over!!!')


使用[‘data’]即可獲取data部分的list,進而使用它的相關(guān)數(shù)據(jù)。

在翻譯dog的基礎(chǔ)上,我們同樣可以將dog設(shè)置成一個參數(shù),通過我們傳入的參數(shù)不同以達到獲取不同單詞的翻譯結(jié)果。

動態(tài)化獲取:

import requests import json if __name__=="__main__":# 1、指定urlpost_url='https://fanyi.baidu.com/sug'# 2、進行UA偽裝headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 3、post請求參數(shù)處理(同get請求一致)word=input('enter a word:')data={'kw':word}# 4、請求發(fā)送response=requests.post(url=post_url,data=data,headers=headers)# 5、獲取響應數(shù)據(jù)(返回的是json)使用.json()返回的是對象# 如果確認服務器響應數(shù)據(jù)是json類型的,才可以使用.json()dic_obj=response.json()# print(dic_obj)# 6、持久化存儲filename='./'+word+'.json'fp=open(filename,'w',encoding='utf-8')# 使用json.dump存儲json文件,因為結(jié)果有中文,中文不支持ascii碼,所以要設(shè)置為Falsejson.dump(dic_obj,fp=fp,ensure_ascii=False)print('Over!!!')

四、爬取豆瓣電影分類排行榜

進入這個網(wǎng)址:豆瓣

當滑動滾輪時,滑到底部的時候頁面會進行刷新使得右邊的滑塊又跑到了中央,所以我們可以利用這次刷新進行數(shù)據(jù)收集。

經(jīng)過驗證,確實是產(chǎn)生了ajax請求,和上面百度翻譯類似。


下面是攜帶的五個參數(shù)。

意思就是說:我們讓這個url發(fā)送get請求,并攜帶參數(shù),就可以獲取到響應的json文件,再進行持續(xù)化存儲。


從?后開始到最后就是傳遞的參數(shù),我們使用字典存儲,也方便之后動態(tài)化。

我們也可以通過下圖來獲取具體的參數(shù),直接復制到字典中存儲即可。


根據(jù)每次滑動的變化,我們可以對每個參數(shù)值的含義進行猜測:(見代碼)

import requests import json if __name__=="__main__":url='https://movie.douban.com/j/chart/top_list'param={'type':'24','interval_id':'100:90','action':'','start':'0', #從庫中第幾部電影去取'limit':'20', #一次請求取出的個數(shù)}headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 屬于get請求response=requests.get(url=url,params=param,headers=headers)list_data=response.json()fp=open('./douban.json','w',encoding='utf-8')json.dump(list_data,fp=fp,ensure_ascii=False)print('Over!!!')


第一部電影確實是憨豆先生,實現(xiàn)了爬取。

(之后就是進一步的數(shù)據(jù)處理)

五、爬取肯德基餐廳查詢

進入網(wǎng)址:http://www.kfc.com.cn/kfccda/storelist/index.aspx


發(fā)現(xiàn),這又是一個局部網(wǎng)頁刷新,所以和之前豆瓣一樣,通過比對輸入關(guān)鍵字前后抓包發(fā)生的變化,從而實現(xiàn)爬取。

import requests if __name__=="__main__":post_url='http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'data={'cname':'','pid':'','keyword': '四川','pageIndex': '1','pageSize': '10',}headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}response=requests.post(url=post_url,data=data,headers=headers)# 返回對象是text類型,編碼為utf-8fp=open('./KFC.txt','w',encoding='utf-8')fp.write(response.text)print('Over!!!')


六、爬取國家藥品監(jiān)督管理總局中基于中華人民共和國化妝品生產(chǎn)許可證相關(guān)數(shù)據(jù)(綜合實戰(zhàn))

動態(tài)加載

import requests if __name__=="__main__":url='http://scxk.nmpa.gov.cn:81/xk/'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}response=requests.get(url=url,headers=headers)print(response.text)

驗證后發(fā)現(xiàn),它并不是直接通過html實現(xiàn)數(shù)據(jù)的顯示,可能是ajax實現(xiàn),再進行驗證。

也可以直接抓包,看對應的url是否有需要的數(shù)據(jù):


這些由其它請求產(chǎn)生的數(shù)據(jù),我們可以叫他們是動態(tài)加載出來的數(shù)據(jù)!

進行ajax抓包驗證:


可以發(fā)現(xiàn),首頁的數(shù)據(jù)是由ajax提供的!

但我們需要的是每一家企業(yè)的詳情頁中的所有信息,該如何處理呢?


我們發(fā)現(xiàn),每一行公司數(shù)據(jù)中都包含著一個ID數(shù)據(jù),我們點開其中一個,進入詳情頁:

發(fā)現(xiàn),該詳情頁的url是通過id來進行訪問的,意思是每個id都對應了一個唯一的詳情頁面,我們可以先獲取它的id,再以它的id為參數(shù),進行詳情頁面的請求,即可實現(xiàn)詳細信息的爬取。

我們對詳情頁進行抓包,又發(fā)現(xiàn):

這個網(wǎng)頁又是ajax刷新出來的動態(tài)網(wǎng)頁,所以又可以通過之前的處理辦法,提取其中的json文件:

同時也發(fā)現(xiàn)了它的參數(shù)(id)如下:

域名和id值進行拼接,拼接出一個完整的企業(yè)對應的詳情頁url。

注意:如果是post型,一定要記得傳入?yún)?shù)!否則什么都得不到,因為post需要你向服務器提供數(shù)據(jù),它才會返回相關(guān)的數(shù)據(jù)給你!

我們先對具體的詳情頁面進行試驗,發(fā)現(xiàn)可以進行爬取:

import requests import json if __name__=="__main__":url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}data={'id': 'ed59438f34ae47e794f4c7ee5137c1f7',}response=requests.post(url=url,data=data,headers=headers)list_data=response.json()fp=open('./藥監(jiān)局.json','w',encoding='utf-8')json.dump(list_data,fp=fp,ensure_ascii=False)print('Over!!!')

接下來的任務就是將首頁中獲取的id與詳情頁面的url聯(lián)系在一起,從而實現(xiàn)詳情頁的爬取:

import requests import pandas as pd import json if __name__=="__main__":# 1、批量獲取不同企業(yè)的id值url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'# 首頁的請求為post,返回值為jsonheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 傳入post所需參數(shù)data={'on': 'true','page': '1', #代表第幾頁'pageSize': '15','productName':'','conditionType': '1','applyname':'','applysn':'',}response=requests.post(url=url,data=data,headers=headers)list_data=response.json()['list']list_id=[]for i in list_data:# 存入相關(guān)的id(共15個)list_id.append(i['ID'])# print(i)# print(list_id)# ['ed59438f34ae47e794f4c7ee5137c1f7', 'd5046c860bbb4e5198fa0dd99382b262', '8bc468fcdb83488681c616d2f7c59149',# '5e45595403cc4509a266666a8a513c46', '246c9e4e2ad64e3f9518908e97a826f7', '76ec5f5a9048457986029282d0f99551',# '670daa3bed864e029c4a17479314240b', '6aab6520cc164b9c9a86d3b5a371152e', 'e8d9c8e820f64c9b8b4c913bafdffecc',# 'f546d7d0b7a34944814291e2c0808500', 'aa42d5a6f10349b98f2fea44867a792c', '7b11ca443c804922815a9410e1fc6c3a',# '72cf694b44a34627b27f6174332b69b1', '47cad475ffb6445da68a8eb83d89fd5f', '165b8a8d86314d5096ebe4e97ca0dd31']# 2、獲取企業(yè)詳情數(shù)據(jù)post_url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'# 同樣也是post型,需要傳入具體的參數(shù)final_data=[]for i in list_id:# 遍歷之前我們獲取到的每一個id,進行每一個數(shù)據(jù)的讀取post_data = {'id': i}post_response = requests.post(url=post_url, data=post_data, headers=headers)final_data.append(post_response.json())final_data=pd.DataFrame(final_data)# 將數(shù)據(jù)存入csv表格中# csv表格的編碼為gbk,pycharm自帶的編碼是utf-8final_data.to_csv('藥監(jiān)局.csv',encoding='gbk')


進一步,對所有頁碼進行遍歷:(就是多了個循環(huán),用于對頁碼進行遍歷)

import requests import pandas as pd if __name__=="__main__":# 用于存儲所有獲取到的數(shù)據(jù)final_data = []# 1、批量獲取不同企業(yè)的id值url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'# 首頁的請求為post,返回值為jsonheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 傳入post所需參數(shù)for page in range(1,6): #先只要前五頁page=str(page)data={'on': 'true','page': page, #代表第幾頁'pageSize': '15', #代表一頁有15個id'productName':'','conditionType': '1','applyname':'','applysn':'',}response=requests.post(url=url,data=data,headers=headers)list_data=response.json()['list']list_id=[]for i in list_data:# 存入相關(guān)的id(共15個)list_id.append(i['ID'])# print(i)# 2、獲取企業(yè)詳情數(shù)據(jù)# 同樣也是post型,需要傳入具體的參數(shù)for i in list_id:# 遍歷之前我們獲取到的每一個id,進行每一個數(shù)據(jù)的讀取post_data = {'id': i}post_response = requests.post(url=post_url, data=post_data, headers=headers)final_data.append(post_response.json())final_data=pd.DataFrame(final_data)# 將數(shù)據(jù)存入csv表格中# csv表格的編碼為gbk,pycharm自帶的編碼是utf-8final_data.to_csv('藥監(jiān)局ALL.csv',encoding='gbk')

二、聚焦爬蟲(數(shù)據(jù)解析)

數(shù)據(jù)解析原理:使用數(shù)據(jù)解析,是因為有一些數(shù)據(jù)存在于標簽之間或者在標簽對應的屬性值中。我們需要定位到具體標簽的位置,或是標簽相應的屬性的位置,再獲取標簽中相關(guān)的數(shù)據(jù)。

大致有三類:
1、正則(適用于多種語言)
2、bs4(僅適用于Python)
3、xpath(重要)

編碼流程變?yōu)?#xff1a;
1、指定url
2、發(fā)起請求
3、獲取相應數(shù)據(jù)
4、數(shù)據(jù)解析
5、持久化存儲

一、正則解析(爬取糗事百科中糗圖中所有的圖片)


從網(wǎng)站中可以看到:

圖片是存儲在具體的一個網(wǎng)頁中的。

import requests if __name__=='__main__':#如何爬取圖片url='http://pic.qiushibaike.com/system/pictures/12413/124132664/medium/LBBZ8DUMBG0M6JEZ.jpg'#content返回的是二進制形式的圖片數(shù)據(jù)# text(字符串) content(二進制) json()(對象)img_data=requests.get(url=url).contentwith open('./qiutu.jpg','wb') as fp:fp.write(img_data)

步驟如下:先獲取一整個頁面,再對這個頁面進行解析,獲取其中的圖片。


進行滑動后發(fā)現(xiàn),它并不會像豆瓣一樣動態(tài)更新,而是直接一頁顯示完,我們可以通過遍歷page來獲取所有圖片。


可以發(fā)現(xiàn),紅框標簽中包含了這一頁的所有糗圖。

進一步發(fā)現(xiàn),在每一個糗圖子類中的thumb標簽下,存儲了糗圖(只有糗圖,沒有其他文字):

img src中存放的就是圖片的地址(.jpg):

import requests import re if __name__=="__main__":url='https://www.qiushibaike.com/imgrank/'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}# 使用通用爬蟲對url對應的一整張頁面進行爬取response=requests.get(url=url,headers=headers)# 獲取源碼數(shù)據(jù)page_text=response.text# 使用聚焦爬蟲將頁面中所有具體圖片進行聚焦爬蟲# 我們需要獲取所有圖片對應的src值,再對每個src值單獨發(fā)送請求,得到每一張圖片# < div class ="thumb" >## < a href = "/article/124132664" target = "_blank" ># < img src = "//pic.qiushibaike.com/system/pictures/12413/124132664/medium/LBBZ8DUMBG0M6JEZ.jpg" alt = "糗事#124132664" class ="illustration" width="100%" height="auto" ># < / a >## < / div >ex='<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'img_src_list=re.findall(ex,page_text,re.S)print(img_src_list)# 發(fā)現(xiàn)存下來的地址缺少協(xié)議頭:https:# '//pic.qiushibaike.com/system/pictures/12412/124120243/medium/BOKRF0W5573YHP7J.jpg'# 在添加協(xié)議頭后,再使用get即可獲取圖片

二、bs4數(shù)據(jù)解析


soup提供的用于數(shù)據(jù)解析的函數(shù)

1、soup.tagName(自己輸入)


這里的html head body div都是tagName(標簽名)

它只返回第一次出現(xiàn)的tagName對應的標簽,不能返回多個。

2、soup.find()

1)soup.find(‘div’)等同于soup.div

2)屬性定位(根據(jù)具體屬性定位到對應屬性的標簽)
soup.find(‘div’,class_/id/attr=‘song’)(這里class要加下劃線,不然會被當作關(guān)鍵字)

3、soup.find_all()

find_all會返回符合要求的所有標簽,用法同soup.find()

4、soup.select()

需要傳入某種選擇器(id、類、標簽選擇器),返回是一個列表

class選擇器:.類名
標簽選擇器:直接寫標簽名
id選擇器:#Id

層級選擇器:

(大于號表示一個層級,也可以將大于號替換為空格,代表之間有多個層級)

soup.select(’.tang > ul > li > a’):查找.tang類下的ul標簽下的li標簽下的a標簽

print(soup.select('div .thumb > a > img'))

選擇div標簽中類名為thumb的類下面的標簽為a的下面的標簽為img的內(nèi)容。

[<img alt="糗事#124138955" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124138955/medium/G7V66LF8S6TGOU6G.jpg" width="100%"/>, <img alt="糗事#124136388" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124136388/medium/48MW1SMPCL45S4Z4.jpg" width="100%"/>, <img alt="糗事#124123833" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124123833/medium/PGFQADGTCL8T0EMD.jpg" width="100%"/>, <img alt="糗事#124130144" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124130144/medium/0RUTLVJ9L534RDCG.jpg" width="100%"/>, <img alt="糗事#124129027" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124129027/medium/MZ936V0QCZBA0DIX.jpg" width="100%"/>, <img alt="糗事#124015279" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12401/124015279/medium/B8ROANAYSIWZQ07X.jpg" width="100%"/>, <img alt="糗事#124039381" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12403/124039381/medium/N6P3FHIGAV0N4Q1U.jpg" width="100%"/>, <img alt="糗事#124132227" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124132227/medium/C4MRAF8159IZEAD9.jpg" width="100%"/>, <img alt="糗事#124131947" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131947/medium/ES1BAH06YM3O2AC7.jpg" width="100%"/>, <img alt="糗事#124137047" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124137047/medium/FZIWPL2PFOFYQMRQ.jpg" width="100%"/>, <img alt="糗事#124138959" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124138959/medium/EULVRT9M3ZZFDQOQ.jpg" width="100%"/>, <img alt="糗事#124139238" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124139238/medium/JY5AT3YY3JTA4SSY.jpg" width="100%"/>, <img alt="糗事#124128456" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124128456/medium/INCK9584YU11CLCO.jpg" width="100%"/>, <img alt="糗事#124134443" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124134443/medium/4WYYQG8Z3VD7AQ9Z.jpg" width="100%"/>, <img alt="糗事#124131716" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131716/medium/LTK72H5NS7X3KO0R.jpg" width="100%"/>, <img alt="糗事#123999393" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12399/123999393/medium/EWBBQAMBHDBE3H4G.jpg" width="100%"/>, <img alt="糗事#124135221" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124135221/medium/0R2D84TTU3GHBOJG.jpg" width="100%"/>, <img alt="糗事#124131622" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131622/medium/BJS1EAY8DK0M2Q59.jpg" width="100%"/>, <img alt="糗事#124130884" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124130884/medium/TZF8FMUCXDKKZWM3.jpg" width="100%"/>, <img alt="糗事#124135578" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124135578/medium/9S28RZ4PIP610QQ5.jpg" width="100%"/>, <img alt="糗事#124136384" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124136384/medium/YHEGWI2C4DVYR7BV.jpg" width="100%"/>, <img alt="糗事#124134929" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124134929/medium/JP7Q2UQ4XTG8ZPGF.jpg" width="100%"/>, <img alt="糗事#124129563" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124129563/medium/FQAINA29JKXU181G.jpg" width="100%"/>, <img alt="糗事#124139821" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124139821/medium/V41ONJ5MYOZRHABV.jpg" width="100%"/>, <img alt="糗事#124123264" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124123264/medium/AHAVUX4WW70CAMRI.jpg" width="100%"/>]

獲取標簽中的文本數(shù)據(jù)

之前是定位到具體的標簽,現(xiàn)在是利用定位到的具體標簽來提取其中的數(shù)據(jù)。

soup.a.text/string/get_text(),用于讀取文本數(shù)據(jù)

text/get_text():可以獲取一個標簽中的所有文本內(nèi)容

string:只可以獲取該標簽下面直系的文本內(nèi)容

我們上面想要的src不屬于文本數(shù)據(jù)!

獲取標簽中屬性值

直接使用 [ 屬性名 ]

print(soup.select('div .thumb a img')[0]['src'])

我們成功從中提取到了src!!!

//pic.qiushibaike.com/system/pictures/12405/124058306/medium/X8FX01T2TYWYF66L.jpg

三、bs4實戰(zhàn):爬取三國演義小說所有的章節(jié)標題和章節(jié)內(nèi)容



這個跟爬取藥監(jiān)局的例子相似,需要現(xiàn)在主頁面獲取到每一個子頁面的url,再對每一個子頁面進行訪問,讀取子頁面中的文本內(nèi)容。


這個網(wǎng)站并不是動態(tài)加載(ajax),而是將具體網(wǎng)址寫入標簽屬性中,所以需要用到數(shù)據(jù)解析!(藥監(jiān)局那個是動態(tài)加載)

import requests from bs4 import BeautifulSoup if __name__=="__main__":# 對首頁頁面數(shù)據(jù)進行爬取url='https://www.shicimingju.com/book/sanguoyanyi.html'# 進行UA偽裝headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}page_text=requests.get(url=url,headers=headers).text# 在首頁中解析出章節(jié)的標題和詳情頁的url# 1、實例化Beautiful Soup對象,將頁面源碼加載到該對象中soup=BeautifulSoup(page_text,'lxml')# print(soup.select('.book-mulu li a'))book_list=soup.select('.book-mulu li a')book_url=[]# https://www.shicimingju.com/book/sanguoyanyi/1.html# 對比原網(wǎng)址,添加https://www.shicimingju.comhead='https://www.shicimingju.com'for i in book_list:temp_str=head+i['href']book_url.append(temp_str)# print(book_url)# 'https://www.shicimingju.com/book/sanguoyanyi/1.html'# 將書中內(nèi)容存入字典books={}fp=open('./sanguo.txt','w',encoding='utf-8')for url in book_url:page_text=requests.get(url=url,headers=headers).textsoup=BeautifulSoup(page_text,'lxml')div_tag=soup.find('div',class_='chapter_content')content=div_tag.textprint(content)

四、xpath解析

最常用且最便捷高效的一種新方法,通用性。

xpath解析原理:

1、實例化一個etree的對象,且需要將被解析的頁面源碼數(shù)據(jù)加載到該對象中

2、調(diào)用etree對象中的xpath方法,結(jié)合著xpath表達式實現(xiàn)標簽的定位和內(nèi)容的捕獲

如何實例化一個etree對象:from lxml import etree

1、將本地html文檔重點源碼數(shù)據(jù)加載到etree對象中:
etree.parse(filePath)

2、可以將從互聯(lián)網(wǎng)上獲取的源碼加載到該對象中:
etree.HTML(‘page_text’)

xpath(‘xpath表達式’),返回一個列表!

response=requests.get(url=url,headers=headers).texttree=etree.HTML(response)r=tree.xpath('/html/head/title')r=tree.xpath('/html//div')r=tree.xpath('//div')

/ 表示從根節(jié)點開始,一個 / 表示一個層級,而//表示多個層級,或者表示可以從任意位置開始定位。(所有)

屬性定位:

tagName[@attrName=“attrValue”]

r=tree.xpath('//div[@class="song"]')

索引定位:

r=tree.xpath('//div[@class="song"]/p')

表示div標簽下,類名為song下的p標簽,可以在后面使用 [1] 索引,從1開始!!!

取文本:

r=tree.xpath('//div[@class="song"]/ul/li[1]/a/text()')# 返回結(jié)果為列表

取得,a標簽下的文本內(nèi)容。
/text(),獲取的是標簽中直系的文本內(nèi)容

//text(),獲取的是標簽中非直系(所有的)文本內(nèi)容

取屬性:

r=tree.xpath('//div[@class="song"]/img/@src')# 返回結(jié)果為列表

/@屬性名 (/@src,獲取img標簽下的src屬性)

五、xpath解析實戰(zhàn):58二手房

三、selenium模塊的基本使用

一、引入

回顧一下,我們是怎么判斷網(wǎng)頁中的數(shù)據(jù)是否為動態(tài)加載:

打開抓包工具,在當前網(wǎng)頁的url對應內(nèi)容中進行搜索,看是否有相應的內(nèi)容:



搜索不到,顯然就是動態(tài)加載的!

那如何快速,準確的找到需要的數(shù)據(jù)在哪里呢?

在紅框中按下 ctrl + f 輸入你需要查詢的信息,進行搜索。

可以發(fā)現(xiàn),如果使用像上面的方法進行查找的話,會比較耗時,我們就需要使用selenium模塊!

二、selenium模塊

1、作用

1、它能幫助便捷的獲取網(wǎng)站中動態(tài)加載的數(shù)據(jù)!
2、便捷地使用模擬登陸!

selenium是基于瀏覽器自動化的一個模塊。(就是自動地使用瀏覽器的相關(guān)功能,讓他自己去操縱瀏覽器,不用我們自己去弄)

2、使用流程

環(huán)境安裝:pip install selenium
下載一個瀏覽器的驅(qū)動程序:
http://npm.taobao.org/mirrors/chromedriver/

驅(qū)動程序和版本要對應。對照表

再把驅(qū)動放在你項目的文件夾中。


實例化一個瀏覽器對象(傳入瀏覽器的驅(qū)動程序)

from selenium import webdriver # 實例化一個瀏覽器對象(傳入瀏覽器的驅(qū)動程序) bro=webdriver.Chrome(executable_path='./chromedriver.exe')

用代碼操縱你的瀏覽器!

以藥監(jiān)局的例子為例:

1、先操縱瀏覽器打開藥監(jiān)局的網(wǎng)站:

from selenium import webdriver # 實例化一個瀏覽器對象(傳入瀏覽器的驅(qū)動程序) bro=webdriver.Chrome(executable_path='./chromedriver.exe') # 對指定網(wǎng)頁發(fā)送請求 bro.get('http://scxk.nmpa.gov.cn:81/xk/')

2、獲取瀏覽器當前頁面的頁面源碼數(shù)據(jù)(公司名字)

from selenium import webdriver from lxml import etree from time import sleep # 實例化一個瀏覽器對象(傳入瀏覽器的驅(qū)動程序) bro=webdriver.Chrome(executable_path='./chromedriver.exe') # 對指定網(wǎng)頁發(fā)送請求 bro.get('http://scxk.nmpa.gov.cn:81/xk/') # 獲取瀏覽器當前頁面的源碼數(shù)據(jù) page_text=bro.page_source# 解析企業(yè)名稱(以xpath為例) tree=etree.HTML(page_text) li_list=tree.xpath('//ul[@id="gzlist"]/li') for li in li_list:name=li.xpath('./dl/@title')[0]print(name) # 關(guān)閉瀏覽器 sleep(5) #暫停五秒后關(guān)閉 bro.quit()

3、其他自動化操作(以淘寶搜索為例)

我們要先找到搜索框在哪里?

打開檢查,找到搜索框?qū)脑创a,發(fā)現(xiàn)里面有一個input標簽,id=‘q’。

標簽定位:

search_input=bro.find_element_by_id('q')

如何向搜索框中傳值呢?

search_input=bro.find_element_by_id('q') # 標簽交互(傳入想輸入搜索框的東西) search_input.send_keys('Iphone')

我們還需要點擊搜索按鈕,我們再去找搜索按鈕對應的源碼:


它有兩個標簽名,用哪一個都行但不能一起用!

from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='./chromedriver.exe')bro.get('https://www.taobao.com/')# 想要通過搜索框搜索數(shù)據(jù) # 先要找到那個搜索框(標簽定位) search_input=bro.find_element_by_id('q') # 標簽交互(傳入想搜索的東西) search_input.send_keys('Iphone')# 點擊搜索按鈕 btn=bro.find_element_by_css_selector('.btn-search') #這里用class搜索也可以 sleep(3) btn.click()

因為沒有登錄,所以運行結(jié)果如下:

如何實現(xiàn)頁面滾輪下滑效果呢?

進入網(wǎng)頁檢查中的console輸入:

即可實現(xiàn)滾輪效果,現(xiàn)在需要使得程序知道怎么操作。

from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='./chromedriver.exe')# 發(fā)起請求 bro.get('https://www.taobao.com/')# 想要通過搜索框搜索數(shù)據(jù) # 先要找到那個搜索框(標簽定位) search_input=bro.find_element_by_id('q') # 標簽交互(傳入想搜索的東西) search_input.send_keys('Iphone')# 實現(xiàn)滾輪下滑效果 # 需要執(zhí)行一組js程序 bro.execute_script('window.scrollTo(0,document.body.scrollHeight)') sleep(2)# 點擊搜索按鈕 btn=bro.find_element_by_css_selector('.btn-search') #這里用class搜索也可以bro.get('https://www.baidu.com') sleep(2) # 回退(倒退) bro.back() sleep(2) # 前進 bro.forward() sleep(3) btn.click()

三、selenium處理iframe

什么是iframe???
用于實現(xiàn)網(wǎng)頁的嵌套。

我們來看看如何拖動一個方塊:


我們先找到需要被拖動方塊的源碼。

為什么會報錯呢?
它說沒有找到我們想要的標簽,我們id也沒有輸錯。
原因:

它是包含在一個叫做iframe的標簽下,所以才導致程序無法找到。

如何定位的標簽存在于iframe標簽之中,直接尋找是尋找不到的!

實現(xiàn)在iframe下的定位:

from selenium import webdriver from time import sleepbro=webdriver.Chrome(executable_path='./chromedriver.exe')bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') # 如何定位的標簽存在于iframe標簽之中,直接尋找是尋找不到的! # 傳入的參數(shù)是Id bro.switch_to.frame('iframeResult') #切換瀏覽器標簽定位的作用域(默認為最外面大的html標簽)div=bro.find_element_by_id('draggable')

模擬人操作鼠標,進行滑塊的拖動:

from selenium import webdriver from time import sleep # 導入動作鏈對應的類 from selenium.webdriver import ActionChainsbro=webdriver.Chrome(executable_path='./chromedriver.exe')bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') # 如何定位的標簽存在于iframe標簽之中,直接尋找是尋找不到的! # 傳入的參數(shù)是Id bro.switch_to.frame('iframeResult') #切換瀏覽器標簽定位的作用域(默認為最外面大的html標簽) div=bro.find_element_by_id('draggable') # 動作鏈 action=ActionChains(bro) # 點擊長按指定的標簽 action.click_and_hold(div)for i in range(5):# perform()立即執(zhí)行動作鏈操作action.move_by_offset(17,0).perform() #做移動偏移(x,y)傳入水平、豎直方向偏移sleep(0.3) # 釋放工作鏈 action.reset_actions()bro.quit()

四、selenium模擬登錄(模擬登錄QQ空間)


主要就是紅框中的三個模塊:賬號、密碼、登錄按鈕。


由于,默認情況下,是要我們進行掃碼,我們還需要點擊右下角賬號密碼登錄。


注意!這里的賬號密碼登錄還是在iframe標簽下!!所以不能直接請求。

from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='../../chromedriver.exe') bro.get('https://qzone.qq.com/') # 參數(shù)為id bro.switch_to.frame('login_frame') a_tag=bro.find_element_by_id('switcher_plogin') a_tag.click() #定位到之后進行點擊


定位賬號和密碼:

from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='../../chromedriver.exe') bro.get('https://qzone.qq.com/') # 參數(shù)為id bro.switch_to.frame('login_frame') a_tag=bro.find_element_by_id('switcher_plogin') a_tag.click() #定位到之后進行點擊# 尋找用戶名、密碼輸入框 userName_tag=bro.find_element_by_id('u') passWord_tag=bro.find_element_by_id('p')# 錄入數(shù)據(jù) userName_tag.send_keys('1229482340') passWord_tag.send_keys('1111')# 尋找工作按鈕 btn=bro.find_element_by_id('login_button') btn.click()sleep(3)bro.quit()

現(xiàn)在不能直接登錄,需要進行滑塊驗證!

五、讓瀏覽器不可視(無頭瀏覽器)

from selenium import webdriver from selenium.webdriver.chrome.options import Options# 無可視化參數(shù) chrome_options=Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu')bro=webdriver.Chrome(executable_path='./chromedriver.exe',options=chrome_options) bro.get('https://www.baidu.com')

六、規(guī)避selenium被網(wǎng)站檢測

from selenium import webdriver # 實現(xiàn)無頭瀏覽器 from selenium.webdriver.chrome.options import Options # 實現(xiàn)規(guī)避檢測 from selenium.webdriver import ChromeOptions# 無可視化參數(shù) chrome_options=Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu')# 如何讓selenium規(guī)避被檢測到的風險 option=ChromeOptions() option.add_experimental_option('excludeSwitches',['enable-automation'])bro=webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options,options=option) bro.get('https://www.baidu.com')

總結(jié)

以上是生活随笔為你收集整理的爬虫实战(自用)requests模块、聚焦爬虫(数据解析)、selenium模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。