网络爬虫技术文档

前言

网络爬虫又称网络蜘蛛、网络机器人,它是一种按照一定的规则自动浏览、检索网页信息的程序或者脚本。网络爬虫能够自动请求网页,并将所需要的数据抓取下来。通过对抓取的数据进行处理,从而提取出有价值的信息。

但要注意:爬虫是一把双刃剑

关于爬虫的如何合法使用,应遵守《中华人民共和国网络安全法》


一、爬虫基础

1、爬虫的简单定义

网络爬虫,又称为网页蜘蛛、蚂蚁、蠕虫、模拟程序,在FOAF社区中,被称为二王爷追逐者。是一种按照一定的规则,自动抓取万维网信息的程序或者脚本。简单来说,网络爬虫就是使用事先写好的程序去抓取网络上所需要的数据。


什么是上网

上网就是由用户端计算机发送给目标计算机,将目标计算机的数据下载到本地的过程。


爬虫要做的是什么

跳过代码模拟网络请求获取数据并解析数据最后保存。


爬虫的价值

如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的猎物。


互联网中最有价值的便是数据,比如天猫商城的商品信息,链家网的租房信息,雪球网的证券投资信息等等,这些数据都代表了各个行业的真金白银,可以说,谁掌握了行业内的第一手数据,谁就成了整个行业的主宰,如果把整个互联网的数据比喻为一座宝藏,那我们的爬虫课程就是来教大家如何来高效地挖掘这些宝藏,掌握了爬虫技能,你就成了所有互联网信息公司幕后的老板,换言之,它们都在免费为你提供有价值的数据。



2、通用网络爬虫

搜索引擎的第一步就是爬虫,但是搜索引擎中的爬虫是一种广泛获取各种网页信息的程序,除了HTML文件外,搜索引擎通常还会抓取和索引文字为基础的多种文件类型,如TXT,WORD,PDF等。但是对于图片, 视频,等非文字的内容则一般不会处理,并且对于脚本和一些网页中的程序也不会处理的。


3、聚焦网络爬虫

针对某一特定领域的数据进行抓取的程序。比如旅游网站,金融网站,招聘网站等等;特定领域的聚集爬虫会使用各种技术去处理我们需要的信息,所以对于网站中动态的那些程序,脚本仍会执行,以保证确定能抓取到网站中的数据。


4、爬虫的用途

解决冷启动问题:对于很多社交类的网站和应用程序,冷启动很困难。要想留住新注册的用户,需要先注入一批假用户,已构造社区的氛围。通常这些假的用户可以通过网络爬虫从微博或其他APP中抓取而来。

搜索引擎的根基:做搜索引擎需要数据来源,就是通过爬虫程序来实现的

建立知识图谱:这是在机器学习方面的用途,爬虫可以帮助建立起机器学习的训练集

数据分析:制作各种商品的比价,进行数据分析、趋势分析、走势预测

5、爬虫的合法性问题

1)目前还处于不明确的蛮阶段,“哪些行为不允许”这种基本秩序还处于建设中。

2)至少目前来看,如果抓取的数据为个人所用,则不存在问题;如果数据用于转载,那么抓取数据的类型就很重要了

3)一般来说,当抓取的数据是实现生活中的真实数据(比如,营业地址,电话清单)时,是允许转载的。但如果是原创数据(文章、意见、评论),通常就会受到版权限制,而不能转载。

4)不管怎么样,作为一个访客,应当约束自己的抓取行为,这就是说要求下.载请求的速度需要限定在一个合理值之内,并且还需要设定一个专属的用户代理来标识自己。


6、robots.txt文档

就是一个君子协议,记录了一些网站允许其他网站爬取的范围(allow允许,disallow不允许),比如: https://www.baidu.com/robots.txt和 https://www.douban.com/robots.txt


7、网站地图sitemap

sitemap是一个网站所有链接的容器,是一个xml文档。很多网站的连接层次比较深,很难抓取到,网站地图可以方便搜索引擎蜘蛛抓取网站页面,通过抓取网站页面,清晰了解网站的架构,网站地图一般存放在根目录下并命名为sitemap,为搜索引擎蜘蛛指路,增加网站重要内容页面的收录。网站地图就是根据网站的结构、框架、内容,生成的导航网页文件。大多数人都知道网站地图对于提高用户体验有好处:它们为网站访问者指明方向,并帮助迷失的访问者找到他们想看的页面。

比如:

https://www.mafengwo.cn/sitemapIndex.xml和 http://www.170hi.com/sitemap.xml

8、深度优先与广度优先

1)深度优先策略


2)广度优先策略


9、HTTP与HTTPS协议

URL:统一资源定位符,是用于完整地描述Internet上网页和其他资源地址的一种标识方法

HTTP协议:无连接(每次连接只处理一个请求),无状态(每次的传输都是独立的)

HTTPS协议:用于Web的安全传输协议,在传输层对网络连接进行加密

HTTP的缺省端口号为80,HTTPS的缺省端口号为443

GET请求:从服务器获取信息,传输给服务器的数据过程不够安全

POST请求:传输数据的过程是安全的,传输数据的大小理论上没有限制

HTTP响应的状态码:

200:成功

300:跳转

400,500:错误

404:页面未找到

二、爬虫技术

1、Web 前端的知识: HTML,CSS,JavaScript,DOM,DHTML,Ajax,jQuery,json等。

2、正则表达式,提取正常一般网页中想要的信息,比如某些特殊的文字,链接信息,懒惰,贪婪型正则表达式。

3、使用re,XPath,lxml,BeautifulSoup等获取一些DOM结构中的节点信息。

4、什么是深度优先,广度优先的抓取算法,及实践中的使用规则。

5、 分析简单网站的结构,使用urllib、requests 库进行简单的数据抓取。

6、什么是Hash,使用简单的MD5、SHA1等算法对数据进行Hash以便存储。

7、HTTP、HTTPS(更安全,使用了应用层加密)协议的基础知识,GET、POST方法,HTTP头中的信息,包括返回状态码,编码,userlagent, cookie, session等。

8、设置User-Agent进行数据爬取,设置代理等。

9、什么是Request、什么是Response,使用Fiddle, Wireshark等工具抓取及分析简单的网络数据包;对于动态爬虫,要分析Ajax请求,模拟制造Post数据包请求,抓取客户端session等信息,对于一些简单的网站,通过模拟数据包进行自动登录。

10、对于比较难搞定的网站,需使用浏览器+selenium抓取一些动态网页信息。

11、并发下载,通过并行下载加速数据抓取,多线程的使用。

12、使用Tesseract, 百度AI、HQG+SVM、CNN等库进行验证码识别。

13、使用数据挖掘的技术,分类算法等避兔死链等。

14、使用常用的数据库进行数据存储,查询,如Mongodb, Redis(大数据量的缓存)等;下载缓存,通过缓存避免重复下载的问题; Bloom Filter 的使用。

15、使用机器学习的技术动态调整爬虫的爬取策略,避免被禁IP封号等。

16、使用一些开源框架Scrapy、Celery等分布式爬虫,部署掌控分布式爬虫进行大规模的数据抓取。


三、网络爬虫是捜索引擎抓取系统的重要组成部分。


爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份。

对爬虫以及抓取系统进行一个简单的概述。


1、网络爬虫的基本结构及工作流程,一个通用的网络爬虫的框架如图所示:



网络爬虫的基本工作流程如下:


1.1.首先选取一部分精心挑选的种子URL;


1.2.将这些URL放入待抓取URL队列;


1.3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。


1.4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。


2、从爬虫的角度对互联网进行划分对应的,可以将互联网的所有页面分为五个部分:


2.1.已下载未过期网页


2.2.已下载已过期网页:抓取到的网页实际上是互联网内容的一个镜像与备份,互联网是动态变化的,一部分互联网上的内容已经发生了变化,这时,这部分抓取到的网页就已经过期了。


2.3.待下载网页:也就是待抓取URL队列中的那些页面


2.4.可知网页:还没有抓取下来,也没有在待抓取URL队列中,但是可以通过对已抓取页面或者待抓取URL对应页面进行分析获取到的URL,认为是可知网页。


2.5.还有一部分网页,爬虫是无法直接抓取下载的。称为不可知网页。


3、抓取策略


在爬虫系统中,待抓取URL队列是很重要的一部分。待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那个页面,后抓取哪个页面。而决定这些URL排列顺序的方法,叫做抓取策略。下面重点介绍几种常见的抓取策略:


3.1.深度优先遍历策略


深度优先遍历策略是指网络爬虫会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。我们以下面的图为例:




遍历的路径:A-F-G  E-H-I B C D

3.2.宽度优先遍历策略

宽度优先遍历策略的基本思路是,将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。还是以上面的图为例:

遍历路径:A-B-C-D-E-F G H I


3.3.反向链接数策略

反向链接数是指一个网页被其他网页链接指向的数量。反向链接数表示的是一个网页的内容受到其他人的推荐的程度。因此,很多时候搜索引擎的抓取系统会使用这个指标来评价网页的重要程度,从而决定不同网页的抓取先后顺序。

在真实的网络环境中,由于广告链接、作弊链接的存在,反向链接数不能完全等他我那个也的重要程度。因此,搜索引擎往往考虑一些可靠的反向链接数。


3.4.Partial PageRank策略

Partial PageRank算法借鉴了PageRank算法的思想:对于已经下载的网页,连同待抓取URL队列中的URL,形成网页集合,计算每个页面的PageRank值,计算完之后,将待抓取URL队列中的URL按照PageRank值的大小排列,并按照该顺序抓取页面。

如果每次抓取一个页面,就重新计算PageRank值,一种折中方案是:每抓取K个页面后,重新计算一次PageRank值。但是这种情况还会有一个问题:对于已经下载下来的页面中分析出的链接,也就是我们之前提到的未知网页那一部分,暂时是没有PageRank值的。为了解决这个问题,会给这些页面一个临时的PageRank值:将这个网页所有入链传递进来的PageRank值进行汇总,这样就形成了该未知页面的PageRank值,从而参与排序。下面举例说明:


3.5.OPIC策略策略

该算法实际上也是对页面进行一个重要性打分。在算法开始前,给所有页面一个相同的初始现金(cash)。当下载了某个页面P之后,将P的现金分摊给所有从P中分析出的链接,并且将P的现金清空。对于待抓取URL队列中的所有页面按照现金数进行排序。


3.6.大站优先策略

对于待抓取URL队列中的所有网页,根据所属的网站进行分类。对于待下载页面数多的网站,优先下载。这个策略也因此叫做大站优先策略。

四、爬虫框架

框架是为了解决特定的业务场景而开发的一套高质量代码,通过框架避免了重复造轮子的低效模式,可以更加专注于具体业务相关的代码。在python中,scrapy就是一个主流的爬虫框架,可以通过如下方式进行安装

scrapy框架的架构如下:


核心是Scrapy引擎,其他各部分的功能如下


1. Spiders,主要有两个功能,提供需要解析的url链接,即Requests,  同时负责解析html页面,从其中提取需要的信息,提取出来的标准化信息称之为Item;


2. Scheduler,称之为调度器,负责对多个Requests任务进行调度


3. Downloader Middlewares, 下载中间件,可以对Requests请求进行封装,典型的应用是添加User-Agent信息,


4. Downloader,负责下载,下载对应的Requests,从服务器获取响应信息,即Responses


5. Item PIpeline,Spiders将提取出标准的Item信息,交给Item PIpeline进行处理,比如去重复等操作

下面通过一个小的实例来看下该框架的使用,通过如下代码可以新建一个爬虫项目

python -m scrapy startproject hello_world

其中的setting.py 文件保存了爬虫相关的设置信息,最常见的用法是对以下选项进行设置

项目启动之后,我们首先要做的就是在spiders目录下,新建一个文件,编写我们的爬虫代码,文件的名字自己定义,内容示例

在代码中,start_urls提供了需要爬取的页面,parse方法提供了从网页中提取信息的具体方式,对于提取信息的标准化,在items.py文件中进行定义

通过以上两个文件的简单代码,就定义了一个最基本的爬虫,功能是从miRTarBase数据库中提取human miRNA的靶基因信息。在命令行中输入命令:

python -m scrapy crawl MirSpider -o test.csv

可以启动该爬虫

直接将结果输出为标准的csv格式,由于采用了异步io的下载模式,爬取速度非常的快。

通过这个简单的示例,可以看出框架对于开发的便利性,我们只需要专注于编写从网页提取信息的核心代码就可以了,大大提高了开发效率,而且由于框架本身的优越性能,开发出的爬虫执行效率也很高。




Scrapy数据流是由执行的核心引擎(engine)控制,流程是这样的:


1、爬虫引擎获得初始请求开始抓取。

2、爬虫引擎开始请求调度程序,并准备对下一次的请求进行抓取。

3、爬虫调度器返回下一个请求给爬虫引擎。

4、引擎请求发送到下载器,通过下载中间件下载网络数据。

5、一旦下载器完成页面下载,将下载结果返回给爬虫引擎。

6、引擎将下载器的响应通过中间件返回给爬虫进行处理。

7、爬虫处理响应,并通过中间件返回处理后的items,以及新的请求给引擎。

8、引擎发送处理后的items到项目管道,然后把处理结果返回给调度器,调度器计划处理下一个请求抓取。

9、重复该过程(继续步骤1),直到爬取完所有的url请求。


下面单独介绍scrapy各个组件,

爬虫引擎(ENGINE)

爬虫引擎负责控制各个组件之间的数据流,当某些操作触发事件后都是通过engine来处理。

调度器

调度接收来engine的请求并将请求放入队列中,并通过事件返回给engine。

下载器

通过engine请求下载网络数据并将结果响应给engine。

Spider

Spider发出请求,并处理engine返回给它下载器响应数据,以items和规则内的数据请求(urls)返回给engine。

管道项目(item pipeline)

负责处理engine返回spider解析后的数据,并且将数据持久化,例如将数据存入数据库或者文件。

下载中间件

下载中间件是engine和下载器交互组件,以钩子(插件)的形式存在,可以代替接收请求、处理数据的下载以及将结果响应给engine。

spider中间件

spider中间件是engine和spider之间的交互组件,以钩子(插件)的形式存在,可以代替处理response以及返回给engine items及新的请求集。

五、爬虫实例

使用python 网络爬虫抽取网易音乐热歌热评数据


1.热门榜页网页

飙升榜

https://music.163.com/discover/toplist?id=19723756 

新歌榜

https://music.163.com/discover/toplist?id=3779629 

原创榜

https://music.163.com/discover/toplist?id=2884035 

热歌榜

https://music.163.com/discover/toplist?id=3778678 

2.歌曲明细页评论网页

​https://music.163.com/song?id=865632948 ​

3.歌曲文件地址数据信息接口

​https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=​

4.爬虫源码实例

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import re

import urllib.request

import urllib.error

import urllib.parse

import json


from Crypto.Cipher import AES

import base64


import requests,pprint,json


url_page = 'http://music.163.com/discover/toplist?id=19723756'  #  飙升榜url 下载网页分析数据

urllib.request.urlretrieve(url_page,'toplist.html')

url_page1 = 'https://music.163.com/discover/artist'


#调式网易音乐页面js得到的加密

params    = ""

_i        = "l6Brr86UeZ6C3Bsw" # 默认使用此字符串

encSecKey = "7ca9b5ba8b13044f47ed74c388df912ac84758122acbedc64111f2ac83232b01d3ce16f7195a39c7e064b4c0240b5c1d52624dc13c22ec820d76dfe32db43e496aeacced5be3ca9108c78a85bb389f1edf8d8c9fced02024ba9490401b4ce062cc50764d0a24294e07bb229271391b5a3640e924ee1ed15435dc6e288f1fa873"

def cryptjscomplex(text):

    BS = AES.block_size

    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode('utf-8')

    unpad = lambda s: s[0:-s[-1]]

    key = bytes(_i, encoding="utf-8")

    text = text.encode("utf-8")

    IV = b'0102030405060708'

    cipher = AES.new(key, mode=AES.MODE_CBC, IV=IV)

    # cipher2 = AES.new(key, mode=AES.MODE_CBC, IV=IV)  # 加密和解密,cipher对象只能用一次

    # print(text)

    encrypted = pad(text)

    # print(encrypted)

    encrypted = cipher.encrypt(encrypted)

    # print(encrypted)

    encrypted = base64.b64encode(encrypted).decode("utf-8")

    # print("第二次加密结果", encrypted)

    return encrypted


def cryptjscomplexbase(text):

    BS = AES.block_size

    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode('utf-8')

    unpad = lambda s: s[0:-s[-1]]

    key = b'0CoJUm6Qyw8W8jud'

    text = text.encode("utf-8")

    IV = b'0102030405060708'

    cipher = AES.new(key, mode=AES.MODE_CBC, IV=IV)

    # cipher2 = AES.new(key, mode=AES.MODE_CBC, IV=IV)  # 加密和解密,cipher对象只能用一次

    # print(text)

    encrypted = pad(text)

    # print(encrypted)

    encrypted = cipher.encrypt(encrypted)

    # print(encrypted)

    encrypted = base64.b64encode(encrypted).decode("utf-8")

    # print("第一次加密结果", encrypted)

    return encrypted


# 获得parms参数值

def getparams(text):

    return cryptjscomplex(

        cryptjscomplexbase(text),)


def gethotSong(model):  # 获取歌曲名称和id


    # url1 = 'http://music.163.com/discover/toplist?id=19723756'  # 飙升榜

    # url2 = 'http://music.163.com/discover/toplist?id=3779629'   # 新歌榜url

    # url3 = 'http://music.163.com/discover/toplist?id=2884035'   # 原创歌榜ur

    # url  = 'http://music.163.com/discover/toplist?id=3778678'   # 热歌榜url

    url = model["url"]

    typename = model["typename"]


    header = {  

        'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'

    }

    request = urllib.request.Request(url=url, headers=header)

    html = urllib.request.urlopen(request).read().decode('utf8')  

    html = str(html)  

    pat1 = r'<ul class="f-hide"><li><a href="/song\?id=\d*?">.*</a></li></ul>'  

    result = re.compile(pat1).findall(html)

    # print(len(result))

    result = result[0]  


    pat2 = r'<li><a href="/song\?id=\d*?">(.*?)</a></li>'  

    pat3 = r'<li><a href="/song\?id=(\d*?)">.*?</a></li>'  

    hot_song_name = re.compile(pat2).findall(result)  

    hot_song_id = re.compile(pat3).findall(result)  

    return hot_song_name, hot_song_id,typename


def gethotComments(hot_song_name, hot_song_id):

    url = 'http://music.163.com/weapi/v1/resource/comments/R_SO_4_' + hot_song_id + '?csrf_token='  

    header = {  

        'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'

    }

    #通过页面手动获取参数

    data1 = {

        'params': 'zC7fzWBKxxsm6TZ3PiRjd056g9iGHtbtc8vjTpBXshKIboaPnUyAXKze+KNi9QiEz/IieyRnZfNztp7yvTFyBXOlVQP/JdYNZw2+GRQDg7grOR2ZjroqoOU2z0TNhy+qDHKSV8ZXOnxUF93w3DA51ADDQHB0IngL+v6N8KthdVZeZBe0d3EsUFS8ZJltNRUJ',

        'encSecKey': '4801507e42c326dfc6b50539395a4fe417594f7cf122cf3d061d1447372ba3aa804541a8ae3b3811c081eb0f2b71827850af59af411a10a1795f7a16a5189d163bc9f67b3d1907f5e6fac652f7ef66e5a1f12d6949be851fcf4f39a0c2379580a040dc53b306d5c807bf313cc0e8f39bf7d35de691c497cda1d436b808549acc'}


    data = {

        'params': 'tn3BOnrm4yHwP8/rNO67PXkdFsIZr1GxkQwludtNY5XPY781W82g3aiHhY+bd4quT7p6EH25qBqfLFdsxCMl0CI73mfflrOUFbK6vGE4g4tW9tfNiHhJucks1/wEsO/RaxWNo2JwQ1KmvO5pAMGYeg==',

        'encSecKey': '9f9ff771dbf2a8de2091e6e90da84fa20231b2c4c17e1830ce41a0e9128e71568b9968ae9944f6ff5cf58b711805200a1a586a7682f2500b98751c43866957975c9ff0092555efb27d558243da6f7331bdb80e12f560ccf9dcc46d05a66707b5e007ad3bbf2937c89b17339083d7dd4dc4099f5ad0b2686293e6d941e7f09559'

    }

    postdata  = urllib.parse.urlencode(data).encode('utf8')  

    request   = urllib.request.Request(url, headers=header, data=postdata)

    reponse   = urllib.request.urlopen(request).read().decode('utf8')

    json_dict = json.loads(reponse)  

    hot_commit = json_dict['hotComments']  

    # 获取歌曲文件URL


    song_id_,song_id, song_time,song_url =gethotsongurl(hot_song_id)

    # print(song_id_,song_id,song_time,song_url)

    num = 0

    fhandle = open('./song_comments', 'a', encoding='utf-8')  #a 追加

    fhandle.write(hot_song_name + ':' + '\n')

    #写入歌曲文件URL

    if(song_url==None):

        # print("vip")

        fhandle.write("VIP歌曲无法下载"+ '\n')

    else:


        fhandle.write("歌曲地址" + ':' +song_url+ '\n')



    for item in hot_commit:

        num += 1

        fhandle.write(str(num) + '.' + item['content'] + '\n')

    fhandle.write('\n==============================================\n\n')

    fhandle.close()

    #下载音乐文件

def gethotsongfile(hot_song_id):

    hotsongurl = hot_song_id

    print(hotsongurl)

    # 搜索指定歌曲文件


def gethotsongurl(song_id_in):

    song_url='https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=' #歌曲名称

    header = {  

        'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'

    }

    text='{"ids":["%s"],"level":"standard","encodeType":"aac","csrf_token":""}'%(song_id_in)

    # ids: JSON.stringify([this.cw8o.id]),

    # level: DEFAULT_LEVEL,

    # encodeType: DEFAULT_ENCODETYPE

    params = (

        ('csrf_token', ''),

    )

    data = {

        'params': getparams(text),

        'encSecKey': encSecKey

    }

    response = requests.post(song_url,headers=header,params=params,data=data)

    # print(response.status_code)

    # resjson=json.loads(response.text)

    # print(resjson)

    # pprint.pprint(response.json())

    # print(json.loads(response.text))

    json_dict=json.loads(response.text)

    song_id_  =None

    song_time =None

    song_url  =None

    for item in json_dict['data']:

        song_id   = item['id']

        song_time = item['time']

        song_url  = item['url']

        song_id_  = song_id_in

        # print(item['id'])

        # print(item['time'])

        # print(item['url'])

    return song_id_,song_id, song_time,song_url

    #下载歌词

def gethotsonglyric(hot_song_id):

    hotsongurl = hot_song_id

    print(hotsongurl)


if __name__ == '__main__':

    # gethotsongurl("1992051395")

    urls=[

        {'url':'http://music.163.com/discover/toplist?id=19723756','typename':'飙升'},

        {'url':'http://music.163.com/discover/toplist?id=3779629' ,'typename':'新歌'},

        {'url':'http://music.163.com/discover/toplist?id=2884035' ,'typename':'原创'},

        {'url':'http://music.163.com/discover/toplist?id=3778678' ,'typename':'热歌'}

        ]


    for url in urls:

        print(url)

        print(url["url"])

        print(url["typename"])

        # hot_song_name, hot_song_id,typename  = gethotSong(url)  # 获取歌曲名称和id


        # num = 0

        # while num < len(hot_song_name):  # 保存热评

        #     print('正在抓取%s第%d首歌曲热评...' % (typename,num + 1))

        #     gethotComments(hot_song_name[num], hot_song_id[num])

        #     print('第%d首歌曲热评抓取成功' % (num + 1))

        #     num += 1


六、附言


网络请求工具

网络请求库:通用

​​urllib​​网络库 (stdlib)。

requests几乎是最流行的网络请求库。

grab网络库(基于 pycurl)。

pycurl网络库(基于 libcurl)。

urllib3具有线程安全连接池、文件发布支持、健全友好等的 Python HTTP 库。

httplib2小型、快速的 HTTP 客户端库。具有持久连接、缓存和 Google App Engine 支持。

RoboBrowser一个简单的 Pythonic 库,用于在没有独立 Web 浏览器的情况下浏览 Web。

MechanicalSoup用于自动与网站交互的 Python 库。

mechanize有状态的程序化网页浏览。

socket底层网络接口 (stdlib)。

Unirest for Python是一组轻量级的 HTTP 库,支持多种语言。

hyper的 HTTP/2 客户端。

PySocks更新和积极维护的 SocksiPy 版本,具有错误修复和额外功能。作为插座模块的直接替代品。

网络请求工具:异步

treq之类的请求。

aiohttp的 http 客户端/服务器 (PEP-3156)。

网络请求工具:底层

dpkt快速、简单的数据包创建/解析,具有基本 TCP/IP 协议的定义。

pyOpenSSL一个围绕 OpenSSL 库的 Python 包装器。

tlslite-ng纯 python 中的 TLS 实现。

scapy强大的基于 Python 的交互式数据包操作程序和库。

impacket对网络协议数据包的低级编程访问。

网页抓取

网页抓取:框架

grab网络抓取框架(基于 pycurl/multicurl)。

scrapy网络抓取框架(基于 Twisted)。

pyspider一个强大的爬取系统。

cola一个分布式爬虫框架。

ruia基于 asyncio 的异步 Python 3.6+网页抓取微框架。

ioweb基于 gevent 和 lxml 的网页抓取框架。

autoscraper一个智能、自动、轻量级的网络爬虫。

frontera一个可扩展的网络爬虫框架。

网页抓取:工具

portia的可视化抓取。

restkit的 HTTP 资源工具包。它允许您轻松访问 HTTP 资源并围绕它构建对象。

requests-html

ScrapydWeb集群管理的全功能 Web UI,支持 Scrapy 日志分析&可视化、自动打包、定时任务、邮件通知等。

Starbelly是一个用户友好且高度可配置的网络爬虫前端。

Gerapy基于 Scrapy, Scrapyd, Django、Vue.js 的分布式爬虫管理框架。

网页抓取:绕过保护

cloudscraper绕过 Cloudflare 的反机器人页面的 Python 模块。

HTML/XML

HTML/XML:通用

lxml有效的 HTML/XML 处理库,支持 XPATH。

cssselect使用带有 CSS 选择器的 DOM 树。

pyquery使用类 jQuery 选择器的 DOM 树。

BeautifulSoup慢速 HTML/XMl 处理库,纯 Python 编写。

html5lib根据 WHATWG 规范构建 HTML/XML 文档的 DOM。该规范用于所有现代浏览器。

feedparser解析 RSS/ATOM 提要。

MarkupSafe为 Python 实现 XML/HTML/XHTML 标记安全字符串。

xmltodict使用 XML 感觉就像使用 JSON。

xhtml2pdf到 PDF 转换器。

untangle将 XML 文档转换为 Python 对象以便于访问。

hodor围绕 lxml 和 cssselect 的配置驱动包装器。

chopper使用相应 CSS 规则从 HTML 页面中提取部分并保留正确 HTML 的工具。

selectolax绑定到 Modest 引擎(带有 CSS 选择器的快速 HTML5 解析器)。

parsel允许您使用 XPath 或 CSS 选择器从 XML/HTML 文档中提取数据。

html5-parser用于 python 的基于 C 的快速 HTML5 解析。

gazpacho一个简单、快速、现代的网络抓取库。

HTML/XML:消毒

Bleach的清理(需要 html5lib)。

sanitize为混乱的数据世界带来理智。

HTML/XML:元数据

extruct用于从 HTML 标记中提取嵌入元数据的库。

文本处理

用于解析和操作纯文本的库。

文本处理:通用

difflib(Python 标准库)计算增量的助手。

Levenshtein快速计算 Levenshtein 距离和字符串相似度。

fuzzywuzzy模糊字符串匹配。

esmre正则表达式加速器。

ftfy自动减少 Unicode 文本的损坏和更一致。

文本处理:音译

unidecode文本的 ASCII 音译库。

文本处理:字符编码

uniout打印可读字符而不是转义字符串。

chardet兼容的字符编码检测器。

xpinyin一个将汉字(汉字)翻译成拼音(拼音)的库。

pangu.py和字母数字的间距文本。

cchardet是高速通用字符编码检测器,绑定到 uchardet。

文本处理:Slugify

awesome-slugify一个可以保存 unicode 的 Python slugify 库。

python-slugify一个将 unicode 转换为 ASCII 的 Python slugify 库。

unicode-slugify生成 unicode slug 的 slugifier。

pytils处理俄语字符串的简单工具(包括 pytils.translit.slugify)。

文本处理:通用解析器

PLY用于 Python 的 lex 和 yacc 解析工具的实现。

pyparsing用于生成解析器的通用框架。

文本处理:人名

python-nameparser将人名解析成各自的组成部分。

文本处理:电话号码

电话号码解析、格式化、存储和验证国际电话号码。

文本处理:用户代理字符串

HTTP 代理解析器代理解析器。

uap-python的 Python 实现。

python-user-agents浏览器用户代理解析器。

fake-useragent用户代理字符串伪造者,基于浏览器的世界统计数据。

user_agent用户代理数据生成器。

文本处理:robots.txt

reppy适用于 Python 的现代 robots.txt 解析器。

文本处理:日期和时间

dateutil对标准 Python 日期时间功能的有用扩展。

dateparser用于人类可读日期的 python 解析器。

ciso8601将 ISO 8601 或 RFC 3339 日期时间字符串转换为 Python 日期时间对象。

文本处理: 价格和货币

price-parser一个用于从原始文本字符串中提取价格和货币的小型库。

结构化格式

用于解析和操作特定文本格式的库。

结构化格式:通用

tablib、CSV、JSON、YAML 格式的表格数据集模块。

texttract从任何文档、Word、PowerPoint、PDF 等中提取文本。

messytables解析杂乱表格数据的工具。

rows一个通用的、漂亮的表格数据界面,无论格式如何(目前是 CSV、HTML、XLS、TXT)。

结构化格式:Office

python-docx读取、查询和修改 Microsoft Word 2007/2008 docx 文件。

xlwt / xlrd从 Excel 文件中写入和读取数据以及格式化信息。

XlsxWriter用于创建 Excel .xlsx 文件的 Python 模块。

xlwings一个 BSD 许可的库,可以轻松地从 Excel 调用 Python,反之亦然。

openpyxl用于读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件的库。

Marmir采用 Python 数据结构并将它们转换为电子表格。

结构化格式:PDF

PDFMiner从 PDF 文档中提取信息的工具。

PyPDF2一个能够拆分、合并和转换 PDF 页面的库。

ReportLab允许快速创建丰富的 PDF 文档。

pdftables直接从 PDF 文件中提取表格

结构化格式:Markdown

Python-Markdown的 Markdown 的 Python 实现。

Mistune最快且功能齐全的 Markdown 纯 Python 解析器。

markdown2的快速且完整的 Python 实现。

mistletoe在纯 Python 中快速、可扩展且符合规范的 Markdown 解析器。

结构化格式:YAML

PyYAML的 YAML 实现。

结构化格式:CSS

cssutils的 CSS 库。

结构化格式:ATOM/RSS

feedparser通用提要解析器。

结构化格式:SQL

sqlparse一个非验证 SQL 解析器。

结构化格式:HTTP

http-parser中 python 的 HTTP 请求/响应解析器。

httptools解析器的 Python 绑定。

结构化格式:微格式

opengraph解析开放图协议标签的 Python 模块。

结构化格式:可移植的可执行文件

pefile一个多平台模块,用于解析和使用可移植可执行文件(又名 PE)文件。

结构化格式:PSD

psd-tools读取 Adob​​e Photoshop PSD 文件(如 规范中所述/fileformatashtml/PhotoshopFileFormats.htm)) 到 Python 数据结构。

结构化格式:书签文件

bookmarks-parser解析 Firefox/Chrome HTML 书签文件。

序列化

orjson支持数据类和日期时间的快速、正确的 Python JSON 库。

ujson用 C 语言编写的超快速 JSON 解码器和编码器,带有 Python 绑定。

自然语言处理

用于处理人类语言的库。

NLTK用于构建 Python 程序以处理人类语言数据的领先平台。

spacy允许使用最先进的深度学习模型来完成常见的 NLP 任务。

fastai带有免费视频教程 + 活跃论坛社区的深度学习库,lib 的缺点:需要 GPU。

gensim用于主题建模、文档索引和大型语料库相似性检索的库。

Pattern的网络挖掘模块。它具有用于自然语言处理、机器学习等的工具。

TextBlob为深入研究常见的 NLP 任务提供一致的 API。站在 NLTK 和 Pattern 的巨大肩膀上。

jieba中文分词工具。

SnowNLP处理中文文本的库。

loso另一个中文分词库。

genius基于条件随机场的中文片段。

langid.py独立的语言识别系统。

韩语 - 韩语形态学库。

pymorphy2俄语的形态分析器(POS 标记器 + 转换引擎)。

PyPLN用于自然语言处理的分布式管道,用 Python 制作。该项目的目标是创建一种使用 NLTK 处理大型语料库的简单方法,并带有 Web 界面。

langdetect语言检测库到 Python 的端口。

浏览器自动化

浏览器自动化:浏览器

selenium自动化真实浏览器(Chrome、Firefox、Opera、IE)。

Ghost.py的包装器(需要 PyQT)。

Spynner的包装器(需要 PyQT)。

Splinter浏览器模拟器的通用 API (selenium webdrivers, django client, zope)。

Requestium和 Selenium 之间的集成层,用于 Web 操作的自动化。

Splash具有 HTTP API 的轻量级、可编写脚本的浏览器即服务。

pyppeteer无头 chrome/chromium 自动化库(puppeteer 的非官方端口)。

Playwright是一个 Python 库,可通过单个 API 自动化 Chromium、Firefox 和 WebKit 浏览器。

seleniumbase用于 Web/UI 测试 + RPA 的 Python 框架。