前言
由于虎扑页面的限制,因为访问虎扑步行街的第11个页面就需要用户进行登录,鉴于此时技术还没有学全,只能爬取1到10的页面。
抓取什么数据
- 帖子名称
- 帖子链接
- 发帖人
- 发帖人链接
- 发帖时间
- 帖子回复数
- 帖子浏览数
- 最后回复帖子的人
- 最后回复的时间
如何抓取数据
-
首先我们发现这个页面是用gzip进行压缩的,gzip是用utf-8进行编码的,也就是我们抓取的页面是用utf-8编码的,而r.text返回的是unicode编码的字符串,如果我们直接用就会出现乱码,因此,我们用r.content,返回的bytes数据(抓取音频,文件),然后将这个页面从utf-8解码为unicode编码
html = r.content html = html.decode('utf-8') #将utf-8解码为unicode
- 抓取数据对应的字段的html标签(代码中看)
用Mongodb存放抓取到的数据
- 需要注意的问题,就是可能会出现本来在第一页的帖子,然后凉了啥的,被顶到了第二页,那么这时候就不能存放在数据库中,所以每次插入数据要进行判断一下
代码
import requests
from bs4 import BeautifulSoup
import time
from pymongo import MongoClient
def get_page(link):
data_list = []
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"
}
r = requests.get(link, headers=headers)
html = r.content
html = html.decode('utf-8') #将utf-8解码为unicode
soup = BeautifulSoup(html, 'lxml')
for_list = soup.find('ul', class_="for-list")
for_list = for_list.find_all('li')
for each_for in for_list:
# 帖子名称
for_name = each_for.find('div', class_="titlelink box").a.text.strip()
# 帖子链接
for_link = each_for.find('div', class_="titlelink box").a['href']
for_link = 'https://bbs.hupu.com' + for_link
# 作者
for_writer = each_for.find('div', class_="author box").a.text.strip()
# 作者链接
for_writer_link = each_for.find('div', class_= "author box").a['href']
# 帖子创建时间
for_createtime = each_for.find('div', class_= "author box")
# 获取节点的所有子节点,然后发现时间在列表中第6项
for_createtime = for_createtime.contents
for_createtime = for_createtime[5].text.strip()
# 回复数
for_reply_numbers = each_for.find('span', class_= "ansour box").text.split('/')[0].strip()
# 浏览数
for_see_numbers = each_for.find('span', class_= "ansour box").text.split('/')[1].strip()
# 最后回复用户
for_last_reply_user = each_for.find('div', class_="endreply box").span.text.strip()
#最后回复时间
for_last_reply_time = each_for.find('div', class_="endreply box").a.text.strip()
data_list.append([for_name, for_link, for_writer, for_writer_link, for_createtime, for_reply_numbers,for_see_numbers, for_last_reply_user,for_last_reply_time])
return data_list
class sort_by_Mongodb:
def __init__(self, db_host, db_port, db_name, coll_name):
self.db_host = db_host
self.db_port = db_port
self.db_name = db_name
self.coll_name = coll_name
self.client = MongoClient(host=self.db_host, port=self.db_port)
self.db = self.client[self.db_name]
self.coll = self.db[self.coll_name]
def update(self, query, insert_data):
# query表示查询条件, insert_data表示更新的数据,其实在本例中就是要插入的数据
self.coll.update_one(query, {'$set':insert_data}, upsert=True)
# upsert (optional): If True, perform an insert if no documents match the filter.
def main():
link = "https://bbs.hupu.com/bxj-"
# 超过第10个页面就需要登录了。。。。
for i in range(1,11):
link_temp = link + str(i)
data_list = get_page(link_temp) #返回的是列表的列表
a = sort_by_Mongodb("localhost", 27017, "hupu", "buxingjie")
for each in data_list:
insert_dict = {
"帖子名称": each[0],
"帖子链接": each[1],
"发帖人": each[2],
"发帖人链接": each[3],
"发帖时间": each[4],
"贴子回复数": each[5],
"帖子浏览数": each[6],
"最后回复帖子的人": each[7],
"最后回复时间": each[8]
}
# 帖子链接肯定是不一样的,因此把这个作为筛选条件
a.update({"帖子链接": each[1]}, insert_dict)
print("第"+ str(i)+ "页面存取完成!!!!!!!!!!!")
time.sleep(2)
if __name__ == "__main__":
main()
结果截图
一共抓取到1151条贴子,对于10个页面来说,好像差不多吧~