新浪微博搜索頁用戶信息爬取


在成功登陸之后,我們可以進行下一波操作了~

接下來,我們的目的是通過輸入關鍵字,找到相關用戶,並收集用戶的一些基本信息

 

環境

tools

1、chrome及其developer tools

2、python3.6

3、pycharm

 

Python3.6中使用的庫

 1 import urllib.error
 2 import urllib.request
 3 import urllib.parse
 4 import urllib
 5 import re
 6 import json
 7 import pandas as pd
 8 import time
 9 import logging
10 import random
11 from lxml import etree

 

關鍵詞搜索

我們首先在微博首頁輸入關鍵詞,進入搜索頁面

 

搜索后,我們發現網址為http://s.weibo.com/user/%25E4%25B8%258A%25E8%25AE%25BF&Refer=weibo_user

很顯然,前面的“http://s.weibo.com/user/”網頁基礎地址,“%25E4%25B8%258A%25E8%25AE%25BF”看起來很像關鍵詞的一種編碼形式,最后的一段內容我們先放一邊,點擊進入下一頁繼續觀察規律

進入第二頁后,我們發現網址變為http://s.weibo.com/user/%25E4%25B8%258A%25E8%25AE%25BF&page=2

這時,我們需要猜想,如果將“page=”之后的數字改為1,是否會跳轉回首頁:

成功了,這樣我們就可以將url分為三部分。

 

現在,我們需要對中間編碼部分進行解析,發現它經過兩次url編碼。

因此,最后搜索頁的url連接如下:

1 import urllib.request
2 
3 keyword = '上訪'
4 once = urllib.request.quote(keyword)
5 pagecode = urllib.request.quote(once)
6 
7 i = 1   # 頁數
8 url = 'http://s.weibo.com/user/' + pagecode + '&page=' + str(i)

 

用戶基本信息提取

接下來,我要對用戶的一些基本信息進行爬取。

經過觀察,初步確定了搜索頁面所能爬取到的用戶信息字段:

  • 微博ID——_id
  • 微博名——name
  • 地區——location
  • 性別——gender
  • 微博地址——weibo_addr
  • 關注——follow
  • 粉絲——fans
  • 微博數——weibo_num
  • 簡介——intro
  • 職業——職業信息
  • 教育——教育信息
  • 標簽——標簽

  (其中,紅色字段是必有的。)

 我們將先對【必有字段】進行爬取,再研究如何爬取【非必有字段】。

 

首先我們先觀察網頁源碼,定位到用戶主體部分【可以用Chrome自帶的developer tools中的element進行定位】

於是我們發現,開頭為“<script>STK && STK.pageletM && STK.pageletM.view({"pid":"pl_user_feedList"”,我們可以通過正則表達式,尋找出該內容

此外,仔細觀察還能發現()里面的內容為json格式。

萬歲~~

這樣對我們提取所需的html內容十分的有幫助~~

 1 data = urllib.request.urlopen(url,timeout=30).read().decode('utf-8') 
 2 
 3 lines = data.splitlines()
 4 for line in lines:
 5     if not line.startswith('<script>STK && STK.pageletM && STK.pageletM.view({"pid":"pl_user_feedList","js":'):
 6         continue
 7 
 8     json_pattern = re.compile('\((.*)\)')
 9     # 利用正則取出json
10     json_data = json_pattern.search(line).group(1)
11     # 將json包裝成字典並提取出html內容
12     html = json.loads(json_data)['html']

 

然后開始正式的網頁內容解析,先對【必有字段】進行解析。

這里,我們依舊需要借助Chrome上的developer tools

通過elements,我們定位到微博名對應的html內容,我們可以利用lxml中的etree和xpath獲取title名。

同理,我們也可以得到其他必有字段,最后我們講所有內容存儲成一個dict,每個key對應的value則為一個list:

1 page = etree.HTML(html)
2 info_user['name'] = page.xpath('//a[@class="W_texta W_fb"]/@title')
3 info_user['_id'] = page.xpath('//a[@class="W_btn_b6 W_fr"]/@uid')
4 info_user['weibo_addr'] = page.xpath('//a[@class="W_texta W_fb"]/@href')
5 info_user['gender'] = page.xpath('//p[@class="person_addr"]/span[1]/@title')
6 info_user['location'] = page.xpath('//p[@class="person_addr"]/span[2]/text()')
7 info_user['follow'] = page.xpath('//p[@class="person_num"]/span[1]/a/text()')
8 info_user['fans'] = page.xpath('//p[@class="person_num"]/span[2]/a/text()')
9 info_user['weibo_num'] = page.xpath('//p[@class="person_num"]/span[3]/a/text()')

 

最后是對【非必有字段】的爬取

該類字段爬取的思代碼邏輯是這樣的

利用lxml包中的etree抓取子樹(class="person_detail")

再對子樹下的枝干進行遍歷,判斷是否存在簡介(class="person_info")和標簽(class="person_label"),分別進行不同的處理

值得注意的是,部分標簽下的內容不止一個,因此我們必須對標簽內容進行一次判斷和遍歷。

由於簡介和標簽分別處於兩個枝干,因此可以編輯兩個不同的函數進行提取:

 1 # 提取簡介信息
 2 def info(self, p, path):
 3     '''
 4     extract introduction of users
 5     :param p: input an etree
 6     :param path: input xpath which must be a string
 7     :return: a string
 8     '''
 9     if type(path) == str:
10         info = p.xpath(path)
11         if len(info) == 0:
12             sub_info = ''
13         else:
14             sub_info = info[0]
15 
16         return sub_info
17     else:
18         print('please enter the path as a string')
19 
20 # 提取標簽信息:標簽、教育信息、工作信息
21 def labels(self, p, path, key):
22     '''
23     extract labels, such as hobbits, education, job, of users
24     :param p: input an etree
25     :param path: input xpath which must be a string
26     :param key: keywords of labels
27     :return: a string
28     '''
29     label = p.xpath(path)
30     if len(label) == 0:
31         sub_label = ''
32     else:
33         for l in label:
34             label_name = re.compile('(.*?):').findall(l.xpath('./text()')[0])
35             if label_name[0] == key:
36                 # 讀取出標簽信息下的所有標簽內容
37                 all_label = l.xpath('./a/text()')
38                 l = ''
39                 for i in all_label:
40                     l = re.compile('\n\t(.*?)\n\t').findall(i)[0] + ',' + l
41                     sub_label = l
42             else:
43                 sub_label = ''
44 
45     return sub_label

 

構造完函數后,可以提取所有用戶的信息啦~

需要注意的是,返回的內容是單個子樹下的一個string,遍歷當前頁的所有用戶的信息,則需要做成list:

 1 info_user['intro'] = []
 2 info_user['標簽'] = []
 3 info_user['職業信息'] = []
 4 info_user['教育信息'] = []
 5 others = page.xpath('//div[@class="person_detail"]')
 6 for p in others:
 7     path1 = './div/p/text()'
 8     info_user['intro'].append(self.info(p, path1))
 9     path2 = './p[@class="person_label"]'
10     info_user['標簽'].append(self.labels(p, path2, '標簽'))
11     info_user['職業信息'].append(self.labels(p, path2, '職業信息'))
12     info_user['教育信息'].append(self.labels(p, path2, '教育信息'))

 

遍歷所有頁面

在成功實踐了用戶基本信息的爬取之后,需要遍歷所有的網頁

這里,我們可以用很傻瓜的方法,自己觀察一共有幾頁,然后編一個for循環

然鵝!!!博主我絕對不會干這種蠢事的!!!必須要有一個更加裝x的方式來遍歷才行!

 

於是,繼續依賴developer tools,找到點擊下一頁對應的元素,我們發現了一個神奇的東西——class="page next S_txt1_S_line1"

這不就是絕佳的定位是否存在下一頁的神器么!!!

於是,最佳代碼邏輯誕生啦~~

通過判斷能否提取出該內容來決定是否進入還需進入下一頁i += 1

 1 i = 1
 2 Flag = True
 3 while Flag:
 4     # 構建url
 5     url = 'http://s.weibo.com/user/' + pagecode + '&page=' + str(i)
 6     try:
 7         # 超時設置
 8         data = urllib.request.urlopen(url,timeout=30).read().decode('utf-8')
 9     except Exception as e:
10         print('出現異常 -->'+str(e))
11 
12     …………
13 
14     next_page = page.xpath('//a[@class="page next S_txt1 S_line1"]/@href')[0]
15     if len(next_page) == 0 :
16         Flag = False
17     else:
18         page_num = re.compile('page=(\d*)').findall(next_page)[0]
19         i = int(page_num)

 

撒花~~~代碼的整體邏輯就這么完善啦~~~

最后,我們需要解決的就是反爬的問題了,博主在這方面還沒有深入研究過

不過主要思路還是有的:

  1. 每次遍歷設置一個time.sleep()
  2. 設置好詳細的頭文件
  3. 尋找代理IP

 

最后完整版代碼就不貼上來啦~~如果有疑問可以在下面回復多多交流~

撒花完結~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM