數(shù)據(jù)分析工程師_14A靜態(tài)網(wǎng)站數(shù)據(jù)獲取

  • 1、介紹了Xpath如何在網(wǎng)站的XML中找我們需要爬取的屬性值。
  • 2、介紹了爬蟲如何抓取網(wǎng)站信息。(抓取到交給Xpath解析)
  • 3、小案例1:爬取豆瓣電影評論
  • 4、小案例2:爬取鏈家網(wǎng)信息
  • 5、小案例3:爬取圖片

1.Xpath介紹

XPath 是一門在 XML 文檔中查找信息的語言。

在 XPath 中,有七種類型的節(jié)點:元素、屬性、文本、命名空間、處理指令、注釋以及文檔(根)節(jié)點。XML 文檔是被作為節(jié)點樹來對待的。樹的根被稱為文檔節(jié)點或者根節(jié)點。


image.png

image.png

1、xpath表達式的基本格式

XPath 使用"路徑表達式(Path Expression)"來選取 XML 文檔中的節(jié)點或者節(jié)點集。在形式上,這些路徑表達式和我們在常規(guī)的電腦"文件系統(tǒng)"中看到的表達式非常相似。

  • 斜杠(/)作為路徑內(nèi)部的分割符。
  • 同一個節(jié)點有絕對路徑和相對路徑兩種寫法。
  • 絕對路徑(absolute path)必須 用"/"起首,后面緊跟根節(jié)點,比 如/step/step/....."。
  • 相對路徑(relative path)則是除了絕對路徑以外的其他寫法,比如 step/step,也就是不使用"/"起首。
  • "."表示當(dāng)前節(jié)點。
  • ".."表示當(dāng)前節(jié)點的父子節(jié)點。

2、選擇節(jié)點的基本規(guī)則

image.png

3、選擇節(jié)點的實例

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

<book>
  <title lang="eng">Learning XML</title>
  <price>39.95</price>
</book>

</bookstore>

[例1]
bookstore:選取bookstore元素的所有節(jié)點。
[例2]
/bookstore:選取跟節(jié)點bookstore,這是絕對路徑的寫法。

[例3]
bookstore/book:選取所有屬于bookstore的子元素的book元素,這是絕對路徑的寫法。
[例4]
//book:選擇所有的book子元素,而不管他們在文檔中的位置。

image.png
image.png
image.png

image.png

image.png

image.png

2、簡單爬蟲與數(shù)據(jù)抓取

image.png

網(wǎng)絡(luò)爬蟲一個非常炫酷,同時又非常實用的技術(shù),這個部分我們給大家介紹如何寫程序去完成網(wǎng)絡(luò)數(shù)據(jù)的抓取。

requests是一個很實用的Python HTTP客戶端庫,編寫爬蟲和測試服務(wù)器響應(yīng)數(shù)據(jù)時經(jīng)常會用到。


image.png

安裝

要安裝requests,最方便快捷的方法是使用pip進行安裝。在命令行執(zhí)行

pip install requests

請求

最簡單的靜態(tài)網(wǎng)頁數(shù)據(jù)獲取,需要先對網(wǎng)頁進行請求,比如我們以騰訊新聞為例:

import requests
result = requests.get('http://www.sohu.com/')
help(requests)

2.1 狀態(tài)碼

我們可以從返回result的狀態(tài)碼中,了解到是否請求成功。


image.png

2.2 文件編碼

我們的最終目的是獲取顯示在網(wǎng)頁上的內(nèi)容,文本字符串有不同的編碼格式,咱們可以先從返回結(jié)果里做一個簡單的了解。


image.png

2.3 返回的網(wǎng)頁內(nèi)容

從返回的結(jié)果result中,可以取出網(wǎng)頁的內(nèi)容


image.png
image.png
image.png
image.png

2.4 在URLs中傳遞參數(shù)

有時候我們需要在URL中傳遞參數(shù),比如在采集百度搜索結(jié)果時,我們wd參數(shù)(搜索詞)和rn參數(shù)(搜素結(jié)果數(shù)量),你可以手工組成URL,requests也提供了一種看起來很NB的方法:


image.png

2.5 設(shè)置超時時間

我們可以通過timeout屬性設(shè)置超時時間,一旦超過這個時間還沒獲得響應(yīng)內(nèi)容,就會提示錯誤。


image.png

2.6 添加代理

爬蟲爬取數(shù)據(jù)時為避免被封IP,經(jīng)常會使用代理。requests也有相應(yīng)的proxies屬性。


image.png

image.png

2.7 請求頭內(nèi)容

請求頭內(nèi)容可以用r.request.headers來獲取。


image.png

2.8 模擬登陸

有很多網(wǎng)站需要我們登錄之后才能完成數(shù)據(jù)的抓取,requests同樣支持提交表單(包含用戶名和密碼)進行登錄。代碼的示例如下:

3爬取豆瓣電影評論

3.1導(dǎo)入需要的庫

import sys
import requests
import time

3.2設(shè)置url和http頭

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 Core/1.47.933.400 QQBrowser/9.4.8699.400',
}
url = 'https://movie.douban.com/subject/20495023/comments'

3.3獲取數(shù)據(jù)

data = requests.get(url,headers)

3.4查看編碼

data.encoding
out : 'utf-8'
data.status_code
out : 200

3.5lxml與解析

大家可以利用BeautifulSoup做解析,我們換一種更高效的解析器,叫做lxml,會通過Xpath路徑表達式來定位節(jié)點位置。

from lxml import etree
selector = etree.HTML(data.text)

3.6抽取所有評論區(qū)域

comments = selector.xpath('//div[@class="comment"]')

3.7對評論區(qū)進行解析

1.初始化需要解析的值

# 初始化4個list用于存儲信息
users = []
users_url = []
stars = []
comment_texts = []

2.獲取評論區(qū)的不同屬性數(shù)據(jù)

for comment in comments:
    user = comment.xpath('.//h3/span[2]/a/text()')[0]
    user_url = comment.xpath('.//h3/span[2]/a/@href')[0]
    star = comment.xpath('.//h3/span[2]/span[2]/@class')[0][7:8]
    comment_text = comment.xpath('.//p/text()')[0].strip()
    
    users.append(user)
    users_url.append(user_url)
    stars.append(star)
    comment_texts.append(comment_text)

3.8組合成數(shù)據(jù)幀

comment_dic = {'user':users, 'user_url':users_url, 'star':stars, 'comments':comment_texts}
import pandas as pd
comment_df = pd.DataFrame(comment_dic)
comment_df

獲取的數(shù)據(jù)展示:


image.png

4、用requests抓取鏈家網(wǎng)信息

image.png

來動手做一個練習(xí),做到學(xué)以致用。
這次,我們來爬取鏈家網(wǎng)的一些內(nèi)容,用的工具依舊是大家熟悉的requests和BeautifulSoup

4.1準(zhǔn)備工作

編寫爬蟲前的準(zhǔn)備工作,我們需要導(dǎo)入用到的庫,這里主要使用的是requests和lxml兩個。還有一個Time庫,負(fù)責(zé)設(shè)置每次抓取的休息時間。

import requests
import time

4.2抓取列表頁

開始抓取前當(dāng)然應(yīng)該了解一下目標(biāo)網(wǎng)站URL結(jié)構(gòu)咯。
鏈家網(wǎng)的二手房列表頁面共有100個,URL結(jié)構(gòu)為http://bj.lianjia.com/ershoufang/pg9/ 其中

  • bj表示城市(北京)
  • /ershoufang/是頻道名稱(二手房)
  • pg9是頁面碼。

我們要抓取的是北京的二手房頻道,所以前面的部分不會變,屬于固定部分,后面的頁面碼需要在1-100間變化,屬于可變部分。將URL分為兩部分,前面的固定部分賦值給url,后面的可變部分使用for循環(huán)遍歷頁面。

url = 'https://bj.lianjia.com/ershoufang/'
page = 'pg'

這里提一個小小的醒,我們最好在http請求中設(shè)置一個頭部信息,否則很容易被封ip。頭部信息網(wǎng)上有很多現(xiàn)成的,也可以使用httpwatch等工具來查看。

#設(shè)置請求頭部信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept':'text/html;q=0.9,*/*;q=0.8',
'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding':'gzip',
'Connection':'close',
'Referer':'http://www.baidu.com/link?url=_andhfsjjjKRgEWkj7i9cFmYYGsisrnm2A-TN3XZDQXxvGsM9k9ZZSnikW2Yds4s&amp;amp;wd=&amp;amp;eqid=c3435a7d00146bd600000003582bfd1f'
}

我們使用for循環(huán)生成1-100的數(shù)字,轉(zhuǎn)換格式后與前面的URL固定部分拼成要抓取的URL。這里設(shè)置每個頁面間隔0.5秒。抓取到的頁面保存到html中。

for i in range(1,2):#暫時抓第一頁
    if i == 1:
        i = str(i)
        tmp_url = url+'/'#第一頁url為http://bj.lianjia.com/ershoufang/
        r = requests.get(url=tmp_url, headers=headers)
        html = r.text
    else:
        i = str(i)
        tmp_url = url+page+i+'/'
        r = requests.get(url=tmp_url, headers=headers)
        html2 = r.text
        html += html2
    time.sleep(2)
 

4.2頁面解析

頁面抓取的工作算是完成了,內(nèi)容在html中,下一步就要進行頁面解析了。我們依舊使用xml對頁面進行解析。

from lxml import etree
selector = etree.HTML(html)

完成頁面解析后就可以對頁面中的關(guān)鍵信息進行提取了。下面我們分別對房源的總價,房源信息關(guān)注度三部分進行提取。 把頁面div標(biāo)簽中class=priceInfo的部分提取出來,并使用for循環(huán)將其中每個房源的總價數(shù)據(jù)存在tp中。

houses = selector.xpath('//li[@class="clear"]') #讀取出當(dāng)前頁面的房子
len(houses)
out: 30
#初始化定義房子名稱,房子價格,房子相關(guān)信息,房子待看信息等的列表
houses_title = []
houses_price = []
houses_info = []
followers_info = []

來看看爬下來的房價數(shù)據(jù)


image.png

4.3做一個統(tǒng)一的解析

for house in houses:
    house_title = house.xpath('.//div[@class="title"]/a/text()')[0]
    house_price = house.xpath('.//div[@class="totalPrice"]/span/text()')[0]
    house_info = house.xpath('.//div[@class="houseInfo"]/a/text()')[0]+house.xpath('.//div[@class="houseInfo"]/text()')[0]
    follower_info = house.xpath('.//div[@class="followInfo"]/text()')[0]
    
    houses_title.append(house_title)
    houses_price.append(house_price)
    houses_info.append(house_info)
    followers_info.append(follower_info)
#定義存儲房子信息的字典
house_dic = {'house_title':houses_title, 'house_price':houses_price, 'house_info':houses_info, 'follower_info':followers_info}
import pandas as pd
house_df = pd.DataFrame(house_dic)
house_df

爬取鏈家網(wǎng)的信息展示:


image.png

5爬取圖片

導(dǎo)入庫函數(shù)

import requests

打開網(wǎng)頁,指定編碼

url = 'http://tieba.baidu.com/p/5346036052'
html = requests.get(url)
html.encoding = 'utf-8'

正則獲取圖像url

from lxml import etree
selector = etree.HTML(html.text);
image_url = selector.xpath('//img[@class="BDE_Image"]/@src')
image_url

圖像寫入文件

img = requests.get(image_url[0])
with open('baidu_tieba.jpg', 'ab') as f:
    f.write(img.content)
    f.close()

醬油哥個人博客:https://enfangzhong.github.io/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容