帖子網(wǎng)頁分析
- 帖子導航
<span class="pagernums" data-pager="list,meigu_|1706|80|1">
從這個標簽中可以獲得帖子總數(shù)1706烹俗,以及每一頁帖子的數(shù)量80,當前處于第幾頁:第一頁次和。
![美股吧帖子列表網(wǎng)頁分析](http://upload-images.jianshu.io/upload_images/5298387-ca563fc7a0c2552e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 構(gòu)造帖子列表的url
http://guba.eastmoney.com/list,meigu_2.html
帖子列表的url可以表示為:
'http://guba.eastmoney.com/list,meigu_{}.html'.format(page_num)
可以根據(jù)帖子總數(shù)/每頁帖子的數(shù)量得到一個帖子url的列表包各,代碼表示:
page_data = soup.find(name='span', class_='pagernums').get('data-pager').split('|')
page_nums = math.ceil(int(page_data[1]) / int(page_data[2]))
**注意:使用math模塊的ceil函數(shù)向上取整**
- 循環(huán)獲取每一頁帖子的信息
## 評論網(wǎng)頁分析
- 評論頁導航
> 查看網(wǎng)頁的html信息七咧,查詢105,有三個地方可以獲取到這個信息叮叹,這里用了正則表達式從script中獲取艾栋。
{var num=40030; }var pinglun_num=105;var xgti="";if(typeof (count) != "undefined"){xgti="<span class="tc2"><a href='list,meigu.html'>相關(guān)帖子<span class="tc1">"+count+"</span>條</a></span>";}
![評論頁導航信息](http://upload-images.jianshu.io/upload_images/5298387-8e7eae194d70eb22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 構(gòu)造評論頁url
http://guba.eastmoney.com/news,meigu,613304918_2.html
帖子評論url可以表示為:
'http://guba.eastmoney.com/news,meigu,613304918_{}.html'.format(page_num)
可以根據(jù)評論總數(shù)reply_count / 30(有分頁情況下,每頁帖子的數(shù)量最多為30)得到一個帖子url的列表蛉顽,代碼表示:
pattern = re.compile(r'var pinglun_num=(.*?);')
文章評論數(shù)
reply_count = int(re.search(pattern, resp.text).group(1))
page_num = math.ceil(reply_count / 30)
**注意:使用math模塊的ceil函數(shù)向上取整**
- 循環(huán)獲取每一頁評論的信息
先判斷有沒有評論蝗砾,如果有的話遍歷評論url,返回帖子的評論信息
## 使用的庫
- requests:發(fā)起網(wǎng)頁請求
- BeautifulSoup:解析網(wǎng)頁
- re:正則表達式解析網(wǎng)頁
- math:使用ceil函數(shù)向上取整
- csv:數(shù)據(jù)保存為csv文件
## 爬取過程
1. 以http://guba.eastmoney.com/list,meigu.html為入口携冤;
2. 先獲取帖子的總數(shù)悼粮、計算出帖子導航頁的頁碼數(shù);
3. 得到帖子的導航url列表曾棕;
4. 遍歷帖子的導航url扣猫,得到帖子的信息;
- 遍歷帖子url的地址翘地,得到帖子的閱讀量申尤、評論數(shù)、標題
- 獲取評論信息
- 以帖子url衙耕,如http://guba.eastmoney.com/news,meigu,646708357.html 為入口
- 先獲取評論的總數(shù)昧穿,計算出帖子評論的頁數(shù)
- 得到評論導航的url列表
- 遍歷評論url列表,得到帖子的評論信息
## 代碼
import requests
from bs4 import BeautifulSoup
import math
import re
import csv
start_url = 'http://guba.eastmoney.com/list,meigu_1.html'
url = "http://guba.eastmoney.com/news,meigu,646708357.html"
base_url = "http://guba.eastmoney.com"
獲取所有帖子的信息
def get_articles_info(start_url):
resp = get_html(start_url)
soup = BeautifulSoup(resp.text, 'html.parser')
page_data = soup.find(name='span', class_='pagernums').get('data-pager').split('|')
page_nums = math.ceil(int(page_data[1]) / int(page_data[2]))
print('共{}頁'.format(page_nums))
articles_infos = []
with open('meigu.csv', 'a') as csv_file:
writer = csv.writer(csv_file)
writer.writerow(['閱讀量', '評論數(shù)', '發(fā)布時間', '帖子網(wǎng)址', '帖子標題', '帖子評論'])
for i in range(1, page_nums+1):
print('爬取第{}頁...'.format(i))
articles_url = start_url.split('')[0] + '' + str(i) + '.html'
articles_infos = parser_articles_info(articles_url)
articles_infos.extend(articles_infos)
return articles_infos
獲取一頁的所有帖子信息:閱讀量臭杰、評論數(shù)粤咪、發(fā)布時間、帖子的url渴杆、帖子的標題寥枝、帖子的所有評論
param:每一頁帖子的鏈接
def parser_articles_info(article_list_url):
resp = get_html(article_list_url)
articles_soup = BeautifulSoup(resp.text, 'html.parser')
articles_infos = articles_soup.find_all(name='div', class_='articleh')
articles = []
for info in articles_infos:
if '/news' in info.find(name='span', class_='l3').find(name='a').get('href'):
article_infos = {
'read_count': info.find(name='span', class_='l1').text,
'reply_count': info.find(name='span', class_='l2').text,
'release_time': info.find(name='span', class_='l5').text,
'article_url': base_url + info.find(name='span', class_='l3').find(name='a').get('href'),
'article_title': info.find(name='span', class_='l3').find(name='a').get('title'),
'article_comments': parse_comment_page(get_html(base_url + info.find(name='span', class_='l3').find(name='a').get('href')))
}
with open('meigu.csv', 'a') as csv_file:
writer = csv.writer(csv_file)
writer.writerow(article_infos.values())
articles.append(article_infos)
# print(articles)
return articles
根據(jù)url獲取html文檔
def get_html(url):
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
}
resp = requests.get(url)
if resp.status_code == 200:
return resp
return None
解析帖子的html文檔,提取需要的數(shù)據(jù):帖子的內(nèi)容以及帖子的所有評論
def parse_comment_page(resp):
soup = BeautifulSoup(resp.text, 'html.parser')
# 正則表達式獲取總的評論數(shù)
pattern = re.compile(r'var pinglun_num=(.*?);')
article_info = {}
# 文章評論數(shù)
article_info['reply_count'] = int(re.search(pattern, resp.text).group(1))
# 文章內(nèi)容
article_info['article_content'] = soup.find(name='div', class_='stockcodec').text.strip()
# print(article_info['article_content'])
page_num = math.ceil(article_info['reply_count'] / 30)
print('{}條評論'.format(article_info['reply_count'] ), ',', '共{}頁'.format(page_num))
# 爬取所有的評論
article_comments = []
if article_info['reply_count'] > 0:
for i in range(1, page_num+1):
comment_url = '.'.join(resp.url.split('.')[:-1]) + '_{}'.format(i) + '.html'
print(comment_url)
article_comments.extend(parser_article_comment(comment_url))
else:
article_comments.append('本帖子暫時沒有評論內(nèi)容')
return article_comments
獲得帖子一頁的評論信息
def parser_article_comment(comment_list_url):
resp = get_html(comment_list_url)
if resp:
comment_soup = BeautifulSoup(resp.text, 'html.parser')
comments_infos = comment_soup.find_all(name='div', class_='zwlitxt')
comments = []
# print(len(comments_infos))
for info in comments_infos:
comment = {}
comment['commentator'] = info.find(name='span', class_='zwnick').find('a').text if info.find(name='span', class_='zwnick').find('a') else None
comment['reply_time'] = info.find(name='div', class_='zwlitime').text
comment['reply_content'] = info.find(name='div', class_='zwlitext').text
comments.append(comment)
return comments
def main():
get_articles_info(start_url)
if name == 'main':
main()
## 運行結(jié)果
![爬取的結(jié)果](http://upload-images.jianshu.io/upload_images/5298387-f98fdbc345c75d57.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
> 爬蟲能正常運行,但是爬取的過程很慢