分类目录归档:Python 爬虫

Python 超简单爬取微博热搜榜数据

微博的热搜榜对于研究大众的流量有非常大的价值。今天的教程就来说说如何爬取微博的热搜榜。 热搜榜的链接是:

https://s.weibo.com/top/summary/

用浏览器浏览,发现在不登录的情况下也可以正常查看,那就简单多了。使用开发者工具(F12)查看页面逻辑,并拿到每条热搜的CSS位置,方法如下:

按照这个方法,拿到这个td标签的selector是:
pl_top_realtimehot > table > tbody > tr:nth-child(3) > td.td-02

其中nth-child(3)指的是第三个tr标签,因为这条热搜是在第三名的位置上,但是我们要爬的是所有热搜,因此:nth-child(3)可以去掉。

还要注意的是 pl_top_realtimehot 是该标签的id,id前需要加#号,最后变成:
#pl_top_realtimehot > table > tbody > tr > td.td-02

你可以自定义你想要爬的信息,这里我需要的信息是:热搜的链接及标题、热搜的热度。它们分别对应的CSS选择器是:

链接及标题:#pl_top_realtimehot > table > tbody > tr > td.td-02 > a
热度:#pl_top_realtimehot > table > tbody > tr > td.td-02 > span

值得注意的是链接及标题是在同一个地方,链接在a标签的href属性里,标题在a的文本中,用beautifulsoup有办法可以都拿到,请看后文代码。

现在这些信息的位置我们都知道了,接下来可以开始编写程序。默认你已经安装好了python,并能使用cmd的pip,如果没有的话请见这篇教程:python安装。需要用到的python的包有:

BeautifulSoup4 安装指令:

pip install beautifulsoup4

lxml解析器安装指令:

pip install lxml

lxml是python中的一个包,这个包中包含了将html文本转成xml对象的工具,可以让我们定位标签的位置。而能用来识别xml对象中这些标签的位置的包就是 Beautifulsoup4.

编写代码:

# https://s.weibo.com/top/summary/
import requests
from bs4 import BeautifulSoup

if __name__ == "__main__":
    news = []
    # 新建数组存放热搜榜
    hot_url = 'https://s.weibo.com/top/summary/'
    # 热搜榜链接
    r = requests.get(hot_url)
    # 向链接发送get请求获得页面
    soup = BeautifulSoup(r.text, 'lxml')
    # 解析页面

    urls_titles = soup.select('#pl_top_realtimehot > table > tbody > tr > td.td-02 > a')
    hotness = soup.select('#pl_top_realtimehot > table > tbody > tr > td.td-02 > span')

    for i in range(len(urls_titles)-1):
        hot_news = {}
        # 将信息保存到字典中
        hot_news['title'] = urls_titles[i+1].get_text()
        # get_text()获得a标签的文本
        hot_news['url'] = "https://s.weibo.com"+urls_titles[i]['href']
        # ['href']获得a标签的链接,并补全前缀
        hot_news['hotness'] = hotness[i].get_text()
        # 获得热度文本
        news.append(hot_news) 
        # 字典追加到数组中 
    
    print(news)

代码说明请看注释,不过这样做,我们仅仅是将结果保存到数组中,如下所示,其实不易观看,我们下面将其保存为csv文件。

Python 热搜榜爬虫
    import datetime
    today = datetime.date.today()
    f = open('./热搜榜-%s.csv'%(today), 'w', encoding='utf-8')
    for i in news:
        f.write(i['title'] + ',' + i['url'] + ','+ i['hotness'] + '\n')

效果如下,怎么样,是不是好看很多:

Python 微博热搜榜爬虫

完整代码如下:

# https://s.weibo.com/top/summary/
import requests
from bs4 import BeautifulSoup

if __name__ == "__main__":
    news = []
    # 新建数组存放热搜榜
    hot_url = 'https://s.weibo.com/top/summary/'
    # 热搜榜链接
    r = requests.get(hot_url)
    # 向链接发送get请求获得页面
    soup = BeautifulSoup(r.text, 'lxml')
    # 解析页面

    urls_titles = soup.select('#pl_top_realtimehot > table > tbody > tr > td.td-02 > a')
    hotness = soup.select('#pl_top_realtimehot > table > tbody > tr > td.td-02 > span')

    for i in range(len(urls_titles)-1):
        hot_news = {}
        # 将信息保存到字典中
        hot_news['title'] = urls_titles[i+1].get_text()
        # get_text()获得a标签的文本
        hot_news['url'] = "https://s.weibo.com"+urls_titles[i]['href']
        # ['href']获得a标签的链接,并补全前缀
        hot_news['hotness'] = hotness[i].get_text()
        # 获得热度文本
        news.append(hot_news)
        # 字典追加到数组中
    
    print(news)

    import datetime
    today = datetime.date.today()
    f = open('./热搜榜-%s.csv'%(today), 'w', encoding='utf-8')
    for i in news:
        f.write(i['title'] + ',' + i['url'] + ','+ i['hotness'] + '\n')

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

python 文件下载、大文件下载、异步批量下载 教程

按照不同的情况,Python下载文件可以分为三种:小文件下载大文件下载、批量下载

本文源代码: https://pythondict.com/download/python-file-download-source-code/

python 小文件下载

流程:使用request.get请求链接,返回的内容放置到变量r中,然后将r写入到你想放的地方。

Python小文件下载流程

以下载上述流程图为例子:

# 例1
import requests
def request_zip(url):
    r = requests.get(url) 
    # 请求链接后保存到变量r中
    with open("new/名字.png",'wb') as f:
        # r.content写入至文件
        f.write(r.content)
request_zip('https://pythondict.com/wp-content/uploads/2019/08/2019082807222049.png')

运行完毕后,它将会被保存到当前文件夹的new文件夹里。

python 大文件下载

我们在小文件下载的时候,是将文件内容暂存到变量里,大家想想,下载大文件的时候还这样做会有什么问题?

很简单,如果你的内存只有8G,结果要下载文件却有10G那么大,那就肯定无法下载成功了。而且本机软件运行占的内存也比较大,如果你的内存只有8G,实际上剩余可用的内存可能低于2G-4G. 这种情况下怎么下载大文件呢?

流式分块下载

原理:一块一块地将内存写入到文件中,以避免内存占用过大。

Python大文件下载流程

当设置了request.get(stream=True)的时候,就是启动流模式下载,典型特征:在r变量的content被调用的时候才会启动下载。代码如下:

# 例2
import requests
def request_big_data(url):
    name = url.split('/')[-1]
    # 获取文件名
    r = requests.get(url, stream=True)
    # stream=True 设置为流读取
    with open("new/"+str(name), "wb") as pdf:
        for chunk in r.iter_content(chunk_size=1024):
            # 每1024个字节为一块进行读取
            if chunk:
                # 如果chunk不为空
                pdf.write(chunk)
request_big_data(url="https://www.python.org/ftp/python/3.7.4/python-3.7.4-amd64.exe")

Python 批量文件下载

所谓批量下载,当然不是一个一个文件的下载了,比如说我们要下载百度图片,如果一个一个下载会出现两种负面情况:

  1. 如果某个请求堵塞,整个队列都会被堵塞
  2. 如果是小文件,单线程下载太慢

我们的解决方案是使用异步策略。如果你会用scrapy框架,那就轻松许多了,因为它结合了twisted异步驱动架构,根本不需要你自己写异步。不过我们python实用宝典讲的可是教程,还是跟大家说一下怎么实现异步下载:

我们需要使用到两个包,一个是asyncio、一个是aiohttp. asyncio是Python3的原装,但是aiohttp则需要各位使用cmd/Terminal打开,输入以下命令安装:

pip install aiohttp

注意asyncio是单进程并发,不是多线程,也不是多进程,是协程。单纯是在一个进程里面异步(切来切去运行),切换的地方用await标记,能够切换的函数用async标记。比如下载异步批量下载两个图片的代码如下:

# 例3
import aiohttp
import asyncio
import time
async def job(session, url):
    # 声明为异步函数
    name = url.split('/')[-1]
    # 获得名字
    img = await session.get(url)
    # 触发到await就切换,等待get到数据
    imgcode = await img.read()
    # 读取内容
    with open("new/"+str(name),'wb') as f:
        # 写入至文件
        f.write(imgcode)
    return str(url)

async def main(loop, URL):
    async with aiohttp.ClientSession() as session:
        # 建立会话session
        tasks = [loop.create_task(job(session, URL[_])) for _ in range(2)]
        # 建立所有任务
        finished, unfinished = await asyncio.wait(tasks)
        # 触发await,等待任务完成
        all_results = [r.result() for r in finished]
        # 获取所有结果
        print("ALL RESULT:"+str(all_results))

URL = ['https://pythondict.com/wp-content/uploads/2019/07/2019073115192114.jpg',
       'https://pythondict.com/wp-content/uploads/2019/08/2019080216113098.jpg']
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop, URL))
loop.close()

注意: img = await session.get(url)
这时候,在你请求第一个图片获得数据的时候,它会切换请求第二个图片或其他图片,等第一个图片获得所有数据后再切换回来。从而实现多线程批量下载的功能,速度超快,下载超清大图用这个方法可以一秒一张。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦,有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典