爬取網(wǎng)址:http://www.reibang.com/c/bDHhpK
爬取信息:用戶ID棍潘,發(fā)表時(shí)間瓶籽,標(biāo)題匠童,內(nèi)容,瀏覽量塑顺,評(píng)論數(shù)汤求,點(diǎn)贊數(shù),打賞數(shù)(可能沒(méi)有)
爬取方式:使用lxml解析严拒。
存儲(chǔ)方式:MongoDB存儲(chǔ) & MySQL存儲(chǔ)
1.MongoDB存儲(chǔ)代碼如下:
import requests
from lxml import etree
import pymongo
from multiprocessing import Pool
#下述三條語(yǔ)句不能放在"if __name__ == '__main__'"中扬绪,否則無(wú)法寫入數(shù)據(jù)庫(kù)。
client = pymongo.MongoClient('localhost', 27017) #連接數(shù)據(jù)庫(kù)
mydb = client['mydb']
jianshu = mydb['jianshu'] ##創(chuàng)建數(shù)據(jù)庫(kù)和數(shù)據(jù)集合
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 = "無(wú)"
else:
reward = reward1[0].strip()
data = {
'用戶ID':author,
'發(fā)表日期':write_time,
'標(biāo)題':title,
'內(nèi)容':content,
'瀏覽量':view,
'評(píng)論數(shù)':comment,
'點(diǎn)贊數(shù)':great,
'打賞數(shù)':reward
}
jianshu.insert_one(data)
except IndexError:
pass
if __name__ == '__main__':
url_list = ["http://www.reibang.com/c/bDHhpK?order_by=added_at&page={}".format(str(i)) for i in range(1,1001)]
pool = Pool(processes=4) #創(chuàng)建進(jìn)程池
pool.map(get_info, url_list) #調(diào)用進(jìn)程池
在代碼運(yùn)行過(guò)程中裤唠,如果想查詢當(dāng)前獲取的數(shù)據(jù)量挤牛,可以通過(guò)Robomongo,對(duì)集合點(diǎn)擊右鍵選擇“Statistics”來(lái)實(shí)現(xiàn)种蘸。
在數(shù)值count中即可看到當(dāng)前獲取的數(shù)據(jù)量墓赴。
當(dāng)然,通過(guò)命令行也可以實(shí)現(xiàn)航瞭。
① 在bin文件夾中輸入mongo
② 輸入use mydb
③ 輸入db.jianshu.find().count()
顯示結(jié)果均為1995诫硕。
2.采用MySQL存儲(chǔ)
1)先建立數(shù)據(jù)表 jianshu
CREATE TABLE jianshu(
用戶ID TEXT,
發(fā)表日期 TEXT,
標(biāo)題 TEXT,
內(nèi)容 TEXT,
瀏覽量 TEXT,
評(píng)論數(shù) TEXT,
點(diǎn)贊數(shù) TEXT,
打賞數(shù) TEXT
)ENGINE INNODB DEFAULT CHARSET=utf8;
2)然后修改了一下導(dǎo)入的模塊,寫入mysql的數(shù)據(jù)格式刊侯,存儲(chǔ)到mysql的操作命令等章办,基本就可以運(yùn)作了。需要注意的是,采用多線程池的操作時(shí)藕届,不要把mysql的相關(guān)操作命令寫入"if name == 'main'"中挪蹭,否則報(bào)錯(cuò)。
代碼如下:
import requests
from lxml import etree
import pymysql
from multiprocessing import Pool
###下述兩條語(yǔ)句不能放在"if __name__ == '__main__'"中翰舌,否則無(wú)法連接數(shù)據(jù)庫(kù)嚣潜。
conn = pymysql.connect(host='localhost',user='root',db='mydb',port=3306,charset="utf8") #連接數(shù)據(jù)庫(kù)
cursor = conn.cursor() #光標(biāo)對(duì)象
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 = "無(wú)"
else:
reward = reward1[0].strip()
cursor.execute('INSERT INTO jianshu(用戶ID,發(fā)表日期,標(biāo)題,內(nèi)容,瀏覽量,評(píng)論數(shù),點(diǎn)贊數(shù),打賞數(shù)) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)',
(author,write_time,title,content,view,comment,great,reward)) #插入數(shù)據(jù)
conn.commit() #提交事務(wù) **此語(yǔ)句也不能放入"if __name__ == '__main__'"中冬骚,否則無(wú)法寫入數(shù)據(jù)庫(kù)椅贱。
except IndexError:
pass
if __name__ == '__main__':
url_list = ["http://www.reibang.com/c/bDHhpK?order_by=added_at&page={}".format(str(i)) for i in range(1,1001)]
pool = Pool(processes=4) #創(chuàng)建進(jìn)程池
pool.map(get_info, url_list) #調(diào)用進(jìn)程池
好不容易讓數(shù)據(jù)入庫(kù)Mysql,但是運(yùn)行完幾頁(yè)后只冻,還是出現(xiàn)了點(diǎn)編碼方面的小問(wèn)題:
Traceback (most recent call last):
File "F:\Python-Ex\try.py", line 588, in <module>
pool.map(get_info, url_list) #調(diào)用進(jìn)程池
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 '標(biāo)題' at row 1")
原因是Mysql里UTF8編碼最多只能支持3個(gè)字節(jié)庇麦,而Emoji表情字符使用的UTF8編碼,很多都是4個(gè)字節(jié)喜德,有些甚至是6個(gè)字節(jié)山橄。
而最簡(jiǎn)單的方法就是把特殊字符替換掉。
由于時(shí)間關(guān)系舍悯,這里就不展開(kāi)了航棱。
相關(guān)解決方案,可以參考以下鏈接:
http://blog.csdn.net/z69183787/article/details/48465729