爬取網站的流程:
- 確定網站哪個url是數據的來源
- 簡要分析網站結構,查看數據在哪裏
- 查看是否有分頁,解決分頁問題
- 發送請求,查看response.text裏面是否有我們想要的數據
- 如果有數據,提取,保存
注意事項:
- 剛開始做爬蟲項目,先不要用類做,只需要關注數據的來源等問題的解決,不要關注封裝結構的處理
一、xpath應用
(一)扇貝單詞項目
import requests,re
from lxml import etree
base_url = 'https://www.shanbay.com/wordlist/110521/232414/?page=%s'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
def get_value(value):
if value:
return value[0]
return ''
result = []
for i in range(1,4):
response = requests.get(base_url%i,headers=headers)
html = etree.HTML(response.text)
# print(etree.tostring(html,pretty_print=True,encoding='utf-8').decode('utf-8'))
tr_list = html.xpath('//tbody/tr[@class="row"]')
for tr in tr_list:
item = {}
word = get_value(tr.xpath('.//td[@class="span2"]/strong/text()'))
mean = get_value(tr.xpath('.//td[@class="span10"]/text()'))
item[word] = mean
result.append(item)
print(result)
封裝
import requests,json
from lxml import etree
class Shanbei(object):
def __init__(self,url,headers):
self.url = url
self.headers = headers
self.result = []
self.word_mean()
self.save_data()
def get_value(self,value):
if value:
return value[0]
return ''
def word_mean(self):
for i in range(1, 4):
response = requests.get(self.url % i, headers=headers)
html = etree.HTML(response.text)
# print(etree.tostring(html,pretty_print=True,encoding='utf-8').decode('utf-8'))
tr_list = html.xpath('//tbody/tr[@class="row"]')
for tr in tr_list:
item = {}
word = self.get_value(
tr.xpath('.//td[@class="span2"]/strong/text()'))
mean = self.get_value(tr.xpath('.//td[@class="span10"]/text()'))
item[word] = mean
self.result.append(item)
def save_data(self):
with open('shanbei_word.json','w',encoding='utf-8') as fp:
json.dump(self.result,fp)
if __name__ == '__main__':
base_url = 'https://www.shanbay.com/wordlist/110521/232414/?page=%s'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
Shanbei(base_url,headers)
with open('shanbei_word.json','r') as fp:
result = json.load(fp)
print(result)
(二)網易雲音樂項目
可迭代對象:有__iter__
屬性的對象。
迭代器:有__next__
屬性的對象。
兩個可以轉換嗎?
iter(可迭代對象)---->返回值爲迭代器
可迭代對象都有哪些?
- list
- dict
- tuple
- str
- bytes
- set
- 迭代器
- 生成器
- 文件流
打印一個文件,同時輸出行號
fp = open('shanbei_word.py','r',encoding='utf-8')
print(fp)
for i,content in enumerate(fp,1):
print(i,content)
代碼
import requests
from lxml import etree
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
def get_xpath(url):
response = requests.get(url,headers=headers)
return etree.HTML(response.text)
# 獲取歌手介紹
def get_info(url,item):
html = get_xpath(url)
introduce_list = html.xpath('//div[@class="n-artdesc"]/p/text()')
introduce = ''.join(introduce_list)
item['introduce'] = introduce
result.append(item)
# 獲取歌手
def get_single(url):
html = get_xpath(url)
single_names = html.xpath('//ul[@id="m-artist-box"]/li/p/a[1]/text()|//ul[@id="m-artist-box"]/li/a[1]/text()')
single_urls = html.xpath('//ul[@id="m-artist-box"]/li/p/a[1]/@href|//ul[@id="m-artist-box"]/li/a[1]/@href')
for i,name in enumerate(single_names):
item = {}
item['name'] = name
item['url'] = 'https://music.163.com' + single_urls[i].replace(' ','')
# 獲取歌手介紹
url = item['url'].replace('?','/desc?')
get_info(url,item)
# 獲取姓名首字母分類頁面
def get_type_page(url):
html = get_xpath(url)
nametype_url_list = html.xpath('//ul[@id="initial-selector"]/li[position()>1]/a/@href')
for one in nametype_url_list:
url = 'https://music.163.com' + one
# 獲取歌手
get_single(url)
# 注意錨點
base_url = 'https://music.163.com/discover/artist'
# 獲取歌手地區分類頁面url
def get_type():
html = get_xpath(base_url)
localtype_url_list = html.xpath('//ul[@class="nav f-cb"]/li/a[contains(@href,"id")]/@href')
for one in localtype_url_list:
url = 'https://music.163.com'+ one
# 獲取姓名首字母分類頁面
get_type_page(url)
if __name__ == '__main__':
result = []
get_type()
print(result)
封裝
import requests,json
from lxml import etree
class Music(object):
def __init__(self,base_url):
self.base_url = base_url
self.headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
self.result = []
self.get_type()
# 注意錨點
def get_xpath(self,url):
response = requests.get(url, headers=self.headers)
return etree.HTML(response.text)
# 獲取歌手地區分類頁面url
def get_type(self):
html = self.get_xpath(self.base_url)
localtype_url_list = html.xpath(
'//ul[@class="nav f-cb"]/li/a[contains(@href,"id")]/@href')
for one in localtype_url_list:
url = 'https://music.163.com' + one
# 獲取姓名首字母分類頁面
self.get_type_page(url)
# 獲取姓名首字母分類頁面
def get_type_page(self,url):
html = self.get_xpath(url)
nametype_url_list = html.xpath(
'//ul[@id="initial-selector"]/li[position()>1]/a/@href')
for one in nametype_url_list:
url = 'https://music.163.com' + one
# 獲取歌手
self.get_single(url)
# 獲取歌手
def get_single(self,url):
html = self.get_xpath(url)
single_names = html.xpath(
'//ul[@id="m-artist-box"]/li/p/a[1]/text()|//ul[@id="m-artist-box"]/li/a[1]/text()')
single_urls = html.xpath(
'//ul[@id="m-artist-box"]/li/p/a[1]/@href|//ul[@id="m-artist-box"]/li/a[1]/@href')
for i, name in enumerate(single_names):
item = {}
item['name'] = name
item['url'] = 'https://music.163.com' + single_urls[i].replace(' ','')
# 獲取歌手介紹
url = item['url'].replace('?', '/desc?')
self.get_info(url, item)
# 獲取歌手介紹
def get_info(self,url, item):
html = self.get_xpath(url)
introduce_list = html.xpath('//div[@class="n-artdesc"]/p/text()')
introduce = ''.join(introduce_list)
item['introduce'] = introduce
self.result.append(item)
if __name__ == '__main__':
base_url = 'https://music.163.com/discover/artist'
m = Music(base_url)
with open('singer.json','w',encoding='utf-8') as fp:
json.dump(m.result,fp)
二、反爬措施以及應對措施
反爬策略
1.通過user-agent客戶端表示判斷
解決辦法:將user-agent封裝到請求頭中
2.通過訪問頻率判斷
解決辦法:設置爬取間隔
n = random.randint(5)
time.sleep(n)
3.查封ip
解決辦法:設置代理ip
4.頁面內容無法直接獲取數據,頁面都是js代碼
解決辦法:使用selenium+phantomjs可以獲取頁面數據
selenium+phantomjs
selenium:是web自動測試的工具。
phantomjs:是一個無界面的瀏覽器,所以它可以運行js代碼,幫我們拿到頁面數據。
它們配合使用就可以解決頁面是js代碼的數據獲取問題
下載和安裝
複製到anaconda的script目錄下,然後執行
pip install selenium==2.48.0
爲了使測試工具與瀏覽器交互,需要使用ChromeDriver
查看google版本號
選擇大版本號對應,小版本號最接近的
解壓後同樣放在anaconda的script目錄中
三、動態html頁面的處理方法
(一)常見的頁面技術
1.js
html是頁面的骨架,css是頁面的裝飾,js是頁面的靈魂。
2.jquery
jquery是一個庫,可以使js代碼更加簡化。
3.ajax
是一種技術,web頁面的異步請求。
4.DHTML
DHTML是Dynamic HTML的縮寫,意思是動態的HTML。它並不是一門獨立的語言,實際上任何可以實現頁面動態改變的方法都可以成爲DHTML。