老师让参加2017年SMP的用户画像评测,将本次评测的相关内容写博客记录一下:
关于评测请看官网:2017SMP用户画像评测
6月1号发布相关数据,这段时间老师让总结一个技术路线,所以先爬点csdn的博文数据做些规划。
下面详细介绍如何爬取部分博文。
爬虫的基础知识这里不做介绍。初步的将代码分为三部分,最后在进行归纳总结。
首先需求只是获取csdn的博文,决定爬取全部的专家博客作为数据集,先处理任务一和任务二。
首先分析专家首页:
从首页直接可以爬取部分的专家的主页链接,格式如下:“黄帅”写正则匹配就可以(需要注意的是要用非贪婪模式,详细的见后面贴出的代码)。
第一步先解决获取一个用户的全部文章,然后存入mysql数据库。然后获取全部专家的id。
面临的问题:
这里遇到了第一个坎,由于直接爬取会出现403错误,所以需要简单改下代码,使其伪装成浏览器,
header = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36"
加入header,需要注意的是这里的伪装浏览器可以伪装为手机端或者pc端。我的问题是一直使用pc端看html代码,在程序里使用的伪装浏览器为手机端的,导致没有找到页数,伪装成pc端之后成功解决获取某人全部文章id的需求。代码如下:
from urllib import request
import re
import time
import random
from bs4 import BeautifulSoup
# import MySQLdb
#定义保存文件函数
def save_file(data, i, article_name):
'''将博文信息写入文件'''
path = "测试/" + article_name + "_"+str(i)+".txt"
file_1 = open(path, 'wb')
file_1.write(data)
file_1.close()
#爬虫类
class CSDNSpider:
def __init__(self,url="http://blog.csdn.net/"):
#默认当前页
self.url = url
header = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36"
self.header = header
#求博客总页数
def getPages(self,article_name):
url = self.url + article_name + "/article/list/1"
req = request.Request(url)
req.add_header('User-Agent', self.header)
res = request.urlopen(req)
data1 = res.read()
data = data1.decode('utf-8')
# saveFile(data1,1)
pages = r'<div.*?pagelist">.*?<span>.*?共(.*?)页</span>'
# 计算我的博文总页数
pattern = re.compile(pages, re.DOTALL)
pagesNum = re.findall(pattern, data)[0]
return pagesNum
def getEachArticle(self,article_name,pagesNum):
#获取博主每篇文章的链接以便进一步处理
list_id = list()
for i in range(pagesNum):
url = self.url + article_name + "/article/list/" + str(i)
url_each = url
req = request.Request(url_each)
req.add_header('User-Agent',self.header)
res = request.urlopen(req)
data_temp = res.read()#存放爬取的页数的html,包含每篇文章的id
data_temp = data_temp.decode("utf-8")
# soup = BeautifulSoup(data_temp, "html.parser")
# list_id = soup.find_all("a")#查找h1标签页内容
partten_1 = re.compile(r"<a href=.*?article/details/(.*?)#")
list_id_1 = partten_1.findall(data_temp)
[list_id.append(i) for i in list_id_1]
# print (list_id)
return list_id
def getText(self,list_id,article_name):
k = 1
list_id_all = list()
for i in list_id:
list_id_all.append(i)
for i in list_id_all:
url = self.url + article_name + "/article/details/" + i
print(url)
req = request.Request(url)
req.add_header('User-Agent',self.header)
res = request.urlopen(req, timeout=5)
data_text = res.read()#存放爬取的页数的html,包含每篇文章的id
save_file(data_text, k, article_name)
k = k + 1
print ("writting success!!")
def main():
#定义爬虫对象
cs = CSDNSpider()
article_name = "mynameishuangshuai"
pagesNum = int(cs.getPages(article_name))
list_id = cs.getEachArticle(article_name,pagesNum)
cs.getText(list_id,article_name)
print ("程序结束!")
if __name__ == '__main__':
main()
这样便实现了将一个用户的全部文章写入txt文档。然后用BeautSoup配合正则来提取文章和标签。