python爬虫android菜鸟低调修行纪念册测试开发

新手向爬虫(一)利用工具轻松爬取简书并分析

2016-11-03  本文已影响7054人  treelake

爬取目标

爬取四块简单的简书网页,并做一定的分析。

网络请求和解析使用库

数据存储

首先我们做最简单的第四块

import requests
from bs4 import BeautifulSoup
# 引入库
base_url = 'http://www.jianshu.com/collections/16/notes?order_by=added_at&page=%d' # page=0 和 page=1的效果相同
add_url = 1 # page数
num = 0 # 文章标题计数

while(True):
    try:
        page = requests.request('get', base_url% add_url).content
        # 将基础网址和页数拼接得到实际网址,使用request的get方法获取响应,再用content方法得到内容
        soup = BeautifulSoup(page) 
        # 使用BeautifulSoup分析页面,这里并没有指定解析器,会自动选取可获得的最优解析器
        # BeautifulSoup会报一个warning要你选择解析器,可以忽略
        
        article_list = [i.get_text() for i in soup.select(".title a")]
        # 这里使用了BeautifulSoup的选择器soup.select,它会返回一个被选取的对象列表,我们使用列表推导,对每个对象获取其中的文字再组成列表。
        # 选择器使用见下文
        for i in article_list:
        # 将文章列表打印出来
            num+=1
            print(num, '  ', i)
        add_url += 1
    except Exception as e:
    # 异常分析,打印出异常信息
        print(e)
        break # 这里使用break退出循环,也可注释掉该句,不断循环

接着让我们来看看首页热门文章

import requests
from bs4 import BeautifulSoup
import csv # 引入csv模块,读写csv文件
import datetime # 引入日期时间模块

base_url = 'http://jianshu.com'

def shouYeReMen():
    add_url = '' # 先置为空字符串
    title_list = [] # 文章标题列表
    
    for i in range(15): # 首页热门实际为15页,一开始可以设大些让程序自动退出来看到底有多少页
        try:
            first_page = requests.get(base_url+ add_url).content
            soup = BeautifulSoup(first_page, "lxml")
            title_list += [i.get_text() for i in soup.select(".title a")]
            # 以上和上一个爬虫类同
            try:
                # print(soup.select(".ladda-button"))
                add_url = soup.select(".ladda-button")[-1].get("data-url")
                # 使用get方法获取button的标签属性信息作为额外的url
                # 这里使用try,在最后一页没有button时会抛出异常
            except:
                # 在异常处理中通过break退出循环
                break
        except requests.exceptions.ConnectionError: # 有可能请求过多导致服务器拒绝连接
            status_code = "Connection refused"
            print(status_code)
            time.sleep(60)
            # 我们睡眠一分钟后再爬
    with open(datetime.datetime.now().strftime('%Y_%m_%d-%H_%M_%S')+'.csv', 'w', newline='', encoding='utf-8') as f:
    # 在脚本当前文件目录下新建以当前时间命名的csv文件,使用utf8编码
        writer = csv.writer(f)
        # 传入文件描述符构建csv写入器
        writer.writerow(title_list)
        # 将本次爬取的所有文章列表写在一行中
        
    print("have_done!")
    
import time
# 最后,我们循环爬取首页信息,为了减轻服务器负担,也避免爬虫请求被拒绝,我们每隔30秒爬取一次
while True:
    shouYeReMen()
    time.sleep(30)
import jieba
from collections import Counter
# 引入便捷的Counter函数,可以看作一个计数器,计算元素在列表中的出现次数
# Counter([1,2,3,1])的输出为Counter({1: 2, 2: 1, 3: 1})
import csv

def word_frequency(text):
# 定义词频统计函数
    words = [word for word in jieba.cut(text, cut_all=False) if len(word) >= 2]
    # 这里我们直接使用jieba.cut函数来分析文本的词汇,为了方便,我们先选取2个字以上的词统计
    # 进一步可以自定义词库,去掉与增加某些词
    c = Counter(words)
    # 统计词频,并利用Counter的方法返回频率最高的18个(词汇,频率)的元组列表
    return c.most_common(18)
        
        
import os; os.chdir(r'E:\python\shouye')
# 这里我使用了系统库,改变当前所处路径,也就是改到下面读取和保存文件的路径
import glob

result = open('result.csv', 'a', newline='', encoding='gb2312')
# 这里编码为gb2312,以便直接在excel中打开查看
writer = csv.writer(result)

filelist = glob.glob('2016_*.csv')
# 使用glob获取当前路径下所有以2016_开头的csv文件名的列表,顺序为文件名顺序
num=1 # 打印输出计数
for file in filelist:
    with open(file, 'r', encoding='utf-8') as f:
        line = f.readline()
        # 读取存有信息的一行
        row = [(word+'-'+str(freq)) for word, freq in word_frequency(line)]
        writer.writerow(row)
        # 以 word, freq = (w, f) 解包返回的词频数据,并组合word和freq(使用str()将freq由数字转化为字符串类型),写入文件
    print("haha",num)
    num+=1
        
result.close()
# 记得关闭文件

再进一步,爬取第三块-热门专题页

from tinydb import TinyDB
db = TinyDB('collection_db.json')
# 这里我们尝试下tinydb,一句话就获得了新建的数据库对象
import csv
csvfile = open("1.csv", "w", encoding='utf-8') # 先保存为utf8编码,以免出现gbk编码错误
fieldnames = ["cname", "href", "focus_number", "essays", "hot_url", "new_url"] # 设定Excel文件的列表头
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
# 这里我们获取csv的字典插入器,可以直接插入字典,键为列表头中的内容
writer.writeheader()
# 写入列表头

import requests
from bs4 import BeautifulSoup
import re
reg = re.compile('(\d+)篇')
# 使用正则匹配来获取篇数,(\d+)表示多个数字

base_url = "http://jianshu.com"
collectionlist_url = "http://www.jianshu.com/collections?order_by=score&page=%d"
# collection_url = 'http://www.jianshu.com/collections/%d/notes?order_by=added_at&page=1'
add_url = 1
# collection_num = 1

collection_selector = "h5 a" # 专题名
focus_on_selector = ".follow > span" # 关注人数
total_essay_selector = ".blue-link" # 总篇数
hot_selector = ".top-articles a" # 热门排序
new_selector = ".latest-articles a" # 最新收入

total_collection_list = []


while(add_url < 300):
    try: # 请求并获取各种数据
        first_page = requests.request('get', collectionlist_url% add_url).content
        soup = BeautifulSoup(first_page, "lxml")
        
        collection_list = [[i.get_text(),i.get('href')] for i in soup.select(collection_selector)] # 一组24个
        if not collection_list : break
        
        focus_on_list = [i.get_text() for i in soup.select(focus_on_selector)] 
        focus_on_list = [int(float(i.replace('K', ''))*1000) if ('K' in i) else int(i) for i in focus_on_list]
        # 对尾缀K处理,将K去掉,将数字乘以1000
        
        total_essay_list =[ int( reg.findall(i.get_text())[0] ) for i in soup.select(total_essay_selector)]
        # 使用zip将多个可迭代对象合并在一起使用
        for c,f,e in zip(collection_list, focus_on_list, total_essay_list):
            c.append(f);c.append(e)
            second_page = requests.request('get', base_url+c[1]).content
            # 访问专题页面,获取该专题的热门链接和最新加入文章页的链接。
            soup = BeautifulSoup(second_page, "lxml")
            hot_url = soup.select(hot_selector)[0].get('href')
            new_url = soup.select(new_selector)[0].get('href')
            c += [hot_url, new_url]
            
        for i in collection_list:
            #print(add_url, '  ', i)
            collection_dict = {"cname": i[0], "href":i[1], "focus_number":i[2], "essays":i[3], "hot_url":i[4], "new_url":i[5]}
            db.insert(collection_dict)
            # 一句话插入数据库
            writer.writerow(collection_dict)
            # 写入csv文件
        
        print(add_url)    
        add_url += 1
        total_collection_list += collection_list
        
    except Exception as e:
        print(e)
        break

csvfile.close()
# 关闭文件

最后轻松一下,完成推荐文章爬取

import requests
from bs4 import BeautifulSoup

base_url = 'http://jianshu.com'
add_url = '/recommendations/notes'
num = 0

while(True):
    try:
        first_page = requests.request('get', base_url+ add_url).content
        soup = BeautifulSoup(first_page, "lxml")
        title_list = [i.get_text() for i in soup.select(".title a")]
        for i in title_list:
            num+=1
            print(num, '  ', i)
        # print(title_list)
        try:
            # print(soup.select(".ladda-button"))
            add_url = soup.select(".ladda-button")[-1].get("data-url")
        except:
            break
    except Exception as e:
        print(e)
        break
上一篇 下一篇

猜你喜欢

热点阅读