美文网首页我爱编程Python爬虫
二十二.多进程实战 - 简书网热评文章

二十二.多进程实战 - 简书网热评文章

作者: 橄榄的世界 | 来源:发表于2018-02-22 23:33 被阅读0次

爬取网址:https://www.jianshu.com/c/bDHhpK
爬取信息:用户ID,发表时间,标题,内容,浏览量,评论数,点赞数,打赏数(可能没有)
爬取方式:使用lxml解析。
存储方式:MongoDB存储 & MySQL存储

image.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”来实现。


image.png

在数值count中即可看到当前获取的数据量。


image.png

当然,通过命令行也可以实现。
① 在bin文件夹中输入mongo
② 输入use mydb
③ 输入db.jianshu.find().count()

image.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

相关文章

  • 二十二.多进程实战 - 简书网热评文章

    爬取网址:https://www.jianshu.com/c/bDHhpK爬取信息:用户ID,发表时间,标题,内容...

  • 实战爬取简书网热评文章(基于lxml及多进程爬虫方法)

    目标 爬取简书网“首页投稿”热评文章的信息,包括用户ID(author)、文章标题(title)、文章内容(con...

  • 用处

    今天我刚注册简书,想借练笔一用。翻了翻热评文章,说实话,我内心有点不舒服。 所谓的热评文章,大概是心灵鸡汤,又或者...

  • 我实在是太高估自己的毅力了

    好几天没有看简书了,由于今天只有两节网课,感觉很轻松,来简书看看,发现“小红点”和关注的人又增多了。 有人给文章评...

  • 贝交易成功

    来简书一年多,每天傻傻写,傻傻评,简书规则从不研究,中午闲来无事,点开简书,翻翻已有5000多贝,忽生交易念头,看...

  • 乘风破浪

    数月连续加班的我,每天晚上都会翻看简书文章,多次看到黄圣依、张雨绮关于《乘风破浪的姐姐》中的热评,很是好奇...

  • 4.4、信号,子进程实战,文件I/O详谈

    1、信号功能实战重载配置文件,热更新,子进程崩溃父进程重新拉起来。sigaction()#课后:搭建信号处理框架。...

  • 动态库和静态库的区别

    参考文章链接: 组件化-动态库实战 - 简书 DevNotes/framework2.md at master ·...

  • 杂想

    下载了简书。 看着热评里的文章,有好多都戳中了我的点,其实自己也是有着文学梦,有着诗和远方,但是只是有着,没有付出...

  • 《资本论》第三章 货币与商品流通(四)

    文章会在简书与微信公众号同步更新,微信公众号:萧二十二

网友评论

    本文标题:二十二.多进程实战 - 简书网热评文章

    本文链接:https://www.haomeiwen.com/subject/dqtatftx.html