【概述】
书名:Python网络爬虫从入门到实践(第2版)
作者:唐松
日期:2021年08月01日
读书用时:1568页,100小时,59个笔记
【读书笔记】
◆ 1.2 网络爬虫是否合法
爬虫协议,行走在法律边缘,触不可及。
>> Robots协议(爬虫协议)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。该协议是国际互联网界通行的道德规范,虽然没有写入法律,但是每一个爬虫都应该遵守这项协议。
携程酒店经理的:三月爬虫高峰期的由来。
>> 因为有大量的大学生五月份交论文,在写论文的时候会选择爬取数据,也就是三月份爬取数据,四月份分析数据,五月份交论文。
◆ 1.3 网络爬虫的基本议题
>> 网络爬虫的流程其实非常简单,主要可以分为三部分:(1)获取网页;(2)解析网页(提取数据);(3)存储数据。
◆ 2.1 搭建Python平台
Anaconda,数据分析专用python工具。
>> 如果你希望成为数据分析师或者商业分析师,爬虫只是方便之后做数据分析,笔者推荐你使用Anaconda,配合着自带的Jupyter Notebook,这会提升你的分析效率。
第三方库,可以看作360杀毒软件,你先杀毒不需要自己写杀毒软件,只需要下载它,使用它完成你的部分需求足以。
>> pip安装第三方库bs4,它可以使用其中的BeautifulSoup解析网页
◆ 2.2 Python使用入门
面向过程编程:好比线性流程写代码,运行逻辑从上到下直接执行,适合临时小需求;
面向函数编程:好比折中组合写代码,封装需要反复多次使用的模块,适合独立的小业务,每个模块之间无联系;
面向对象编程:善用初始化函数self.参数,做数据关联,适合接口测试。
def __init__(self,name,age):
self.name = name
self.age = age
>> 如果各个函数之间独立且无共用的数据,就选用函数式编程;如果各个函数之间有一定的关联性,那么选用面向对象编程比较好。
直接调用:初始化函数直接赋值指向参数;
间接调用:通过self.参数传到类的子函数做二次调用,配上self.就可以在全类中全局调用。
>> 调用被封装的内容时有两种方式:通过对象直接调用和通过self间接调用
继承的原理:通过比对子类的共同属性,然后封装一个父类,子类天然继承父类的所有属性,可以节约代码,不过读起来需要从后向前读。
>> 动物:吃喝拉撒
猫:喵喵叫(猫继承动物的功能)
狗:汪汪叫(狗继承动物的功能)
◆ 2.4 Python实践:基础巩固
搜索引擎的坑:百度搜索,你会发现很多名字不一样,点进去内容却一样的伪答案,而且时间也乱七八糟需要添加检索条件,最坑的是前几个文章都是百度快照;谷歌相比百度的竞价排名,更多的是通过点击率或者收藏浏览指数排名,好处就是广告不多,缺点就是有的时候看不懂英文。
>> 就笔者自己的体验而言,谷歌的有效信息检索速度比百度快,较新的回答很有可能是英文的,但是如果你的英文阅读能力不行,就另当别论了。记得使用谷歌搜索时,找到Stack Overflow网站上的回答可以非常快地解决你的问题。
python基础面试题库
>> Python基础试题
有序序列:列表、元祖。
无序序列:字典。
>> 对字典进行排序是不可能的,只有把字典转换成另一种方式才能排序。字典本身是无序的,但是如列表元组等其他类型是有序的,所以需要用一个元组列表来表示排序的字典。
不可更改对象:字符串、数字、元组;
可变对象:列表、字典。
>> 这是因为在Python中对象有两种,即可更改(mutable)与不可更改(immutable)对象。在Python中,strings字符串、tuples元组和numbers数字是不可更改对象,而list列表、dict字典等是可更改对象。
◆ 第3章 静态网页抓取
>> 第3章 ◄ 静态网页抓取 ►
在网站设计中,纯粹HTML格式的网页通常被称为静态网页,早期的网站一般都是由静态网页制作的。在网络爬虫中,静态网页的数据比较容易获取,因为所有数据都呈现在网页的HTML代码中。相对而言,使用AJAX动态加载网页的数据不一定会出现在HTML代码中,这就给爬虫增加了困难。本章先从简单的静态网页抓取开始介绍,第4章再介绍动态网页抓取。
在静态网页抓取中,有一个强大的Requests库能够让你轻易地发送HTTP请求,这个库功能完善,而且操作非常简单。本章首先介绍如何安装Requests库,然后介绍如何使用Requests库获取响应内容,最后可以通过定制Requests的一些参数来满足我们的需求。
◆ 3.2 获取响应内容
>> 说明如下:
(1)r.text是服务器响应的内容,会自动根据响应头部的字符编码进行解码。
(2)r.encoding是服务器内容使用的文本编码。
(3)r.status_code用于检测响应的状态码,如果返回200,就表示请求成功了;如果返回的是4xx,就表示客户端错误;返回5xx则表示服务器错误响应。我们可以用r.status_code来检测请求是否正确响应。
(4)r.content是字节方式的响应体,会自动解码gzip和deflate编码的响应数据。
(5)r.json()是Requests中内置的JSON解码器。
◆ 3.3 定制Requests
get请求,用paramas传参数;
post请求,用paycloud的json格式和data格式传参数。
>> 在Requests中,你可以直接把这些参数保存在字典中,用params(参数)构建至URL中。
>> 编码为表单形式的数据
◆ 第4章 动态网页抓取
>> 动态网页抓取的两种技术:通过浏览器审查元素解析真实网页地址和使用Selenium模拟浏览器的方法。
◆ 4.1 动态抓取的实例
Ajax异步更新技术:通过在后台与服务器进行少量数据交换实现部分内容的更新,有点:不重复下载数据,时间短,更新部分新数据快。
>> 异步更新技术——AJAX(Asynchronous Javascript And XML,异步JavaScript和XML)。它的价值在于通过在后台与服务器进行少量数据交换就可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下对网页的某部分进行更新。一方面减少了网页重复内容的下载,另一方面节省了流量,因此AJAX得到了广泛使用。
>> 异步更新技术——AJAX(Asynchronous Javascript And XML,异步JavaScript和XML)。它的价值在于通过在后台与服务器进行少量数据交换就可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下对网页的某部分进行更新。一方面减少了网页重复内容的下载,另一方面节省了流量,因此AJAX得到了广泛使用。
ajax案例,博客评论的内容:通过js提取数据加载到源代码中进行展示。
>> 通过JavaScript提取数据加载到源代码进行呈现的。
◆ 4.2 解析真实地址抓取
>> json_string[json_string.find('{'):-2] # 从第一个左大括号提取,最后的两个字符-括号和分号不取
json.loads:把字符串转为json格式。
>> 使用json.loads可以把字符串格式的响应体数据转化为json数据。
◆ 4.3 通过Selenium模拟浏览器抓取
>> find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
>> 加快Selenium的爬取速度。常用的方法有:
(1)控制CSS的加载。
(2)控制图片文件的显示。
(3)控制JavaScript的运行。
>> # 控制css from selenium import webdriver fp = webdriver.FirefoxProfile() fp.set_preference("permissions.default.stylesheet",2) driver = webdriver.Firefox(firefox_profile=fp, executable_path =r'C:\Users\santostang\Desktop\geckodriver.exe') #把上述地址改成你电脑中geckodriver.exe程序的地址 driver.get("Hello world!")
>> 控制css的加载主要用fp = webdriver.FirefoxProfile()这个功能
>> # 限制图片的加载 from selenium import webdriver fp = webdriver.FirefoxProfile() fp.set_preference("permissions.default.image",2) driver = webdriver.Firefox(firefox_profile=fp, executable_path =r'C:\Users\santostang\Desktop\geckodriver.exe') #把上述地址改成你电脑中geckodriver.exe程序的地址 driver.get("Hello world!")
>> # 限制JavaScript的执行 from selenium import webdriver fp = webdriver.FirefoxProfile() fp.set_preference("javascript.enabled", False) driver = webdriver.Firefox(firefox_profile=fp, executable_path =r'C:\Users\santostang\Desktop\geckodriver.exe') #把上述地址改成你电脑中geckodriver.exe程序的地址 driver.get("Hello world!")
◆ 第5章 解析网页
>> 第5章 ◄ 解析网页 ►
我们已经能够使用requests库从网页把整个源代码爬取下来了,接下来需要从每个网页中提取一些数据。本章主要介绍使用3种方法提取网页中的数据,分别是正则表达式、BeautifulSoup和lxml。
3种方法各有千秋,想要快速学习的读者可以先挑选一种自己喜欢的方法学习,3种方法都能够解析网页。你也可以先阅读本章的最后一节,在了解3种方法各自的优缺点后,再选择一种方法开始学习。

>> 本章主要介绍使用3种方法提取网页中的数据,分别是正则表达式、BeautifulSoup和lxml。
◆ 5.1 使用正则表达式解析网页
>> Python正则表达式的3种方法,分别是re.match、re.search和re.findall。
>> r'(.*) are (.*? ) .*’前面的r意思是raw string,代表纯粹的字符串,使用它就不会对引号里面的反斜杠’\’进行特殊处理。
不写r:表达式需要\\\\来匹配\
写上r:表达式需要\\来匹配\
>> 正则表达式如果不用r'…’方法的话,就需要进行“字符串转义”和“正则转义”
>> 

抓取博客主页所有文章标题的Python代码如下:
 import requests import re link = "Santos Tang" headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} r = requests.get(link, headers= headers) html = r.text title_list = re.findall('
◆ 5.2 使用BeautifulSoup解析网页
>> pip install bs4
>> 使用BeautifulSoup(r.text, "lxml")将网页响应体的字符串转化为soup对象,然后就可以使用soup库的功能了。
>> pip install lxml
◆ 第6章 数据存储
>> 第6章 ◄ 数据存储 ►
本章主要介绍将数据存储在文件中和存储在数据库中。当我们完成爬取网页并从网页中提取出数据后,需要把数据保存下来。本章将介绍两种保存数据的方法:
(1)存储在文件中,包括TXT文件和CSV文件。
(2)存储在数据库中,包括MySQL关系数据库和MongoDB数据库。

◆ 6.1 基本存储:存储至TXT或CSV
>> [插图]
r“”是转义字符串的特殊字符,
\左斜杆是原始地址路径,
\\双斜杆是转义后的路径
/右斜杆是防止转义的路径
>> 为了防止对反斜杠的转义,地址还可以斜杠“/”来写,也就是with open ('C:/you/desktop/title.txt', "a+") as f:。
“\t”.join(),可以用来连接多个字符串,因为一般字符串中不会出现tab符号。
>> output = '\t'.join(['name', 'title', 'age', 'gender'])
f.read().spitline()
读取文件内容,按照每一行为一个元素的列表类型返回。
>> result = f.read().splitlines()
>> CSV文件的每一行都用换行符分隔,列与列之间用逗号分隔。
>> import csv with open('test.csv', 'r', encoding='UTF-8') as csvfile: csv_reader = csv.reader(csvfile) for row in csv_reader: print(row) print(row[0])
>> import csv output_list = ['1', '2', '3', '4'] with open('test2.csv', 'a+', encoding='UTF-8', newline='') as csvfile: w = csv.writer(csvfile) w.writerow(output_list)
◆ 6.2 存储至MySQL数据库
关系型数据库,表示以primary key为关联字段把各个独立的表连接起来的数据库,特点体积小、速度快而且免费,非关系型数据库就是把所有数据放在一个数据池里面,修改维护添加删除数据都很慢且难以维护。
>> 由于MySQL关系数据库体积小、速度快而且免费,因此在网络爬虫的数据存储中作为常用的数据库。
>> 创建数据表必须指明每一列数据的名称(column_name)和类别(column_type),正确创建数据表的方法是:
 CREATE TABLE urls( id INT NOT NULL AUTO_INCREMENT, url VARCHAR(1000) NOT NULL, content VARCHAR(4000) NOT NULL, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) );
>> pip install pymysql
◆ 6.3 存储至MongoDB数据库
>> NoSQL泛指非关系型数据库。传统的SQL数据库把数据分隔到各个表中,并用关系联系起来。但是随着Web 2.0网站的兴起,大数据量、高并发环境下的MySQL扩展性差,大数据下读取,写入压力大,表结构更改困难,使得MySQL应用开发越来越复杂。相比之下,NoSQL自诞生之初就容易扩展,数据之间无关系,具有非常高的读写性能。
>> MongoDB是一款基于分布式文件存储的数据库,本身就是为Web应用提供可扩展的高性能数据存储。因此,使用MongoDB存储网络爬虫的数据再好不过了。
>> 使用MongoDB的程序启动方式。打开MongoDB安装文件夹,默认为C:\Program Files\MongoDB\Server\4.0 \bin,找到mongod.exe双击打开(注意有d的为启动程序)。启动程序后,再运行mongo.exe程序(没有d),如图6-29所示。
>> pip install pymongo
◆ 6.4 总结
爬虫存储数据:
优先txt或者csv;
如果数据量很大,打开文件都会卡顿的时候,建议使用mysql关系型数据库存储;
如果是json格式,可以直接用mango数据库存储。
>> 如果存储的数据不是关系型数据格式,推荐选择MongoDB,甚至可以直接存储爬取的JSON格式数据而不用进行解析。如果是关系型的表格形式,那么可以使用MySQL存储数据。
◆ 第7章 Scrapy框架
>> 第7章 ◄ Scrapy框架 ►
前面几章介绍了使用requests加BeatifulSoup工具来获取网页、解析网页、存储数据,上手比较简单,但是每个功能的代码都要自己实现。本章介绍的Scrapy是一个爬虫框架,它将上述的很多功能都封装进框架里。使用较少的代码就能完成爬虫的工作。
本章首先介绍Scrapy和Requests的对比,然后介绍如何安装Scrapy,如何使用Scrapy进行抓取,Scrapy的注意事项,最后通过Scrapy爬虫实践来实现真正上手。
◆ 7.1 Scrapy是什么
>> Scrapy是一个为了爬取网站数据,提取数据而编写的应用框架。简单来说,它把爬虫的三步:获取网页,解析网页,存储数据都整合成了这个爬虫框架。这样,通过Scrapy实现一个爬虫变得简单了很多。
7.1.1 Scrapy架构
下面的图7-1展示了Scrapy的架构,包括了各个组件,以及数据流的情况(箭头所示)。
>> Scrapy是一个为了爬取网站数据,提取数据而编写的应用框架。简单来说,它把爬虫的三步:获取网页,解析网页,存储数据都整合成了这个爬虫框架。
其实不管是爬虫还是语言的学习,都需要你先碎片化你的需求,分成每一个小步,慢慢深入,学会以后再去优化,再去借鉴别人写好的框架,你会发现眼前一亮;可是越来越熟练以后,你会发现不再喜欢条条框框,于是你又回归强撸代码。
>> 初学者老老实实地用Requests爬取网页,用Selenium获取动态网页,用bs4解析网页,用csv存储网页;从零开始做一个爬虫项目,自己设计抓取策略会让你对爬虫有非常深入地认识。
>> Scrapy优势在于并发性好,在做大批量数据爬虫时简单易用。
◆ 第8章 提升爬虫的速度
>> 第8章 ◄ 提升爬虫的速度 ►
通过前面7章的学习,相信读者已经能够从获取网页、解析网页、存储数据来实现一些基本的爬虫了。从本章开始,我们将进入爬虫的进阶部分,包括第8章到第13章。进阶部分的各章并没有先后顺序,对某一章感兴趣的读者可以直接跳到这章学习。
本章将介绍如何提升爬虫的速度,主要有3种方法:多线程爬虫、多进程爬虫和多协程爬虫。相对于普通的单线程爬虫,使用这3种方法爬虫的速度能实现成倍的提升。