Python數(shù)據(jù)可視化:Python大佬有哪些?
有態(tài)度地學(xué)習(xí)
之前講了代理池以及Cookies的相關(guān)知識(shí),這里針對搜狗搜索微信公眾號(hào)文章的爬取,將它倆實(shí)踐一下。
在崔大的書里面,他是用代理IP來應(yīng)對搜狗的反爬措施,因?yàn)橥籌P訪問網(wǎng)頁過于頻繁,就會(huì)跳轉(zhuǎn)驗(yàn)證碼頁面。
不過時(shí)代在進(jìn)步,搜狗搜索的反爬也在更新,現(xiàn)在它是IP加Cookies雙重把關(guān)。
01 網(wǎng)頁分析
獲取微信公眾號(hào)文章信息,標(biāo)題、開頭、公眾號(hào)、發(fā)布時(shí)間。
請求方式為GET,請求網(wǎng)址為紅框部分,后面的信息沒什么用。
02 反爬破解
什么時(shí)候出現(xiàn)上圖這種情況呢?
兩種,一種同一個(gè)IP重復(fù)訪問頁面,另一種同一個(gè)Cookies重復(fù)訪問頁面。
兩個(gè)都有,掛的更快!完整爬取我只成功了一次...
因?yàn)槲易铋_始就是先什么都不設(shè)置,然后就出現(xiàn)驗(yàn)證碼頁面。然后用了代理IP,還是會(huì)跳轉(zhuǎn)驗(yàn)證碼頁面,直到***改變Cookies,才成功爬取。
01 代理IP設(shè)置
- def get_proxies(i):
- """
- 獲取代理IP
- """
- df = pd.read_csv('sg_effective_ip.csv', header=None, names=["proxy_type", "proxy_url"])
- proxy_type = ["{}".format(i) for i in np.array(df['proxy_type'])]
- proxy_url = ["{}".format(i) for i in np.array(df['proxy_url'])]
- proxies = {proxy_type[i]: proxy_url[i]}
- return proxies
代理的獲取以及使用這里就不贅述了,前面的文章有提到,有興趣的小伙伴可以自行去看看。
經(jīng)過我兩天的實(shí)踐,免費(fèi)IP確實(shí)沒什么用,兩下子就把我真實(shí)IP揪出來了。
02 Cookies設(shè)置
- def get_cookies_snuid():
- """
- 獲取SNUID值
- """
- time.sleep(float(random.randint(2, 5)))
- url = "http://weixin.sogou.com/weixin?type=2&s_from=input&query=python&ie=utf8&_sug_=n&_sug_type_="
- headers = {"Cookie": "ABTEST=你的參數(shù);IPLOC=CN3301;SUID=你的參數(shù);SUIR=你的參數(shù)"}
- # HEAD請求,請求資源的首部
- response = requests.head(url, headers=headers).headers
- result = re.findall('SNUID=(.*?); expires', response['Set-Cookie'])
- SNUID = result[0]
- return SNUID
總的來說,Cookies的設(shè)置是整個(gè)反爬中最重要的,而其中的關(guān)鍵便是動(dòng)態(tài)改變SNUID值。
這里就不詳細(xì)說其中緣由,畢竟我也是在網(wǎng)上看大神的帖子才領(lǐng)悟到的,而且領(lǐng)悟的還很淺。
成功爬取100頁就只有一次,75頁,50頁,甚至到***一爬就掛的情況都出現(xiàn)了...
我可不想身陷「爬-反爬-反反爬」的泥潭之中,爬蟲之后的事情才是我的真正目的,比如數(shù)據(jù)分析,數(shù)據(jù)可視化。
所以干票大的趕緊溜,只能膜拜搜狗工程師。
03 數(shù)據(jù)獲取
1 構(gòu)造請求頭
- head = """
- Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
- Accept-Encoding:gzip, deflate
- Accept-Language:zh-CN,zh;q=0.9
- Connection:keep-alive
- Host:weixin.sogou.com
- Referer:'http://weixin.sogou.com/',
- Upgrade-Insecure-Requests:1
- User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
- """
- # 不包含SNUID值
- cookie = '你的Cookies'
- def str_to_dict(header):
- """
- 構(gòu)造請求頭,可以在不同函數(shù)里構(gòu)造不同的請求頭
- """
- header_dict = {}
- header = header.split('\n')
- for h in header:
- h = h.strip()
- if h:
- k, v = h.split(':', 1)
- header_dict[k] = v.strip()
- return header_dict
2 獲取網(wǎng)頁信息
- def get_message():
- """
- 獲取網(wǎng)頁相關(guān)信息
- """
- failed_list = []
- for i in range(1, 101):
- print('第' + str(i) + '頁')
- print(float(random.randint(15, 20)))
- # 設(shè)置延時(shí),這里是度娘查到的,說要設(shè)置15s延遲以上,不會(huì)被封
- time.sleep(float(random.randint(15, 20)))
- # 每10頁換一次SNUID值
- if (i-1) % 10 == 0:
- value = get_cookies_snuid()
- snuid = 'SNUID=' + value + ';'
- # 設(shè)置Cookies
- cookies = cookie + snuid
- url = 'http://weixin.sogou.com/weixin?query=python&type=2&page=' + str(i) + '&ie=utf8'
- host = cookies + '\n'
- header = head + host
- headers = str_to_dict(header)
- # 設(shè)置代理IP
- proxies = get_proxies(i)
- try:
- response = requests.get(url=url, headers=headers, proxies=proxies)
- html = response.text
- soup = BeautifulSoup(html, 'html.parser')
- data = soup.find_all('ul', {'class': 'news-list'})
- lis = data[0].find_all('li')
- for j in (range(len(lis))):
- h3 = lis[j].find_all('h3')
- #print(h3[0].get_text().replace('\n', ''))
- title = h3[0].get_text().replace('\n', '').replace(',', ',')
- p = lis[j].find_all('p')
- #print(p[0].get_text())
- article = p[0].get_text().replace(',', ',')
- a = lis[j].find_all('a', {'class': 'account'})
- #print(a[0].get_text())
- name = a[0].get_text()
- span = lis[j].find_all('span', {'class': 's2'})
- cmp = re.findall("\d{10}", span[0].get_text())
- #print(time.strftime("%Y-%m-%d", time.localtime(int(cmp[0]))) + '\n')
- date = time.strftime("%Y-%m-%d", time.localtime(int(cmp[0])))
- with open('sg_articles.csv', 'a+', encoding='utf-8-sig') as f:
- f.write(title + ',' + article + ',' + name + ',' + date + '\n')
- print('第' + str(i) + '頁成功')
- except Exception as e:
- print('第' + str(i) + '頁失敗')
- failed_list.append(i)
- continue
- # 獲取失敗頁碼
- print(failed_list)
- def main():
- get_message()
- if __name__ == '__main__':
- main()
***成功獲取數(shù)據(jù)。
04 數(shù)據(jù)可視化
1 微信文章發(fā)布數(shù)量***0
這里對搜索過來的微信文章進(jìn)行排序,發(fā)現(xiàn)了這十位Python大佬。
這里其實(shí)特想知道他們是團(tuán)隊(duì)運(yùn)營,還是個(gè)人運(yùn)營。不過不管了,先關(guān)注去。
這個(gè)結(jié)果可能也與我用Python這個(gè)關(guān)鍵詞去搜索有關(guān),一看公眾號(hào)名字都是帶有Python的(CSDN例外)。
- from pyecharts import Bar
- import pandas as pd
- df = pd.read_csv('sg_articles.csv', header=None, names=["title", "article", "name", "date"])
- list1 = []
- for j in df['date']:
- # 獲取文章發(fā)布年份
- time = j.split('-')[0]
- list1.append(time)
- df['year'] = list1
- # 選取發(fā)布時(shí)間為2018年的文章,并對其統(tǒng)計(jì)
- df = df.loc[df['year'] == '2018']
- place_message = df.groupby(['name'])
- place_com = place_message['name'].agg(['count'])
- place_com.reset_index(inplace=True)
- place_com_last = place_com.sort_index()
- dom = place_com_last.sort_values('count', ascending=False)[0:10]
- attr = dom['name']
- v1 = dom['count']
- bar = Bar("微信文章發(fā)布數(shù)量***0", title_pos='center', title_top='18', width=800, height=400)
- bar.add("", attr, v1, is_convert=True, xaxis_min=10, yaxis_rotate=30, yaxis_label_textsize=10, is_yaxis_boundarygap=True, yaxis_interval=0, is_label_show=True, is_legend_show=False, label_pos='right', is_yaxis_inverse=True, is_splitline_show=False)
- bar.render("微信文章發(fā)布數(shù)量***0.html")
2 微信文章發(fā)布時(shí)間分布
因?yàn)檫@里發(fā)現(xiàn)搜索到的文章會(huì)有2018年以前的,這里予以刪除,并且驗(yàn)證剩下文章的發(fā)布時(shí)間。
畢竟信息講究時(shí)效性,如果我搜索獲取的都是老掉牙的信息,就沒什么意思了,更何況還是在一直在變化的互聯(lián)網(wǎng)行業(yè)。
- import numpy as np
- import pandas as pd
- from pyecharts import Bar
- df = pd.read_csv('sg_articles.csv', header=None, names=["title", "article", "name", "date"])
- list1 = []
- list2 = []
- for j in df['date']:
- # 獲取文章發(fā)布年份及月份
- time_1 = j.split('-')[0]
- time_2 = j.split('-')[1]
- list1.append(time_1)
- list2.append(time_2)
- df['year'] = list1
- df['month'] = list2
- # 選取發(fā)布時(shí)間為2018年的文章,并對其進(jìn)行月份統(tǒng)計(jì)
- df = df.loc[df['year'] == '2018']
- month_message = df.groupby(['month'])
- month_com = month_message['month'].agg(['count'])
- month_com.reset_index(inplace=True)
- month_com_last = month_com.sort_index()
- attr = ["{}".format(str(i) + '月') for i in range(1, 12)]
- v1 = np.array(month_com_last['count'])
- v1 = ["{}".format(int(i)) for i in v1]
- bar = Bar("微信文章發(fā)布時(shí)間分布", title_pos='center', title_top='18', width=800, height=400)
- bar.add("", attr, v1, is_stack=True, is_label_show=True)
- bar.render("微信文章發(fā)布時(shí)間分布.html")
3 標(biāo)題、文章開頭詞云
- from wordcloud import WordCloud, ImageColorGenerator
- import matplotlib.pyplot as plt
- import pandas as pd
- import jieba
- df = pd.read_csv('sg_articles.csv', header=None, names=["title", "article", "name", "date"])
- text = ''
- # for line in df['article'].astype(str):(前文詞云代碼)
- for line in df['title']:
- text += ' '.join(jieba.cut(line, cut_all=False))
- backgroud_Image = plt.imread('python_logo.jpg')
- wc = WordCloud(
- background_color='white',
- mask=backgroud_Image,
- font_path='C:\Windows\Fonts\STZHONGS.TTF',
- max_words=2000,
- max_font_size=150,
- random_state=30
- )
- wc.generate_from_text(text)
- img_colors = ImageColorGenerator(backgroud_Image)
- wc.recolor(color_func=img_colors)
- plt.imshow(wc)
- plt.axis('off')
- # wc.to_file("文章.jpg")(前文詞云代碼)
- wc.to_file("標(biāo)題.jpg")
- print('生成詞云成功!')
公眾號(hào)文章標(biāo)題詞云,因?yàn)槭且訮ython這個(gè)關(guān)鍵詞去搜索的,那么必然少不了Python。
然后詞云里出現(xiàn)的的爬蟲,數(shù)據(jù)分析,機(jī)器學(xué)習(xí),人工智能。就便知道Python目前的主要用途啦!
不過Python還可用于Web開發(fā),GUI開發(fā)等,這里沒有體現(xiàn),顯然不是主流。
公眾號(hào)文章開頭詞云,記得以前寫作文的時(shí)候,老師不就說過開頭基本決定了你的分?jǐn)?shù),所以一定要開頭引用一下名人的話(古人有云...)。
那么公眾號(hào)文章應(yīng)該也不例外,不過這里呢,我倒是感覺到了不少廣告的氣息...
當(dāng)然數(shù)據(jù)分析,機(jī)器學(xué)習(xí),人工智能同樣也還在其中,是不是培訓(xùn)廣告的噱頭我就不知道了。
就像之前在一個(gè)公號(hào)里看到的一句話,仿佛學(xué)會(huì)了Python就會(huì)人工智能,又仿佛要學(xué)習(xí)人工智能就必須學(xué)習(xí)Python,那么真是這樣嗎???
相信答案就在大家心中!