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

在成功登錄以後,咱們能夠進行下一波操做了~html

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

 

環境正則表達式

toolschrome

一、chrome及其developer toolsjson

二、python3.6app

三、pycharmdom

 

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

 

關鍵詞搜索ui

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

 

搜索後,咱們發現網址爲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

 

最後完整版代碼就不貼上來啦~~若是有疑問能夠在下面回覆多多交流~

撒花完結~~

相關文章
相關標籤/搜索