爬取网址:https://www.jianshu.com/c/bDHhpK
爬取信息:用户ID,发表时间,标题,内容,浏览量,评论数,点赞数,打赏数(可能没有)
爬取方式:使用lxml解析。
存储方式:MongoDB存储 & MySQL存储
![](https://img.haomeiwen.com/i10026411/ca226885350c2ce0.png)
1.MongoDB存储代码如下:
import requests
from lxml import etree
import pymongo
from multiprocessing import Pool
#下述三条语句不能放在"if __name__ == '__main__'"中,否则无法写入数据库。
client = pymongo.MongoClient('localhost', 27017) #连接数据库
mydb = client['mydb']
jianshu = mydb['jianshu'] ##创建数据库和数据集合
def get_info(url):
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3294.6 Safari/537.36'}
r = requests.get(url,headers =headers)
html = etree.HTML(r.text)
infos = html.xpath('//ul[@class="note-list"]/li')
for info in infos:
try:
author = info.xpath('div/div[1]/div/a/text()')[0]
write_time = info.xpath('div/div[1]/div/span/@data-shared-at')[0]
title = info.xpath('div/a/text()')[0]
content = info.xpath('div/p/text()')[0].strip()
view = info.xpath('div/div[2]/a/text()')[1].strip()
comment = info.xpath('div/div[2]/a[2]/text()')[1].strip()
great = info.xpath('div/div[2]/span[1]/text()')[0].strip()
reward1 = info.xpath('div/div[2]/span[2]/text()')
if len(reward1)== 0:
reward = "无"
else:
reward = reward1[0].strip()
data = {
'用户ID':author,
'发表日期':write_time,
'标题':title,
'内容':content,
'浏览量':view,
'评论数':comment,
'点赞数':great,
'打赏数':reward
}
jianshu.insert_one(data)
except IndexError:
pass
if __name__ == '__main__':
url_list = ["https://www.jianshu.com/c/bDHhpK?order_by=added_at&page={}".format(str(i)) for i in range(1,1001)]
pool = Pool(processes=4) #创建进程池
pool.map(get_info, url_list) #调用进程池
在代码运行过程中,如果想查询当前获取的数据量,可以通过Robomongo,对集合点击右键选择“Statistics”来实现。
![](https://img.haomeiwen.com/i10026411/a0ee3ce641c65d9f.png)
在数值count中即可看到当前获取的数据量。
![](https://img.haomeiwen.com/i10026411/cdb9d28a915b0938.png)
当然,通过命令行也可以实现。
① 在bin文件夹中输入mongo
② 输入use mydb
③ 输入db.jianshu.find().count()
![](https://img.haomeiwen.com/i10026411/0ed3a445a966ec20.png)
显示结果均为1995。
2.采用MySQL存储
1)先建立数据表 jianshu
CREATE TABLE jianshu(
用户ID TEXT,
发表日期 TEXT,
标题 TEXT,
内容 TEXT,
浏览量 TEXT,
评论数 TEXT,
点赞数 TEXT,
打赏数 TEXT
)ENGINE INNODB DEFAULT CHARSET=utf8;
2)然后修改了一下导入的模块,写入mysql的数据格式,存储到mysql的操作命令等,基本就可以运作了。需要注意的是,采用多线程池的操作时,不要把mysql的相关操作命令写入"if name == 'main'"中,否则报错。
代码如下:
import requests
from lxml import etree
import pymysql
from multiprocessing import Pool
###下述两条语句不能放在"if __name__ == '__main__'"中,否则无法连接数据库。
conn = pymysql.connect(host='localhost',user='root',db='mydb',port=3306,charset="utf8") #连接数据库
cursor = conn.cursor() #光标对象
def get_info(url):
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3294.6 Safari/537.36'}
r = requests.get(url,headers =headers)
html = etree.HTML(r.text)
infos = html.xpath('//ul[@class="note-list"]/li')
for info in infos:
try:
author = info.xpath('div/div[1]/div/a/text()')[0]
write_time = info.xpath('div/div[1]/div/span/@data-shared-at')[0]
title = info.xpath('div/a/text()')[0]
content = info.xpath('div/p/text()')[0].strip()
view = info.xpath('div/div[2]/a/text()')[1].strip()
comment = info.xpath('div/div[2]/a[2]/text()')[1].strip()
great = info.xpath('div/div[2]/span[1]/text()')[0].strip()
reward1 = info.xpath('div/div[2]/span[2]/text()')
if len(reward1)== 0:
reward = "无"
else:
reward = reward1[0].strip()
cursor.execute('INSERT INTO jianshu(用户ID,发表日期,标题,内容,浏览量,评论数,点赞数,打赏数) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)',
(author,write_time,title,content,view,comment,great,reward)) #插入数据
conn.commit() #提交事务 **此语句也不能放入"if __name__ == '__main__'"中,否则无法写入数据库。
except IndexError:
pass
if __name__ == '__main__':
url_list = ["https://www.jianshu.com/c/bDHhpK?order_by=added_at&page={}".format(str(i)) for i in range(1,1001)]
pool = Pool(processes=4) #创建进程池
pool.map(get_info, url_list) #调用进程池
好不容易让数据入库Mysql,但是运行完几页后,还是出现了点编码方面的小问题:
Traceback (most recent call last):
File "F:\Python-Ex\try.py", line 588, in <module>
pool.map(get_info, url_list) #调用进程池
File "C:\Python36\lib\multiprocessing\pool.py", line 266, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:\Python36\lib\multiprocessing\pool.py", line 644, in get
raise self._value
pymysql.err.InternalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x8E\\xA4\\xE5\\xB8...' for column '标题' at row 1")
原因是Mysql里UTF8编码最多只能支持3个字节,而Emoji表情字符使用的UTF8编码,很多都是4个字节,有些甚至是6个字节。
而最简单的方法就是把特殊字符替换掉。
由于时间关系,这里就不展开了。
相关解决方案,可以参考以下链接:
http://blog.csdn.net/z69183787/article/details/48465729
网友评论