csdn论坛页抓取
抓取csdn论坛
实现功能
获取论坛分类所有链接,并拼接成推荐精华页的完成的链接
获取推荐精华页的帖子状态,赏分,帖子标题,作者,发布时间,回复量,查看量,最后发表时间
置顶内容不爬取,只打印置顶内容的帖子标题,作者信息和帖子链接
跳过没有内容的版块,并打印出来
把获取到的内容添加到数据库
未实现功能
获取非技术论坛时遇到一个讨论帖子,前面没有帖子状态,出现index下标异常
未爬取推荐精华页的所有帖子(只实现了第一页的爬取)
未爬取帖子内容(帖子发布的内容和回复信息等等)
未爬取发帖人的个人信息(排名,发帖数,回帖数,结帖率等等)
总结:
python的很多基础方法不知道
字符串操作不熟练
xpath语法不熟练
peewee很多方法不知道
马虎,判断帖子有没有内容时,后面忘加一个方法导致运行错误,找了半个多小时才找到
未实现功能应该都能解决,只是嫌麻烦
"""
抓取
解析
存储
"""
import re
import ast
from urllib import parse
import requests
from scrapy import Selector
import json
import time
from csdn_spider.models import * domain = 'https://bbs.csdn.net'
def get_nodes_json():
left_menu_text = requests.get('https://bbs.csdn.net/dynamic_js/left_menu.js?csdn').text
# print(left_menu_text)
nodes_str_match = re.search('forumNodes: (.*])',left_menu_text)
if nodes_str_match:
nodes_str = nodes_str_match.group(1).replace('null','None')
nodes_list = ast.literal_eval(nodes_str)
# print(nodes_list)
return nodes_list
return [] url_list = []
def process_nodes_list(nodes_list):
#将js的格式提取出url转换到list中
for item in nodes_list:
if 'url' in item:
if item['url']:
url_list.append(item['url'])
if 'children' in item:
process_nodes_list(item['children']) def get_levell_list(nodes_list):
levell_url = []
for item in nodes_list:
if 'url' in item and item['url']:
levell_url.append(item['url'])
return levell_url def get_last_list():
#获取最终需要抓取的url
nodes_list = get_nodes_json()
process_nodes_list(nodes_list)
levell_url = get_levell_list(nodes_list)
last_url = []
for url in url_list:
if url not in levell_url:
last_url.append(url)
all_urls = []
for url in last_url:
all_urls.append(parse.urljoin(domain, url+'/recommend'))
return all_urls def parse_list(url):
res_text = requests.get(url).text
sel = Selector(text=res_text)
all_sel = sel.xpath('//table[@class="forums_tab_table"]/tbody//tr')
if len(all_sel.extract()) != 0:
if str(re.search('没有帖子', all_sel.extract()[0])) != 'None':
print('没有帖子')
return
for tr in all_sel:
if (tr.xpath('td[@class="forums_topic"]/span[1]/text()').extract()) == ['[置顶]']:
print('发现置顶!!!')
print('置顶账号为:',tr.xpath('td[@class="forums_author"]/a/text()').extract()[0])
print('置顶内容为:',tr.xpath('td[@class="forums_topic"]/a[2]/text()').extract()[0])
print('置顶链接为:',parse.urljoin(domain,tr.xpath('td[@class="forums_topic"]/a[2]/@href').extract()[0]))
print('###############')
else:
#帖子状态
status = tr.xpath('td[@class="forums_topic_flag"]/span/text()').extract()[0]
# print('帖子状态', status)
#赏分
score = tr.xpath('td[@class="forums_score"]/em/text()').extract()[0]
# print('赏分', score)
#标题链接
topic_url = parse.urljoin(domain,tr.xpath('td[@class="forums_topic"]/a/@href').extract()[0])
# print('标题链接', topic_url)
#标题
topic_title = tr.xpath('td[@class="forums_topic"]/a/text()').extract()[0]
# print('标题', topic_title)
#标题id
topic_id = topic_url.split('/')[-1]
# print('标题id', topic_id)
#作者链接
id_url = tr.xpath('td[@class="forums_author"]/a/@href').extract()[0]
# print('作者链接', id_url)
#作者id
author_id = id_url.split('/')[-1]
# print('作者id', author_id)
#作者名称
author_name = tr.xpath('td[@class="forums_author"]/a/text()').extract()[0]
# print('作者名称', author_name)
#发布时间
create_time = datetime.strptime(tr.xpath('td[@class="forums_author"]/em/text()').extract()[0], '%Y-%m-%d %H:%M')
# print('发布时间', create_time)
#回复和查看的字符串
answer_info = (tr.xpath('td[@class="forums_reply"]/span/text()').extract()[0]).split('/')
#回复数量
answer_nums = answer_info[0]
# print('回复数量', answer_nums)
#查看数量
click_nums = answer_info[-1]
# print('查看数量', click_nums)
#最后发表时间
last_time = datetime.strptime(tr.xpath('td[@class="forums_last_pub"]/em/text()').extract()[0], '%Y-%m-%d %H:%M')
# print('最后发表时间', last_time)
#添加到数据库
Topic.create(id=topic_id,status=status,score=score,title_url=topic_url,title=topic_title,author_id=author_id,author_name=author_name,create_time=create_time,answer_nums=answer_nums,click_nums=click_nums,last_answer_time=last_time) if __name__=='__main__':
all_urls = get_last_list()
for url in all_urls:
print('正在连接:',url)
parse_list(url)
time.sleep(3)
from peewee import *#建立数据库连接
db = MySQLDatabase('spider', host='127.0.0.1', port=3306, user='root', password='123456lmr')
# class BaseModel(Model):
class Meta:
database = db '''
设计数据表的时候需要注意的点
char类型,尽量设置MAX(最大长度)
对于无法确定最大长度的,要采用TextField类型
default和null=True
主键无法设置int以外的类型(可能是版本问题)
''' #帖子list
class Topic(BaseModel):
#帖子名称
title = CharField()
#帖子链接
title_url = CharField(default='')
# #帖子内容
# content = TextField(default='')
#帖子id
id = IntegerField(primary_key=True)
#用户id
author_id = CharField()
#用户名称
author_name = CharField()
#创建时间
create_time = DateTimeField()
#回复数量
answer_nums = IntegerField(default=0)
#查看数量
click_nums = IntegerField(default=0)
# #点赞数量
# parised_nums = IntegerField(default=0)
# #结帖率
# jtl = FloatField(default=0.0)
#赏分
score = IntegerField(default=0)
#状态
status = CharField()
#最后回复时间
last_answer_time = DateTimeField() #帖子内容
class Answer(BaseModel):
#
topic_id = IntegerField()
author = CharField()
content = TextField(default="")
create_time = DateTimeField()
parised_nums = IntegerField(default=0) #点赞数 #用户
class Author(BaseModel):
name = CharField()
sign_name_id = CharField()
# id = CharField(primary_key=True)
click_nums = IntegerField(default=0) # 访问数
original_nums = IntegerField(default=0) # 原创数
forward_nums = IntegerField(default=0) # 转发数
rate = CharField(default=-1) # 排名
answer_nums = IntegerField(default=0) # 评论数
parised_nums = IntegerField(default=0) # 获赞数
desc = TextField(null=True)
industry = CharField(null=True)
location = CharField(null=True)
follower_nums = IntegerField(default=0) # 粉丝数
following_nums = IntegerField(default=0) # 关注数 if __name__ == '__main__':
# db.create_tables([Topic])
# db.create_tables([Answer])
# db.create_tables([Author])
db.create_tables([Topic, Answer, Author])
csdn论坛页抓取的更多相关文章
- python实现一个栏目的分页抓取列表页抓取
python实现一个栏目的分页抓取列表页抓取 #!/usr/bin/env python # coding=utf-8 import requests from bs4 import Beautifu ...
- 简易数据分析 12 | Web Scraper 翻页——抓取分页器翻页的网页
这是简易数据分析系列的第 12 篇文章. 前面几篇文章我们介绍了 Web Scraper 应对各种翻页的解决方法,比如说修改网页链接加载数据.点击"更多按钮"加载数据和下拉自动加载 ...
- 简易数据分析 10 | Web Scraper 翻页——抓取「滚动加载」类型网页
这是简易数据分析系列的第 10 篇文章. 友情提示:这一篇文章的内容较多,信息量比较大,希望大家学习的时候多看几遍. 我们在刷朋友圈刷微博的时候,总会强调一个『刷』字,因为看动态的时候,当把内容拉到屏 ...
- 简易新闻网站NewsWeb-网页抓取
本文转载自姚虎才子 今天做项目时用到java抓取网页内容,本以为很简单的一件事但是还是让我蛋疼了一会,网上资料一大堆但是都是通过url抓取网页内容,但是我要的是读取本地的html页面内容的方法,网上找 ...
- Python爬虫:新浪新闻详情页的数据抓取(函数版)
上一篇文章<Python爬虫:抓取新浪新闻数据>详细解说了如何抓取新浪新闻详情页的相关数据,但代码的构建不利于后续扩展,每次抓取新的详情页时都需要重新写一遍,因此,我们需要将其整理成函数, ...
- python3爬虫再探之豆瓣影评数据抓取
一个关于豆瓣影评的爬虫,涉及:模拟登陆,翻页抓取.直接上代码: import re import time import requests import xlsxwriter from bs4 imp ...
- Golang分布式爬虫:抓取煎蛋文章|Redis/Mysql|56,961 篇文章
--- layout: post title: "Golang分布式爬虫:抓取煎蛋文章" date: 2017-04-15 author: hunterhug categories ...
- Python抓取成都房价信息
Python里scrapy爬虫 scrapy爬虫,正好最近成都房价涨的厉害,于是想着去网上抓抓成都最近的房价情况,顺便了解一下,毕竟咱是成都人,得看看这成都的房子我以后买的起不~ 话不多说,进入正题: ...
- Python 爬虫抓取代理IP,并检测联通性
帮朋友抓了一些代理IP,并根据测试联的通性,放在了不通的文件夹下.特将源码分享 注意: 1,环境Python3.5 2,安装BeautifulSoup4 requests 代码如下: 1 2 3 4 ...
随机推荐
- 【DFS练习】Pku1950 Dessert-C++
这道题和这道题很类似. 这里还是说一下坑点,因为前一道题'等式'的加数只有9个,但是这道题目最大到了15,所以在选择不加符号的时候需要判断是用100去乘还是用10去乘就可以了. 基本代码稍微把相关的9 ...
- sizeof()和lstrlen()和strlen()区别
strlen()是返回字符串的字节长度, lstrlen()是返回字符串的字符长度. 也就是说第二个函数可能和第一个函数结果一样,如果字符串中字符单位都是单字节的话. 一般来说主要 ...
- GO学习笔记 - 命令行解析
本文主题:基于os.Args与flag实现Golang命令行解析. 小慢哥的原创文章,欢迎转载 目录 ▪ 一. os.Args ▪ 二. flag ▪ 三. 结合os.Args与flag实现子命令 ▪ ...
- 「数据分析」Sqlserver中的窗口函数的精彩应用之数据差距与数据岛(含答案)
上一篇介绍过数据差距与数据岛的背景,这里不再赘述,请翻阅上一文.此篇在Sqlserver上给大家演示1000万条记录的计算性能. 测试电脑软硬件说明 一般般的笔记本电脑,2017年7月,价格:4500 ...
- [PTA] 数据结构与算法题目集 6-8 求二叉树高度 & 6-9 二叉树的遍历
6.8 二叉树高度 int GetHeight(BinTree BT) { if (BT == NULL) return 0; int leftH = GetHeight(BT->Left); ...
- SQLyog 破解版
百度云:链接:http://pan.baidu.com/s/1eSMEzIE 密码:ubi2
- thinkphp 数据库操作
//所有的数据中,查出某个字段$result = $music->field('music')->select();$hotlist = M('News')->where('stat ...
- spring源码分析之配置文件名占位符的解析(一)
一.直接写个测试例子 package com.test; import org.junit.Test; import org.springframework.context.ApplicationCo ...
- http.client.ResponseNotReady: Request-sent
最近学习python写接口测试,使用的是connection.request 发现在测试一个发送报告接口时候,同一个接口,同样的脚本,只是一个参数传不同值,总提示:http.client.Respon ...
- JAVA常用的集合类
package com.xian.test; import java.util.ArrayList; import java.util.Enumeration; import java.util.Ha ...