目錄css
本篇爲技術篇,,會講解各類爬蟲庫的使用,至於庫的安裝在安裝篇已經介紹了html
這種狀況是網頁沒有設置編碼,獲取不到,因此使用了默認的編碼,這個時候中文就會出現亂碼的狀況python
只須要多加一行代碼便可git
response.encoding='gb2312'
免費的代理我試着不行,暫時不研究了,寫一下付費的代理是怎麼使用的github
我購買的是訊代理,購買以後先在白名單裏面添加本身的IP,而後點擊生成APIweb
選擇訂單,選擇一個城市,而後生成jsonmongodb
接下來使用Python獲取代理IP,我是獲取了以後存到數據庫了chrome
import pyodbc import json import requests import sys import time headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} conn = pyodbc.connect('DRIVER={SQL Server};SERVER=192.168.3.8,1433;DATABASE=VaeDB;UID=sa;PWD=test123') cursor = conn.cursor() r = requests.get('http://apXXXXXXXXXXXXXXXXXXXXX40300', headers=headers) print(r.text) jsonobj = json.loads(str(r.text)) datetime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) cursor.execute( 'update ProxyIP set IP=?,UpdateDate=? where Id=1', (jsonobj['RESULT'][0]['ip']+':'+jsonobj['RESULT'][0]['port'],datetime)) conn.commit() sys.exit()
怎麼使用代理,這個分爲好幾個狀況,我使用的是Selenium,就寫這個,requests的用到再補充數據庫
conn = pyodbc.connect( 'DRIVER={SQL Server};SERVER=111.108.8.2,1433;DATABASE=VaeDB;UID=sa;PWD=testxxxx') cursor = conn.cursor() cursor.execute(""" select IP from dbo.ProxyIP """ ) data = cursor.fetchone() proxyip=str(data[0]) chrome_options=webdriver.ChromeOptions() chrome_options.add_argument('--proxy-server=http://'+ proxyip) browser = webdriver.Chrome(chrome_options=chrome_options)
我使用BeautifulSoup爬取了好幾萬的數據了,對於普通的網站,BeautifulSoup真的很好用json
#BeautifulSoup初始化能夠自動更正HTML格式,補全沒有閉合的元素 print (soup.prettify())#以標準的縮進格式輸出 print(soup.title)#標題 print(soup.title.string)#標題裏面的內容 print(soup.title.name)#title的節點名稱,就是title print(soup.p)#第一個p元素的內容 print(soup.p.attrs)#第一個p元素的全部屬性和值 print(soup.p['class'])#第一個p元素class屬性的值 print(soup.p['name'])#第一個p元素name屬性的值 print(soup.p.b.string)#第一個p標籤下的b標籤的文本內容 print(soup.p.contents)#第一個p元素下的全部子節點,不包括孫子節點 #第一個p元素全部的子節點 print(soup.p.descendants) for i,child in enumerate(soup.p.descendants): print(i,child) print(soup.p.parent)#第一個p元素的父節點 #第一個p元素全部的父節點 print(soup.p.parents) print(list(enumerate(soup.p.parents))) print(soup.p.next_sibling)#第一個p元素的下一個兄弟節點,注意有回車的時候要寫兩個next_sibling print(list(enumerate(soup.p.next_siblings)))#第一個p元素後面的全部兄弟節點 print(soup.p.previous_sibling)#第一個p元素的上一個兄弟節點 print(list(enumerate(soup.p.previous_siblings)))#第一個p元素前面的全部兄弟節點 ######################################################### #下面這些是比較經常使用的,上面的瞭解一下便可 # 判斷某個標籤是否有屬性,例如img標籤有一個alt屬性,有時候img沒有alt屬性,我就能夠判斷一下,不然出錯 if img.attrs.get('alt'): soup.find(id='text-7').find_all(name='li') #根據文本查找到該標籤 # 例以下面的,根據Description查找含有Description的第一個p元素 test = soup.find(lambda e: e.name == 'p' and 'Description' in e.text) # 其實若是是直接子元素的話,也可使用parent,可是這個不多用,適用狀況很少 test= soup.find(text=re.compile('Description')).parent #查找某個屬性爲包含的標籤 #標籤的屬性有不少值,例如img標籤的alt屬性,有item和img兩個值,能夠經過以下查找 noscript.find_all('img',attrs={'alt':re.compile('item')}) #判斷屬性裏面是否有某個值 if 'Datasheet' in img['alt']: #替換全部的br換行符號 html = get_one_page(url) return html.replace('<br>', '').replace('<br />', '').replace('<br/>', '') #去除最後一個逗號 datasheet_url.rstrip(',') #去除關鍵字和空格,只要後面的內容 #例如 Function : Sensitive Gate Silicon Controlled Rectifiers #獲得的就是Sensitive Gate Silicon Controlled Rectifiers return re.sub(keywords+'.*?[\s]:.*?[\s]', '', child.find(text=re.compile(keywords)).string) #返回某個符號以前的字符 import re text="K6X4008C1F-BF55 ( 32-SOP, 55ns, LL )" b=re.search('^[^\(]*(?=\()',text,re.M) if b: print(b.group(0)) print(len(b.group(0))) else: print('沒有') #關鍵地方是,這裏是匹配的( 括號須要\來轉義一下 ^[^\(]*(?=\() #若是是逗號,能夠寫 ^[^,]*(?=,) #若是是單詞,好比我想匹配Vae這個單詞,以下 text='XuSong Vae hahaha' text2='VV Vae hahaha' b=re.search('^[^Vae]*(?=Vae)',text,re.M) #這個例子很重要,text是能夠正則出XuSong的,可是下面的VV就正則不出來了,由於^是後面的Vae的任意一個單詞,只要前面包含就不行,VV包含了V,因此就不行了,我嘗試着給Vae加括號,也不行.而後我就想了一個辦法,把Vae替換成逗號之類的符號不就能夠了,只要是一個字符就行,以下 text='XuSong Vae hahaha' text2='VV Vae hahaha' b=re.search('^[^,]*(?=,)',text.replace('Vae',','),re.M) #一段HTML元素中去除a標籤,可是保留a標籤的值 return re.sub('(<\/?a.*?>)', '', description_element) #有時候想獲取一段HTML元素內容,由於有的排版在,好比ul和li元素,排版是在的,若是使用text就是一串文本,換行都沒了,能夠這樣 str(child.find(class_='ul2')) #獲取到這段HTML元素以後,使用str函數變成字符串便可 #下一個兄弟元素最好使用find_next_sibling() #等待驗證,和next_sibling比較一下再說 驗證完畢,我來說一下find_next_sibling()和next_sibling的區別 若是想要後面的元素的話,寫find_next_sibling() 若是想要後面的內容的話,寫next_sibling 例如 <a>111</a><p>222</p> 想要獲取p元素應該使用find_next_sibling() <a>111</a>我是文本 想要獲取 我是文本 應該使用next_sibling #Python爬蟲數據插入到MongoDB import pymongo client = pymongo.MongoClient("mongodb://admin:test123@192.168.3.80:27017/") db = client.datasheetcafe collection = db.datasheetcafe collection.insert_one(message)
在爬取一個新網站的時候,我發現網站上的網頁數據全都是動態加載的,瀏覽器加載以後數據纔會顯示,這個時候BeautifulSoup就沒用了,徹底獲取不到HTML節點
這種狀況,可使用Selenium進行動態加載,我使用這個已經爬取了近200萬的數據
#有不顯示瀏覽器的,可是我選擇了Chrome瀏覽器 browser = webdriver.Chrome() #先獲取url,再選擇元素 browser.get(url) div = browser.find_element_by_css_selector('.information') #find_element_by_css_selector這個東西是css選擇器,若是選擇一個就使用這個,想要選擇一堆就加個s,使用find_elements_by_css_selector #後面的類就是. id就是# 標籤名就直接寫,以下 table = browser.find_element_by_css_selector('#part-specs') table.find_elements_by_css_selector('tr') # 獲取屬性的值 tr.get_attribute('class') #對了,下面這個獲取的可不是HTML元素,是一個WebElement元素 table = browser.find_element_by_css_selector('#part-specs') #因此若是你想要HTML元素這樣寫 table = browser.find_element_by_css_selector('#part-specs').get_attribute('outerHTML') #獲取裏面的文本值就這樣寫 browser.find_element_by_css_selector('.part-number').text #至於怎麼判斷元素是否存在的,我寫了if可是沒有,因此我利用try catch幫助解決 try: button=browser.find_element_by_css_selector('#show-secondary-part-list') button.click() except Exception as e: print('沒有這個元素')
有時候Selenium加載一個網頁時間過長了,因此必須設定一個超時時間
browser = webdriver.Chrome() browser.set_page_load_timeout(20) browser.set_script_timeout(20) try: browser.get(address) except TimeoutException: browser.execute_script('window.stop()') div = browser.find_element_by_css_selector('.information') ....
先設定加載時間爲20秒,若是20都沒加載出來,就算了,直接中止加載,爬取網頁內容吧,若是一個HTML元素都沒抓取到,空白頁面,那就try catch跳過這個網頁
默認使用Chrome是加載出來的,也能夠隱藏Chrome瀏覽器,那個無界面PhantomJS已經被淘汰了
chrome_options=webdriver.ChromeOptions() # chrome_options.add_argument('--headless') 若是想不彈出chrome瀏覽器就開啓這兩行,那個PantomJS啥的已通過期了 # chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('--proxy-server=http://'+ proxyip) chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) #這一行是爲了防止網站識別出我是selenium,參考:https://zhuanlan.zhihu.com/p/65077940 browser = webdriver.Chrome(chrome_options=chrome_options)
個人爬蟲爬了一段時間就中止了,selenium控制的瀏覽器要麼變成了空白頁,要麼訪問失敗,最可怕的是頁面卡着不動了,這個時候只能重啓爬蟲程序了,因此我把爬蟲發佈成exe了,我使用Windows自帶的計劃任務,隔一段時間就啓動exe爬蟲,而後問題來了
我必須關閉exe的彈窗,否則加載愈來愈多的exe,內存會崩的,因而我採用了Python多進程
一個進程去爬蟲,一個進程去計時,若是計時10分鐘,就退出exe
可是沒有執行,不管我使用sys.exit()仍是os._exit()都沒法退出exe,至今不知道爲何
沒辦法只好採起了另一種方法,殺進程
import os os.system('taskkill /im conhost.exe /F') # 這兩個不能同時執行,我寫了兩個py,發佈兩個exe執行 os.system('taskkill /im chromedriver.exe /F') os.system('taskkill /im chrome.exe /F')
我把控制檯和Chrome全殺了.......這樣Windows計劃任務會重啓exe,而後過10分鐘我再全殺了.....
對了,Win10的計劃任務也搞了我很久,就是不成功,詳情見Windows計劃任務
暫留......
scrapy startproject tutorial
scrapy genspider quotes quotes.toscrape.com
scrapy crawl quotes
爬蟲小Demo應該不會再更新了,我爬取的東西不可能寫出來了,僅僅介紹技術,授人以漁吧
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://www.zhihu.com/explore", headers=headers) pattern = re.compile('explore-feed.*?question_link.*?>(.*?)</a>', re.S) titles = re.findall(pattern,r.text) print(titles)
講解:headers裏面有瀏覽器標識,不加這個知乎會禁止抓取
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://avatars0.githubusercontent.com/u/13572737?s=460&v=4", headers=headers) with open('Vae.jpg','wb') as f: f.write(r.content)
這個不只能夠爬取圖片,爬取視頻,音頻,也是這樣的
==注意:爬取圖片的時候,不寫headers會報錯,找不到源==
下面是把圖片保存到制定位置的代碼,多了一個判斷文件夾是否存在,不存在就建立文件夾的操做,我是根據圖片的連接截取做爲文件夾的名稱的,使用建立文件夾的os須要導入os
import os def get_allpath(imgurl): info=imgurl[imgurl.index('uploads'):] infos=info.split('/') return infos[0]+"\\"+infos[1]+infos[2]+"\\"+infos[3] def get_path(imgurl): info=imgurl[imgurl.index('uploads'):] infos=info.split('/') return infos[0]+"\\"+infos[1]+infos[2] def create_makedirs(dirpath): if not os.path.exists(dirpath): os.makedirs(dirpath) def get_image(child, path): for img in child.find_all(name='img'): imgurl = img.attrs.get('data-lazy-src') if imgurl: if 'gif' in imgurl: create_makedirs(path+get_path(imgurl)) r = requests.get(imgurl,headers=headers) with open(path+get_allpath(imgurl), 'wb') as f: f.write(r.content) #最後我在調用的時候,直接輸入放到哪裏的路徑便可 path = 'D:\\datasheetcafe\\' get_image(child, path)
其實和爬取圖片是同樣的,只不過換了url而已,這裏以爬取個人嗶哩嗶哩視頻爲例
如圖是個人嗶哩嗶哩發的一個視頻,點擊F12,而後在NetWork裏面找到視頻的那個請求,通常是最大Size的那個
點進去,看到的那一串就是視頻地址
複製視頻地址到python爬蟲裏面,改一下存儲爲.mp4
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://113-219-141-2.ksyungslb.com/upos-sz-mirrorks32u.acgvideo.com/upgcxcode/63/76/19157663/19157663-1-48.mp4?e=ig8euxZM2rNcNbKVhwdVhoMMhwdVhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1562826409&gen=playurl&nbs=1&oi=1947754487&os=ks3u&platform=pc&trid=28dcba5166d84f6f8b078fccbdd41f2e&uipk=5&upsig=cae257a7f3504f28137a3036304288df&uparams=e,deadline,gen,nbs,oi,os,platform,trid,uipk&mid=32059965&ksy_gslb_referer=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2Fav11592898", headers=headers) with open('Vae.mp4','wb') as f: f.write(r.content)
這個網站是這樣的,他的信息是js動態加上去的,並且必須登陸以後才能看到數據
因此我使用BeautifulSoup在線爬不行,我不會
使用了Selenium登陸了,也動態加載頁面了,數據也出來了,可是這個網站特別的不規則,
都沒有class,我很差找規律,也是不會寫......
大佬給我提出個辦法,由於這個網站的頁面很少,也就20幾個,讓我直接保存到本地,而後讀取本地的html爬蟲,這樣就可使用BeautifulSoup了,不錯哦
我直接在網頁上按下了ctrl+s,保存到了本地.........
注意啊!! ctrl+s保存的網頁仍是沒有數據的啊,仍是須要js加載的啊......我忙活了半天,白忙活了
大佬得知此事以後,痛心疾首,說我早就和你說了,複製DOM就能夠了,你不聽 🐷
對此我只能說,我是🐷,我是🐷,我是🐷
正確的作法是,選擇這該死的DOM,右鍵,複製HTML,這樣他的數據啥的,全都有
我是一個一個複製了,而後保存到個人本地html了
若是是不少的話,成百上千的網頁,這樣就不適合手動了,可使用Selenium加載以後保存到本地
我不會放出全部的,寫寫重點
首先要安裝一個爬本地HTML的包
pip install requests-file
from requests_file import FileAdapter def get_one_page(file_name): s = requests.Session() s.mount('file://', FileAdapter()) html = s.get(f'file:///D:/'+file_name+'.html') soup = BeautifulSoup(html, 'lxml') ...省略...