嗨!大家好,我是秃顶的码哥!
这篇文章可以说是C站最全Python爬虫教程了,从软件安装,到实战爬取。不仅案例丰富,还直接上代码解析,能让人更直观的理解每行代码的含义!(文章较长,建议先点赞收藏再观看!)
1.Windows上安装Python3
(1)打开浏览器,访问Python官网(https://www.python.org/)。
(2)鼠标移动至Downloads链接,点击Windows链接。
(3)根据读者的Windows版本(32位或64位),下载相应的Python 3.5版本,如为Windows32位,点击下载Windows x86 executable installer,如果为Windows64位,点击下载Windows x86-64 executable installer。
(4)单击运行文件,勾选Add Python 3.5 to PATH,然后单击Install Now按钮即可完成安装。
在电脑中,通过打开命令提示符(cmd),输入python,出现如图界面,就说明Python环境安装成功。
界面出现提示符>>>就表明进入了Python交互式环境,输入代码按Enter键即可运行Python代码,通过输入exit()并按Enter键,就可以退出Python交互式环境。
2.Mac上安装Python3
Mac中自带了Python 2.7,需在Python官网上安装Python 3.5。Mac中的安装比Windows下更为简单,一直单击“下一步”按钮即可完成。打开终端,输入python3,即可进入Mac的Python 3的交互式环境。
3.Linux上安装Python3
大部分Linux系统电脑内置Python 2和Python 3,通过在终端输入python –version,可以查看当前Python 3的版本。如果需要安装某个特定版本的Python,可以在终端中输入:
sudo apt-get install python3.5
1.1.2 PyCharm安装
安装好Python环境后,读者还需安装一个集成开发环境(IDE),IDE集成了代码编写功能、分析功能、编译功能、调试功能。在这里推荐最智能好用的Python IDE,叫做PyCharm。进入PyCharm的官网(http://www.jetbrains.com/pycharm/),下载社区版即可。
如何使用PyCharm关联Python解释器,让PyCharm可以运行Python代码。
(1)打开PyCharm,在菜单栏中选择:File > Defalut Settings。
(2)单击Project Interpreter,在窗口右方选择Python环境,选择Python 3.5,单击OK按钮,即可关联Python解释器(如下图所示)。
1.2.1 变量
Python中的变量很好理解,例如:
a = 1
这种操作称为赋值,意思为将数值1赋给了变量a。
注意:Python中语句结束不需要已分号结束,变量不需要提前定义。
现在有变量a和变量b,我们可以通过下面代码进行变量a、b值的对换:
a = 4 b = 5 t = a #把a值赋给t变量 a = b #把b值赋给a变量 b = t #把t值赋给b变量 print(a,b) # result 5 4
这种方法类似于将两个杯子中的饮料对换,我们只需多加一个杯子,即可完成饮料的对换工作。
1.2.2 字符串的“加法”和“乘法”
由于Python爬虫的对象大部分为文本,所以字符串的用法尤为重要。在Python中,字符串由双引号或单引号和引号中的字符组成。首先,通过下面代码看看字符串的“加法”:
a = 'I' b = ' love' c = ' Python' print(a + b + c) #字符串相加 # result I love Python
在爬虫代码中,会经常构造URL,例如:在爬取一个网页链接时,只有一部分:/u/9104ebf5e177,这部分链接是无法访问的,还需要http://www.jianshu.com,这时可以通过字符串的“加法”进行合并。
Python的字符串不仅可以相加,也可以乘以一个数字:
a = 'word' print(a*3) #字符串乘法 #result wordwordword
字符串乘以一个数字,意思就是将字符串复制这个数字的份数。
1.2.3 字符串的切片和索引
字符串的切片和索引就是通过string[x],获取字符串的一部分信息:
a = 'I love python' print(a[0]) #取字符串第一个元素 #result I print(a[0:5]) #取字符串第一个到第五个元素 #result I lov print(a[-1]) #取字符串最后一个元素 #result n
通过下图就能清楚的理解字符串的切片和索引:
1.2.4 字符串方法
Python做为面向对象的语言,每个对象都有着相应的方法,字符串也是一样,拥有着多种方法,在这里介绍爬虫中所常用的几种方法。
1.split()方法
a = 'www.baidu.com' print(a.split('.')) # result ['www', 'baidu', 'com']
2.repalce()方法
a = 'There is apples' b = a.replace('is','are') print(b) # result There are apples
这种方法类似文本中的“查找和替换”功能。
3.strip()方法
a = ' python is cool ' print(a.strip()) # result python is cool
strip()方法返回去除两侧(不包括内部)空格的字符串,也可以指定需要去除的字符,将他们列为参数中即可。
4.format()方法
最后,再讲解下好用的字符串格式化符,首先看下代码。
a = '{} is my love'.format('Python') print(a) # result Python is my love
字符串格式化符就像是做选择题,留了空给做题者选择。在爬虫过程中,有些网页链接的部分参数是可变的,这时使用字符串格式化符可以减少代码的使用量。
字符串格式化符演示
1.3.1 函数
“脏活累活交给函数来做”,首先,看看Python中定义函数的方法。
def 函数名(参数1,参数2…):
return ‘结果’
制作一个输入直角边就能计算出直角三角形的面积函数:
**def function(a,b): return '1/2*a*b'** #也可以写出这样 **def function(a,b): print( 1/2*a*b)**
注意:别太纠结区别,用return是返回一个值,而第二个是调用函数执行打印功能。
通过输入function(2,3),便可以调用函数,计算直角边为2和3的直角三角形的面积。
1.3.2 判断语句
在爬虫实战中,也会经常使用判断语句,Python的判断语句格式如下:
if condition: do else: do # 注意:冒号和缩进不要忘记了 # 再看一下多重条件的格式 if condition: do elif condition: do else: do
在平时使用密码时,输入密码正确即可登录,错误时就需要继续输入了。
def count_login(): password = input('password:') if password == '12345': print('输入成功!') else: print('错误,再输入') count_login() count_login()
(1)运行程序,输入密码按Enter键。
(2)如果输入的字符串为12345,则打印“输入成功!”,程序结束。
(3)如果输入的字符串不为12345,则打印“错误,再输入”,继续运行程序,直到输入正确为至。
读者也可以设计的更为有趣,例如:“3次输入失败后,退出程序”等。
1.3.3 循环语句
Python的循环语句包括for循环和while循环,如下代码所示。
#for循环 for item in iterable: do #item表示元素,iterable是集合 for i in range(1,11): print(i) #其结果为依次输出1到10,切记11是不输出的,range为Python内置函数。 #while循环 while condition: do
1.4.1 列表
在爬虫实战中,用的最多的就是列表数据结构,不论是构造出的多个URL,还是爬取到的数据,大多数为列表数据结构。首先,介绍列表的最显著的特征:
(1)列表中的每一个元素都是可变的。
(2)列表的元素都是有序的,也就是说每个元素都有对应的位置(类似字符串的切片索引)。
(3)列表可以容纳所有的对象。
1.4.2 字典
Python的字典数据结构与现实中的字典类似,以键值对(’key’-‘value’)的形式表现出来。本文中只讲解字典的创造,字典的操作在后文中进行详细介绍。
user_info = { 'name':'xiaoming', 'age':'23', 'sex':'man'
1.4.3 元组和集合
在爬虫中,元组和集合很少用到,这里就只做简单的介绍。元组类似与列表,但是元组的元素不能够修改,只能查看,元组的格式如下。
tuple = (1,2,3)
集合的概念类似与数学中的集合。每个集合中的元素是无序的,不可重复的对象,有时,可以通过集合把重复的数据去除掉。
list = ['xiaoming','zhangyun','xiaoming'] set = set(list) print(set) # result {'zhangyun', 'xiaoming'}
1.5.1 打开文件
Python中通过open()函数打开文件,语法如下:
open(name[, mode[, buffering]])
open()函数使用文件名做为唯一的强制参数,然后返回一个文件对象。模式(mode)和缓冲(buffering)是可选参数。在Python的文件操作中,mode参数的输入是有必要的,而buffering使用较少。
1.5.2 读写文件
上小节中有了名为f的类文件对象,那么就可以通过f.write()方法和f.read()方法写入和读取数据。
f = open('C:/Users/Administrator/Desktop/file.txt','w+') f.write('hello world')
这时,在本机上打开file.txt文件,可以看到下图所示的结果。
如果再次运行程序,txt文件中的内容不会继续添加,可以修改模式参数为’r+’,便可一直写入文件。
1.5.3 关闭文件
当完成读写工作后,应该牢记使用close()方法关闭文件。这样可以保证Python进行缓冲的清理(出于效率的考虑而把数据临时存储在内存中)和文件的安全。通过下面代码即可关闭文件。
f = open('C:/Users/Administrator/Desktop/file.txt','r') content = f.read() print(content) f.close()
1.6.1 定义类
类是用来描述具有相同的属性和方法的对象的集合。人可以通过不同的肤色划分不同的种类、食物也有不同的种类、商品也是形形色色,但划分为同一类的物体,他们肯定具有相似的特征和行为方式。
对于同一款自行车而言,他们的组成结构都是一样的:车架、车轮、脚踏等。通过Python可以定义这个自行车的类:
class Bike: compose = ['frame','wheel','pedal']
通过使用class定义一个自行车的类,类中的变量compose称为类的变量,专业术语为类的属性。这样,顾客购买的自行车,组成结构都是一模一样的了。
my_bike = Bike() you_bike = Bike() print(my_bike.compose) print(you_bike.compose) #类的属性都是一样
1.6.2 实例属性
对于同一款自行车来说,有些顾客买回来后会改造下,加一个篓子可以放东西等等。
class Bike: compose = ['frame','wheel','pedal'] my_bike = Bike() my_bike.other = 'basket' print(my_bike.other) #实例属性
结果下图所示。
1.6.3 实例方法
读者是否还记得字符串的format()方法。方法就是函数,方法是对实例进行使用的,所以又叫实例方法。对于自行车而言,它的方法就是骑行。
class Bike: compose = ['frame','wheel','pedal'] def use(self): print('you are riding') my_bike = Bike() my_bike.use()
结果下图所示。
1.6.4 类的继承
随着时代的变迁,越来越多的共享单车出现了,新的共享单车和原来的组成结构类似,但多了付费的功能。
class Bike: compose = ['frame','wheel','pedal'] def __init__(self): self.other = 'basket' #定义实例的属性 def use(self,time): print('you ride {}m'.format(time*100)) class Share_bike(Bike): def cost(self,hour): print('you spent {}'.format(hour*2)) bike = Share_bike() print(bike.other) bike.cost(2)
类的继承
2.1.1 网络连接
网络连接像是在自助饮料售货机上购买饮料一样:购买者只需选择所需饮料,投入硬币(或纸币),自助饮料售货机就会弹出相应的商品。网络连接也正是如此,如下图所示,本机电脑(购买者)带着请求头和消息体(硬币和所需饮料)向服务器(自助饮料售货机)发起一次Requests请求(购买),相应的服务器(自助饮料售货机)会返回本机电脑相应的HTML文件作为Response(相应的商品)。
2.1.2 爬虫原理
了解网络连接的基本原理后,爬虫原理就很好理解了。网络连接需要电脑一次Requests请求和服务器端的Response回应。爬虫也是需要二件事:
(1)模拟电脑对服务器发起Requests请求。
(2)接收服务器端的Response的内容并解析提取所需信息。
但互联网网页错综复杂,一次的请求和回应不能够批量获取网页的数据,这时就需要设计爬虫的流程,本书中主要运用到两种爬虫所需的流程:多页面和跨页面爬虫流程。
多页面网页爬虫流程:
跨页面网页爬虫流程:
2.2.1 Chrome浏览器的安装
Chrome浏览器的安装与普通软件安装一样,不需要进行任何的配置。在搜索引擎中输入Chrome,点击下载安装即可。安装完成后,打开,会出现下图的错误。
这是因为Chrome浏览器默认的搜索引擎为Google搜索引擎,国内的网络是无法打开的。解决的办法为:
(1)打开Chrom浏览器的设置。
(2)在“启动时”栏目中,选择打开特定网页或一组网页。
(3)点击“设置网页”链接,输入读者常用的搜索引擎或网页,单击“确定”按钮。
(4)退出Chrome浏览器,打开后便是设置过后的网页。操作效果如下图
Chrome浏览器设置网页(一)
Chrome浏览器设置网页(二)
Chrome浏览器设置网页(三)
2.2.2 网页构造
现在任意打开一个网页(http://bj.xiaozhu.com/),标右击空白处,在弹出的快捷菜单中选择“检查”命令,可以看到网页的代码。
分析这个图,上半部分为HTML文件,下部分为CSS样式,用标签的就是JavaScript。用户浏览的网页就是浏览器渲染后的结果,浏览器就像翻译官,把HTML、CSS和JavaScript进行翻译得到用户使用的网页界面。
2.2.3 查询网页信息
打开网页(http://bj.xiaozhu.com/),右击网页空白处,从快捷菜单中选择“查看网页源代码”命令,即可查看该网页的源代码,如图所示。
3.1.1 Python第三方库的概念
Python之所以强大并逐渐流行起来,一部分原因要归功于Python强大的第三方库。这样用户就不用了解底层的思想,用最少的代码写出最多的功能。
没使用第三库的话,用户就得从原始材料开始,一步步制造下去,一个车轮子都不知道要造多久呢?而使用第三方库就不一样,车轮子和车身都已经制造好了,拼接一下就可以使用了(有些车直接就给用户了)。这种拿来即用的就是Python第三方库
3.1.2 Python第三方库的安装方法
1.在PyCharm中安装
(1)打开PyCharm,在菜单栏中选择:File > Defalut Settings。
(2)单击左侧Project Interpreter选项,在窗口右方选择Python环境。
(3)单击“+”号按钮添加第三方库。
(4)输入第三方库名称,选中需下载的库。
(5)勾选Install to users site复选框,然后单击Install Package按钮。操作过程如图。
2.在pip中安装
在安装Python后,pip也会同时进行安装,我们可以在命令行cmd中输入:
pip --version
如果出现下面提示,则表示pip成功安装:
pip 9.0.1 from D:\anaconda\lib\site-packages (python 3.6)
在pip成功安装之后,在命令行cmd中输入以下代码即可下载第三方库:
pip3 install packagename #packagename为安装库的名称,在这里输入pip3 install beautifulsoup4即可下载beautifulsoup4库了。
注意:如果为Python2,pip3改为pip
安装完后有提示:
Successfully installed packagename
3.下载whl文件
有时候前二者方法安装会出现问题,可能是由于网络原因,也可能是包的依赖关系而引起的的,这时候就需要手动安装,这种方法最稳妥。
(1)进入http://www.lfd.uci.edu/~gohlke/pythonlibs/,搜索lxml库,点击下载到本地,如图所示。
(2)到命令行输入:
pip3 install wheel
(3)等待执行完成,成功后在命令行输入:
cd D:\python\ku #后面为下载whl文件的路径
(4)最后,在命令行输入:
pip3 install lxml-3.7.2-cp35-cp35m-win_amd64.whl # lxml-3.7.2-cp35-cp35m-win_amd64.whl是你下载的文件的完整路径名
这样就可以下载库到本地了,通过whl文件,可以自动安装依赖的包。
3.1.3 Python第三方库的使用方法
当成功安装Python第三方库后,就可通过下面方法导入并使用第三方库了:
import xxxx #xxxx为导入的库名,例如import requests
注意:导入BeautifulSoup库的写法为:from bs4 import BeautifulSoup。
3.2.1 Requests库
Requests库官方文档指出:让HTTP服务人类。细心的读者就会发现,Requests库的作用就是请求网站获取网页数据的。让我们从简单的实例开始,讲解Requests库的使用方法。
import requests res = requests.get('http://bj.xiaozhu.com/')#网站为小猪短租网北京地区网址 print(res) #pycharm中返回结果为<Response [200]>,说明请求网址成功,若为404,400则请求网址失败。 print(res.text) #pycharm部分结果如图
3.2.2 BeautifulSoup库
BeautifulSoup库是一个非常流行的Python模块。通过BeautifulSoup库可以轻松的解析Requests库请求的网页,并把网页源代码解析为Soup文档,以便过滤提取数据。
import requests from bs4 import BeautifulSoup headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36' } res = requests.get('http://bj.xiaozhu.com/',headers=headers) soup = BeautifulSoup(res.text,'html.parser') #对返回的结果进行解析 print(soup.prettify())
3.2.3 Lxml库
Lxml库是基于libxm12这一个XML解析库的Python封装。该模块使用C语言编写,解析速度比BeautifulSoup更快,具体的使用方法在之后的章节中讲解。
3.3.1 爬虫思路分析
1)爬取小猪短租北京地区短租房13页的信息,通过手动浏览,以下为前四页的网址:
http://bj.xiaozhu.com/
http://bj.xiaozhu.com/search-duanzufang-p2-0/
http://bj.xiaozhu.com/search-duanzufang-p3-0/
http://bj.xiaozhu.com/search-duanzufang-p4-0/
只需更改p后面的数字即可,以此来构造出13页的网址。
(2)本次爬虫在详细页中进行,故先需爬取进入详细页的网址链接,进而爬取数据。
(3)需要爬取的信息有:
标题、地址、价格、房东名称、
房东性别已经房东头像的链接,
如图所示。
3.3.2 爬虫代码及分析
代码如下:
01 from bs4 import BeautifulSoup 02 import requests 03 import time #导入相应的库文件 04 05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/53.0.2785.143 Safari/537.36' 08 } #加入请求头 09 10 def judgment_sex(class_name): #定义判断用户性别的函数 11 if class_name == ['member_ico1']: 12 return '女' 13 else: 14 return '男' 15 16 def get_links(url): #定义获取详细页url的函数 17 wb_data = requests.get(url,headers=headers) 18 soup = BeautifulSoup(wb_data.text,'lxml') 19 links = soup.select('#page_list > ul > li > a') #links为url列表 20 for link in links: 21 href = link.get("href") 22 get_info(href) #循环出的url,依次调用get_info函数 23 24 def get_info(url): #定义获取网页信息的函数 25 wb_data = requests.get(url,headers=headers) 26 soup = BeautifulSoup(wb_data.text,'lxml') 27 tittles = soup.select('div.pho_info > h4') 28 addresses = soup.select('span.pr5') 29 prices = soup.select('#pricePart > div.day_l > span') 30 imgs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > a > img') 31 names = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a') 32 sexs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > div') 33 for tittle, address, price, img, name, sex in zip(tittles,addresses,prices,imgs,names,sexs): 34 data = { 35 'tittle':tittle.get_text().strip(), 36 'address':address.get_text().strip(), 37 'price':price.get_text(), 38 'img':img.get("src"), 39 'name':name.get_text(), 40 'sex':judgment_sex(sex.get("class")) 41 } 42 print(data) #获取信息并通过字典的信息打印 43 44 if __name__ == '__main__': #为程序的主入口 45 urls = ['http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format(number) for number in 46 range(1,14)] #构造多页url 47 for single_url in urls: 48 get_links(single_url) #循环调用get_links函数 49 time.sleep(2) #睡眠2秒
运行的部分结果如图所示。
代码分析:
(1)
01 from bs4 import BeautifulSoup 02 import requests 03 import time #导入相应的库文件
导入程序需要的库,Requests库用于请求网页获取网页数据。BeautifulSoup用于解析网页数据。time库的sleep()方法可以让程序暂停。
(2)
05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/53.0.2785.143 Safari/537.36' 08 } #加入请求头
通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。
(3)
16 def get_links(url): #定义获取详细页url的函数 17 wb_data = requests.get(url,headers=headers) 18 soup = BeautifulSoup(wb_data.text,'lxml') 19 links = soup.select('#page_list > ul > li > a') #links为url列表 20 for link in links: 21 href = link.get("href") 22 get_info(href) #循环出的url,依次调用get_info函数
定义了get_links()函数,用于获取进入详细页的链接。
(4)
24 def get_info(url): #定义获取网页信息的函数 25 wb_data = requests.get(url,headers=headers) 26 soup = BeautifulSoup(wb_data.text,'lxml') 27 tittles = soup.select('div.pho_info > h4') 28 addresses = soup.select('span.pr5') 29 prices = soup.select('#pricePart > div.day_l > span') 30 imgs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > a > img') 31 names = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a') 32 sexs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > div') 33 for tittle, address, price, img, name, sex in zip(tittles,addresses,prices,imgs,names,sexs): 34 data = { 35 'tittle':tittle.get_text().strip(), 36 'address':address.get_text().strip(), 37 'price':price.get_text(), 38 'img':img.get("src"), 39 'name':name.get_text(), 40 'sex':judgment_sex(sex.get("class")) 41 } 42 print(data) #获取信息并通过字典的信息打印
定义get_info()函数,用于获取网页信息并输出信息。
(5)
10 def judgment_sex(class_name): 11 if class_name == ['member_ico1']: 12 return '女' 13 else: 14 return '男'
定义judgment_sex()函数,用于判断房东的性别。
(6)
44 if __name__ == '__main__': #为程序的主入口 45 urls = ['http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format(number) for number in 46 range(1,14)] #构造多页url 47 for single_url in urls: 48 get_links(single_url) #循环调用get_links函数 49 time.sleep(2) #睡眠2秒
为程序的主入口。
3.4.1 爬虫思路分析
(1)爬取的内容为酷狗榜单中酷狗top500的音乐信息,如图所示。
(2)网页版酷狗不能手动翻页,进行下一步的浏览。但通过观察第一页的URL:
http://www.kugou.com/yy/rank/home/1-8888.html
这里尝试把数字1换为数字2,进行浏览,恰好返回的是第2页的信息(下图)。进行多次尝试,发现更换不同数字即为不同页面,故只需更改home/后面的数字即可。由于每页显示的为22首歌曲,所以总共需要23个URL。
(3)需要爬取的信息有:排名情况、歌手、歌曲名和歌曲时间,如下图所示。
3.4.2 爬虫代码及分析
代码如下:
01 import requests 02 from bs4 import BeautifulSoup 03 import time #导入相应的库文件 04 05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/56.0.2924.87 Safari/537.36' 08 } #加入请求头 09 10 def get_info(url): #定义获取信息的函数 11 wb_data = requests.get(url,headers=headers) 12 soup = BeautifulSoup(wb_data.text,'lxml') 13 ranks = soup.select('span.pc_temp_num') 14 titles = soup.select('div.pc_temp_songlist > ul > li > a') 15 times = soup.select('span.pc_temp_tips_r > span') 16 for rank,title,time in zip(ranks,titles,times): 17 data = { 18 'rank':rank.get_text().strip(), 19 'singer':title.get_text().split('-')[0], 20 'song':title.get_text().split('-')[0], #通过split获取歌手和歌曲信息 21 'time':time.get_text().strip() 22 } 23 print(data) 获取爬虫信息并按字典格式打印 24 25 if __name__ == '__main__': #程序主入口 26 urls = ['http://www.kugou.com/yy/rank/home/{}-8888.html'.format(str(i)) for i in 27 range(1,24)] #构造多页url 28 for url in urls: 29 get_info(url) #循环调用get_info函数 time.sleep(1) #睡眠1秒
运行的部分结果如图所示:
代码分析:
(1)
01 import requests 02 from bs4 import BeautifulSoup 03 import time #导入相应的库文件
导入程序需要的库,
Requests库用于请求网页
获取网页数据。
BeautifulSoup用于解析网
页数据。time库的sleep()
方法可以让程序暂停。
(2)
05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/56.0.2924.87 Safari/537.36' 08 } #加入请求头
通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。
(3)
10 def get_info(url): #定义获取信息的函数 11 wb_data = requests.get(url,headers=headers) 12 soup = BeautifulSoup(wb_data.text,'lxml') 13 ranks = soup.select('span.pc_temp_num') 14 titles = soup.select('div.pc_temp_songlist > ul > li > a') 15 times = soup.select('span.pc_temp_tips_r > span') 16 for rank,title,time in zip(ranks,titles,times): 17 data = { 18 'rank':rank.get_text().strip(), 19 'singer':title.get_text().split('-')[0], 20 'song':title.get_text().split('-')[0], #通过split获取歌手和歌曲信息 21 'time':time.get_text().strip() 22 } 23 print(data) 获取爬虫信息并按字典格式打印
定义get_info()函数,用于获取网页信息并输出信息。
(4)
25 if __name__ == '__main__': #程序主入口 26 urls = ['http://www.kugou.com/yy/rank/home/{}-8888.html'.format(str(i)) for i in 27 range(1,24)] #构造多页url 28 for url in urls: 29 get_info(url) #循环调用get_info函数 time.sleep(1) #睡眠1秒
为程序的主入口。
4.1.1 一般字符
正则表达式的一般字符有3个,见表格。
4.1.2 预定义字符集
正则表达式预定义字符集有6个,参见表。
4.1.3 数量词
正则中的数量词列表参见表。
4.1.4 边界匹配
边界匹配的关键符号参见表。
4.2.1 search()函数
re模块的search()函数匹配并提取第一个符合规律的内容,返回一个正则表达式对象。search()函数的语法为:
re.match(pattern, string, flags=0) (1)pattern为匹配的正则表达式。 (2)string为要匹配的字符串。 (3)flags为标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 可以看出,search()函数返回的是正则表达式对象,通过正则表达式匹配到了“1”这个字符串,可以通过下面代码返回匹配到的字符串: import re a = 'one1two2three3' infos = re.search('\d+',a) print(infos.group()) #group方法获取信息
4.2.2 sub()函数
re模块提供了sub()函数用于替换字符串中的匹配项,sub()函数的语法为:
re.sub(pattern, repl, string, count=0, flags=0)
(1)pattern为匹配的正则表达式。
(2)repl为替换的字符串。
(3)string为要被查找替换的原始字符串。
(4)counts为模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
(5)flags为标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
4.2.3 findall()函数
findall()函数匹配所有符合规律的内容,并以列表的形式返回结果,例如上文中的’one1two2three3’,通过search()函数只能匹配到第一个符合规律的结果,通过findall可以返回字符串所有的数字。
import re a = 'one1two2three3' infos = re.findall('\d+',a) print(infos)
结果如图所示。
4.2.4 re模块修饰符
re模块中包含一些可选标志修饰符来控制匹配的模式,见表。
在爬虫中,re.S是最常用的修饰符,它能够换行匹配。
4.3.1 爬虫思路分析
(1)爬取的内容为斗破苍穹小说网全文小说,如图所示。
2)爬取所有章节的信息,通过手动浏览,以下为前五章的网址:
http://www.doupoxs.com/doupocangqiong/2.html
http://www.doupoxs.com/doupocangqiong/5.html
http://www.doupoxs.com/doupocangqiong/6.html
http://www.doupoxs.com/doupocangqiong/7.html
http://www.doupoxs.com/doupocangqiong/8.html
第一章与第二章没有明显规律,但第二章后的URL规律很明显,通过数字递加来分页。手动输入http://www.doupoxs.com/doupocangqiong/3.html,会发现是404界面。
所以具体的思路为:从第一章开始构造URL,中间有404错误就跳过不爬取。
(3)需要爬取的信息为全文文字信息,如下图所示。
4)运用Python对文件的操作,把爬取的信息存储在本地的txt文本中。
4.3.2 爬虫代码及分析
代码如下:
01 import requests 02 import re 03 import time #导入相应的库文件 04 05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/56.0.2924.87 Safari/537.36' 08 } #加入请求头 09 10 f = open('C:/Users/LP/Desktop/doupo.txt','a+') #新建txt文档,追加的方式 11 12 def get_info(url): #定义获取信息的函数 13 res = requests.get(url,headers=headers) 14 if res.status_code == 200: #判断请求码是否为200 15 contents = re.findall('<p>(.*?)</p>',res.content.decode('utf-8'),re.S) 16 for content in contents: 17 f.write(content+'\n') #正则获取数据写入txt文件中 18 else: 19 pass #不为200就pass掉 20 21 if __name__ == '__main__': #程序主入口 22 urls = ['http://www.doupoxs.com/doupocangqiong/{}.html'.format(str(i)) for i in 23 range(2,1665)] #构造多页url 24 for url in urls: 25 get_info(url) #循环调用get_info函数 26 time.sleep(1) #睡眠1秒 f.close() #关闭txt文件
运行的结果保存在电脑,文件名为doupo的文档中,如图
代码分析:
(1)
01 import requests 02 import re 03 import time #导入相应的库文件
导入程序需要的库,Requests库用于请求网页获取网页数据。运用正则表达式不需要用BeautifulSoup解析网页数据,而是使用Python中的re模块匹配正则表达式。time库的sleep()方法可以让程序暂停。
(2)
05 headers = { 06 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 07 Gecko) Chrome/56.0.2924.87 Safari/537.36' 08 } #加入请求头
通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。
(3)
10 f = open('C:/Users/LP/Desktop/doupo.txt','a+') #新建txt文档,追加的方式
新建TXT文档,用于存储小说全文信息。
(3)
12 def get_info(url): #定义获取信息的函数 13 res = requests.get(url,headers=headers) 14 if res.status_code == 200: #判断请求码是否为200 15 contents = re.findall('<p>(.*?)</p>',res.content.decode('utf-8'),re.S) 16 for content in contents: 17 f.write(content+'\n') #正则获取数据写入txt文件中 18 else: 19 pass #不为200就pass掉
定义get_info()函数,用于获取网页信息并存储信息。传入URL后,进行请求。通过正则表达式定位到小说文本内容,并写入TXT文档中。
(4)
21 if __name__ == '__main__': #程序主入口 22 urls = ['http://www.doupoxs.com/doupocangqiong/{}.html'.format(str(i)) for i in 23 range(2,1665)] #构造多页url 24 for url in urls: 25 get_info(url) #循环调用get_info函数 26 time.sleep(1) #睡眠1秒
为程序的主入口。通过对网页URL的观察,通过列表的推导式构造所有小说URL,并依次调用get_info()函数,time.sleep(1)的意思每循环一次,让程序暂停1秒,防止请求网页频率过快而导致爬虫失败。
4.4.1 爬虫思路分析4.4.2 爬虫代码及分析
(1)爬取的内容为糗事百科文字内容中的信息,如图所示。
(2)爬取糗事百科文字35页的信息,通过手动浏览,以下为前四页的网址:
http://www.qiushibaike.com/text/
http://www.qiushibaike.com/text/page/2/?s=4964629
http://www.qiushibaike.com/text/page/3/?s=4964629
http://www.qiushibaike.com/text/page/4/?s=4964629
这里的?s=4964629应该只是从Cookies里提取的用户标识,去掉后依然能打开网页。然后把第一页的网址改为http://www.qiushibaike.com/text/page/1/也能正常浏览,故只需更改page后面的数字即可,以此来构造出35页的网址。
(3)需要爬取的信息有:用户ID,用户等级,用户性别,发表段子文字信息,好笑数量和评论数量,如图4.15所示。
(4)运用Python对文件的操作,把爬取的信息存储在本地的txt文本中。
4.4.2 爬虫代码及分析
代码如下:
01 import requests 02 import re #导入相应的库文件 03 04 headers = { 05 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 06 Gecko) Chrome/53.0.2785.143 Safari/537.36' 07 } #加入请求头 08 09 info_lists = [] #初始化列表,用于装入爬虫信息 10 11 def judgment_sex(class_name): #定义获取用户性别的函数 12 if class_name == 'womenIcon': 13 return '女' 14 else: 15 return '男' 16 17 def get_info(url): 18 res = requests.get(url) 19 ids = re.findall('<h2>(.*?)</h2>',res.text,re.S) 20 levels = re.findall('<div class="articleGender \D+Icon">(.*?)</div>',res.text,re.S) 21 sexs = re.findall('<div class="articleGender (.*?)">',res.text,re.S) 22 contents = re.findall('<div class="content">.*?<span>(.*?)</span>',res.text,re.S) 23 laughs = re.findall('<span class="stats-vote"><i class="number">(\d+)</i>',res.text,re.S) 24 comments = re.findall('<i class="number">(\d+)</i> 评论',res.text,re.S) 25 for id,level,sex,content,laugh,comment in zip(ids,levels,sexs,contents,laughs,comments): 26 info = { 27 'id':id, 28 'level':level, 29 'sex':judgment_sex(sex), #调用judgment_sex函数 30 'content':content, 31 'laugh':laugh, 32 'comment':comment 33 } 34 info_lists.append(info) #获取数据,并append到列表中 35 36 if __name__ == '__main__': #程序主入口 37 urls = ['http://www.qiushibaike.com/text/page/{}/'.format(str(i)) for i in range(1,36)] 38 for url in urls: 39 get_info(url) #循环调用获取爬虫信息的函数 40 for info_list in info_lists: 41 f = open('C:/Users/Administrator//Desktop/qiushi.text','a+') #遍历列表,创建txt文件 42 try: 43 f.write(info_list['id']+'\n') 44 f.write(info_list['level'] + '\n') 45 f.write(info_list['sex'] + '\n') 46 f.write(info_list['content'] + '\n') 47 f.write(info_list['laugh'] + '\n') 48 f.write(info_list['comment'] + '\n\n') 49 f.close() #写入数据到txt中 50 except UnicodeEncodeError: 51 pass #pass掉编码错误
运行的结果保存在电脑,文件名为qiushi的文档中,如图所示。
代码分析:
(1)
01 import requests 02 import re #导入相应的库文件
导入程序需要的库,Requests库用于请求网页获取网页数据。运用正则表达式不需要用BeautifulSoup解析网页数据,而是使用Python中的re模块匹配正则表达式。
(2)
04 headers = { 05 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 06 Gecko) Chrome/53.0.2785.143 Safari/537.36' 07 } #加入请求头
通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。
(3)
17 def get_info(url): 18 res = requests.get(url) 19 ids = re.findall('<h2>(.*?)</h2>',res.text,re.S) 20 levels = re.findall('<div class="articleGender \D+Icon">(.*?)</div>',res.text,re.S) 21 sexs = re.findall('<div class="articleGender (.*?)">',res.text,re.S) 22 contents = re.findall('<div class="content">.*?<span>(.*?)</span>',res.text,re.S) 23 laughs = re.findall('<span class="stats-vote"><i class="number">(\d+)</i>',res.text,re.S) 24 comments = re.findall('<i class="number">(\d+)</i> 评论',res.text,re.S) 25 for id,level,sex,content,laugh,comment in zip(ids,levels,sexs,contents,laughs,comments): 26 info = { 27 'id':id, 28 'level':level, 29 'sex':judgment_sex(sex), #调用judgment_sex函数 30 'content':content, 31 'laugh':laugh, 32 'comment':comment 33 } 34 info_lists.append(info) #获取数据,并append到列表中
定义get_info()函数,用于获取网页信息并把数据传入到info_lists列表中。传入URL后,进行请求。
(4)第9行
09 info_lists = [] #初始化列表,用于装入爬虫信息
定义了一个info_lists空列表,用于存放爬取的信息,每条数据为字典结构。
(5)11~15行
11 def judgment_sex(class_name): 12 if class_name == 'womenIcon': 13 return '女' 14 else: 15 return '男'
定义judgment_sex()函数,用于判断用户的性别。
(6)
36 if __name__ == '__main__': #程序主入口 37 urls = ['http://www.qiushibaike.com/text/page/{}/'.format(str(i)) for i in range(1,36)] 38 for url in urls: 39 get_info(url) #循环调用获取爬虫信息的函数 40 for info_list in info_lists: 41 f = open('C:/Users/Administrator//Desktop/qiushi.text','a+') #遍历列表,创建txt文件 42 try: 43 f.write(info_list['id']+'\n') 44 f.write(info_list['level'] + '\n') 45 f.write(info_list['sex'] + '\n') 46 f.write(info_list['content'] + '\n') 47 f.write(info_list['laugh'] + '\n') 48 f.write(info_list['comment'] + '\n\n') 49 f.close() #写入数据到txt中 50 except UnicodeEncodeError: 51 pass #pass掉编码错误
为程序的主入口。通过对网页URL的观察,通过列表的推导式构造35个URL,并依次调用get_info()函数,循环遍历info_lists列表,存入到文件名qiushi的TXT文档中。
1.Mac系统
安装Lxml之前需要安装Command Line Tools,其中一种安装方法为,在终端输入:
xcode-select –install
如果安装成功会提示Successful的字样。如果安装失败,还可以使用brew或者下载dmg的方式进行安装,具体方法请自行百度。
然后就可以安装Lxml库了,在终端输入:
pip3 install lxml
这样就完成了Mac系统下Lxml库的安装。
2.Linux系统
Linux系统安装Lxml库最为简单,在终端输入:
sudo apt-get install Python 3-lxml
这样就完成了Linux系统下Lxml库的安装。
注意:Windows7下安装Lxml库已在前文中讲解。
5.1.2 Lxml库使用
1.修正HTML代码
2.读取HTML文件
3.解析HTML文件
5.2.1 节点关系
1.父节点
2.子节点
3.同胞节点
4.先辈节点
5.后代节点
5.2.2 节点选择
XPath使用路径表达式在XML文档中选取节点。节点是通过沿着路径或者step来选取的,见表。
5.2.3 使用技巧
在爬虫实战中,Xpath路径可以通过
Chrome复制得到,如图所示。
(1)鼠标定位到想要提取的数据位置,右击,从快捷菜单中选择“检查”命令。
(2)在网页源代码中右击所选元素。
(3)选择Copy Xpath命令。这时便能得到:
//*[@id="qiushi_tag_118732380"]/div[1]/a[2]/h2
通过代码即可得到用户id:
import requests from lxml import etree headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36' } url = 'http://www.qiushibaike.com/text/' res = requests.get(url,headers=headers) selector = etree.HTML(res.text) id = selector.xpath('//*[@id="qiushi_tag_118732380"]/div[1]/a[2]/h2/text()') print(id)
注意:通过/text()可以获取标签中的文字信息。
结果为:
['王卫英']
5.2.4 性能对比
前文中提到Lxml库的解析速度快,但是“口说无凭”,本小节将会通过代码对正则表达式、BeautifulSoup、Lxml进行性能对比。
5.3.1 数据存储到CSV
前文中爬取的数据要么打印到屏幕上,要么存储到TXT文档中,这些格式并不利于数据的存储。想想,读者平时是用什么来存储数据的?大部分读者可能是使用微软公司的Excel来储存数据,大规模的数据则是使用数据库(下文将详细讲解)。CSV是存储表格数据的常用文件格式,Excel和很多应用都支持CSV格式,因为它很简洁。
5.3.2 爬虫思路分析
(1)爬取的内容为豆瓣图书top250的信息,如图所示。
(2)爬取豆瓣图书top250的10页信息,通过手动浏览,以下为前4页的网址:
https://book.douban.com/top250
https://book.douban.com/top250?start=25
https://book.douban.com/top250?start=50
https://book.douban.com/top250?start=75
然后把第1页的网址改为https://book.douban.com/top250?start=0也能正常浏览,故只需更改start=后面的数字即可,以此来构造出10页的网址。
(3)需要爬取的信息有:书名、书本的URL链接、作者、出版社、出版时间,书本价格、评分和评价,如图所示。
(4)运用Python中的csv库,把爬取的信息存储在本地的CSV文本中。
5.3.3 爬虫代码及分析
代码如下:
01 01 from lxml import etree 02 02 import requests 03 03 import csv #导入相应的库文件 04 05 fp = open('C://Users/LP/Desktop/doubanbook.csv','wt',newline='',encoding='utf-8')#创建csv 06 writer = csv.writer(fp) 07 writer.writerow(('name', 'url', 'author', 'publisher', 'date', 'price', 'rate', 'comment'))#写入header 08 09 urls = ['https://book.douban.com/top250?start={}'.format(str(i)) for i in range(0,250,25)]#构造urls 10 11 headers = { 12 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 13 Gecko) Chrome/55.0.2883.87 Safari/537.36' 14 } #加入请求头 15 16 for url in urls: 17 html = requests.get(url,headers=headers) 18 selector = etree.HTML(html.text) 19 infos = selector.xpath('//tr[@class="item"]') #取大标签,以此循环 20 for info in infos: 21 name = info.xpath('td/div/a/@title')[0] 22 url = info.xpath('td/div/a/@href')[0] 23 book_infos = info.xpath('td/p/text()')[0] 24 author = book_infos.split('/')[0] 25 publisher = book_infos.split('/')[-3] 26 date = book_infos.split('/')[-2] 27 price = book_infos.split('/')[-1] 28 rate = info.xpath('td/div/span[2]/text()')[0] 29 comments = info.xpath('td/p/span/text()') 30 comment = comments[0] if len(comments) != 0 else "空" 31 writer.writerow((name,url,author,publisher,date,price,rate,comment)) #写入数据 32 33 fp.close() #关闭csv文件
运行的结果保存在电脑中,文件名为doubanbook的CSV文件中,通过Excel打开会出现乱码错误,如图所示。
可以通过记事本打开,另存为修改编码为UTF-8,便不会出现乱码问题,如图所示。
这时,通过Excel打开,便不会出现乱码问题了,如图所示。
代码分析:
(1)
01 01 from lxml import etree 02 02 import requests 03 03 import csv #导入相应的库文件
导入程序需要的库,Requests库用于请求网页获取网页数据。Lxml库永远解析提取数据。csv库用于存储数据。
(2)
05 fp = open('C://Users/LP/Desktop/doubanbook.csv','wt',newline='',encoding='utf-8')#创建csv 06 writer = csv.writer(fp) 07 writer.writerow(('name', 'url', 'author', 'publisher', 'date', 'price', 'rate', 'comment'))#写入header
创建CSV文件,并且写入表头信息。
(3)
09 urls = ['https://book.douban.com/top250?start={}'.format(str(i)) for i in range(0,250,25)]#构造urls
构造所有的URL链接。
(4)
11 headers = { 12 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like 13 Gecko) Chrome/55.0.2883.87 Safari/537.36' 14 } #加入请求头
通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。
(5)
16 for url in urls: 17 html = requests.get(url,headers=headers) 18 selector = etree.HTML(html.text) 19 infos = selector.xpath('//tr[@class="item"]') #取大标签,以此循环 20 for info in infos: 21 name = info.xpath('td/div/a/@title')[0] 22 url = info.xpath('td/div/a/@href')[0] 23 book_infos = info.xpath('td/p/text()')[0] 24 author = book_infos.split('/')[0] 25 publisher = book_infos.split('/')[-3] 26 date = book_infos.split('/')[-2] 27 price = book_infos.split('/')[-1] 28 rate = info.xpath('td/div/span[2]/text()')[0] 29 comments = info.xpath('td/p/span/text()') 30 comment = comments[0] if len(comments) != 0 else "空" 31 writer.writerow((name,url,author,publisher,date,price,rate,comment)) #写入数据
首先,循环URL,根据“先抓大后抓小,寻找循环点”的原则,找到每条信息的标签,如图所示。
然后在爬取详细信息,最后写入到CSV文件中。
(6)
33 fp.close() #关闭csv文件
关闭文件。
5.4.1 数据存储到Excel
使用Python的第三方库xlwt,可将数据写入到Excel中,通过pip进行安装即可:
pip3 install xlwt
执行结果如图所示。
通过下面代码,便可以将数据写入Excel中:
import xlwt #导入写入excel的库文件 book = xlwt.Workbook(encoding='utf-8') #创建工作簿 sheet = book.add_sheet('Sheet1') #创建工作表 sheet.write(0,0,'python') #在相应单元格写入数据 sheet.write(1,1,'love') book.save('test.xls') #保存到文件
运行后,可在本地找到该Excel文件,结果如图所示。
(1)导入xlwt库。
(2)通过Workbook()方法创建一个工作簿。
(3)创建一个名字为Sheet1的工作表。
(4)写入数据,可以看出第一个和第二个参数为Excel表格的单元格位置,第三个为写入内容。
(5)保存到文件中。
5.4.2 爬虫思路分析
(1)爬取的内容为起点中文网的全部作品信息(http://a.qidian.com/),如图所示。
(2)爬取起点中文网的全部作品信息前100页,通过手动浏览,下面为第二页的网址:
http://a.qidian.com/?size=-1&sign=-1&tag=-1&chanId=-1&subCateId=-1&orderId=&update=-1&page=2&month=-1&style=1&action=-1&vip=-1
猜想这些字段是用来控制作品分类的,我们爬取的为全部作品,依次删掉一些参数检查,发现改为http://a.qidian.com/?page=2,也可访问相同的信息,通过多页检验,证明了合理性,以此来构造100页URL。
(3)需要爬取的信息有:小说名、作者ID、小说类型、完成情况、摘要和字数,如图5.27所示。
(4)运用xlwt库,把爬取的信息存储在本地的Excel表格中。
5.4.3 爬虫代码及分析
代码如下:
01 import xlwt 02 import requests 03 from lxml import etree 04 import time #导入相应的库文件 05 06 all_info_list = [] #初始化列表,存入爬虫数据 07 08 def get_info(url): #定义获取爬虫信息的函数 09 html = requests.get(url) 10 selector = etree.HTML(html.text) 11 infos = selector.xpath('//ul[@class="all-img-list cf"]/li') #定位大标签,以此循环 12 for info in infos: 13 title = info.xpath('div[2]/h4/a/text()')[0] 14 author = info.xpath('div[2]/p[1]/a[1]/text()')[0] 15 style_1 = info.xpath('div[2]/p[1]/a[2]/text()')[0] 16 style_2 = info.xpath('div[2]/p[1]/a[3]/text()')[0] 17 style = style_1+'·'+style_2 18 complete = info.xpath('div[2]/p[1]/span/text()')[0] 19 introduce = info.xpath('div[2]/p[2]/text()')[0].strip() 20 word = info.xpath('div[2]/p[3]/span/text()')[0].strip('万字') 21 info_list = [title,author,style,complete,introduce,word] 22 all_info_list.append(info_list) #把数据存入列表 23 time.sleep(1) #睡眠1秒 24 25 if __name__ == '__main__': #程序主入口 26 urls = ['http://a.qidian.com/?page={}'.format(str(i)) for i in range(1,29655)] 27 for url in urls: 28 get_info(url) 29 header = ['title','author','style','complete','introduce','word'] #定义表头 30 book = xlwt.Workbook(encoding='utf-8') #创建工作簿 31 sheet = book.add_sheet('Sheet1') #创建工资表 32 for h in range(len(header)): 33 sheet.write(0, h, header[h]) #写入表头 34 i = 1 35 for list in all_info_list: 36 j = 0 37 for data in list: 38 sheet.write(i, j, data) 39 j += 1 40 i += 1 #写入爬虫数据 41 book.save('xiaoshuo.xls') #保存文件
运行后,存入数据到Excel表格中,如图所示。
代码分析:
(1)
01 import xlwt 02 import requests 03 from lxml import etree 04 import time #导入相应的库文件
导入程序所需要的库,
xlwt用于写入数据到
Excel文件中,requests库
用于请求网页。lxml库用于
解析提取数据。time库的
sleep()方法可以让程序暂停。
(2)
06 all_info_list = [] #初始化列表,存入爬虫数据
定义all_info_list列表,用于存储爬取的数据。
(3)
08 def get_info(url): #定义获取爬虫信息的函数 09 html = requests.get(url) 10 selector = etree.HTML(html.text) 11 infos = selector.xpath('//ul[@class="all-img-list cf"]/li') #定位大标签,以此循环 12 for info in infos: 13 title = info.xpath('div[2]/h4/a/text()')[0] 14 author = info.xpath('div[2]/p[1]/a[1]/text()')[0] 15 style_1 = info.xpath('div[2]/p[1]/a[2]/text()')[0] 16 style_2 = info.xpath('div[2]/p[1]/a[3]/text()')[0] 17 style = style_1+'·'+style_2 18 complete = info.xpath('div[2]/p[1]/span/text()')[0] 19 introduce = info.xpath('div[2]/p[2]/text()')[0].strip() 20 word = info.xpath('div[2]/p[3]/span/text()')[0].strip('万字') 21 info_list = [title,author,style,complete,introduce,word] 22 all_info_list.append(info_list) #把数据存入列表 23 time.sleep(1) #睡眠1秒
定义获取爬虫信息的函数:用于获取小说信息,并把小说信息以列表的形式存储到all_info_list列表中。
注意:列表中有列表,这样存储是为了方便写入到Excel中。
(5)
25 if __name__ == '__main__': #程序主入口 26 urls = ['http://a.qidian.com/?page={}'.format(str(i)) for i in range(1,29655)] 27 for url in urls: 28 get_info(url) 29 header = ['title','author','style','complete','introduce','word'] #定义表头 30 book = xlwt.Workbook(encoding='utf-8') #创建工作簿 31 sheet = book.add_sheet('Sheet1') #创建工资表 32 for h in range(len(header)): 33 sheet.write(0, h, header[h]) #写入表头 34 i = 1 35 for list in all_info_list: 36 j = 0 37 for data in list: 38 sheet.write(i, j, data) 39 j += 1 40 i += 1 #写入爬虫数据 41 book.save('xiaoshuo.xls') #保存文件
函数主入口,构造100页URL,依次调用函数获取小说信息,最后把信息写入到Excel文件中。
6.1.1 API概述
现在API是越来越多,一些“成熟”的网站都会为自己构造API为使用者或开发者提供使用,例如可以通过百度地图API进行查询路线,定位坐标等。通过一些音乐API查询歌手信息、歌词下载等。通过翻译API进行实时翻译多国语言。甚至可以花一点费用去APIStore(http://apistore.baidu.com/)上购买API服务,如图所示。
6.1.2 API使用方法
API用一套非常标准的规则生成数据,而且生成的数据也是按照非常标准的方式组织的。因为规则很标准,所以一些简单、基本的规则很容易学,可以快速地掌握API的用法。但并非所有的API使用都很简单,有些API的规则却是很多且复杂,建议在使用前认真观看该API的帮助文档。
6.1.3 API验证
有些简单的API不需要验证操作,但现在大部分的API是需要用户提交验证的。提交验证主要是为了计算API调用的费用,这种常见于付费的API,例如某天气查询API,需购买获得apikey作为验证才能调用API
6.2.1 JSON解析库
Python中有解析JSON数据的标准库,可以通过下面代码来使用它:
import json
不同于其他Python的解析库,JSON解析库并不是把JSON数据解析为JSON对象或者JSON节点,而是把JSON数据转换为字典,JSON数组转换成列表,JSON字符串转换为Python字符串。这样,便可以轻松的对JSON数据进行操作了。
6.2.2 斯必克API调用
读者平时会使用翻译软件来翻译英文,本节就教读者使用斯必克API打造自己的翻译小工具。
(1)打开APIStore(http://apistore.baidu.com/)。
(2)在产品分类中点选“更多”,如图所示。
(3)选择“翻译”,找到斯必克API,如下图所示。
(4)进去后会提示登入百度账号,不需登入账号,删掉即可,选择API阅读帮助文档和示例,如下图所示。
通过下面代码便可以实时翻译了:
import requests import json #导入库 word = input('请输入中文: ') #输入中文 url = 'http://howtospeak.org:443/api/e2c?user_key=dfcacb6404295f9ed9e430f67b641a8e ¬rans=0&text={}'.format(word) res = requests.get(url) json_data = json.loads(res.text) english_word = json_data['english'] print(english_word) #解析提取英文单词
运行程序后,读者输入想翻译的中文句子,按Enter键便能输出英文翻译,如图所示。
6.2.3 百度地图API调用
地理位置信息是爬虫实战中有趣的一部分,本小节将通过百度地图的API,把地点名换算为经纬度,通过下面代码便可调用百度地图API。
import requests address = input('请输入地点:') par = {'address': address, 'key': 'cb649a25c1f81c1451adbeca73623251'} #get请求参数 url = 'http://restapi.amap.com/v3/geocode/geo' res = requests.get(url, par) print(res.text)
运行程序后,输入地点名,按Enter键就可以返回结果,如图所示。
6.3.1 图片爬取方法
图片爬取一般有两种方法:
(1)第1种是通过URLlib.request中的URLretrieve模块,这种方法的使用如下:
urlretrieve(url,path)
URL为图片链接,path为图片下载到本地的地址。
(2)但是有时第1种方法爬取图片会报错,就必须使用第2种方法,就是请求图片链接,再存入到文件中。
6.3.2 爬虫思路分析
(1)爬取Pexels(https://www.pexels.com/)上的图片,该网站提供海量共享图片素材,图片质量很高,而且因为共享,可以免费用于个人和商业用途,如图所示。
(2)由于该网站为外文网,需输入英文,通过手动输入几个关键字,可发现网址的变化如下:
https://www.pexels.com/search/book/
https://www.pexels.com/search/office/
https://www.pexels.com/search/basketball/
通过这种规律来构造URL。
(3)通过斯必克API进行中文转英文,这样,可通过输入中文来构造URL。
(4)运用Python爬取图片的第二种方法,进行图片的下载。
6.4.1 地图的绘制
个人BDP是一款在线版数据可视化分析工具,操作很简单,不需要提供代码,也支持地图的可视化。
(1)在浏览器中打开个人BDP网址(https://me.bdp.cn/home.html),进行登录(读者注册后方可登录),登入后界面如图。
(2)单击选择“工作表”,然后单击选择“上传数据”按钮,如图所示。
(3)上传的数据支持Excel和CSV格式,上传具有经纬度信息的Excel表格,如图所示。
(4)在“工作表”中,单击“新建图表”链接按钮,然后单击“地图图表”选项,最后单击“确定”按钮,如下图所示。
(5)选择经纬度的字段,坐标系,单击“确定”按钮,如图所示。
(6)把数据拖放至图层,选择第一个图表类型,用address字段调整符号颜色,用counts字段调整符号大小,进行图表的命名,如图所示。
(7)返回,可在仪表盘中找到完成的地图图表,也可导出为图片,如图所示。
6.4.2 爬取思路分析
(1)爬取的内容为糗事百科热门中用户的地址信息。
(2)糗事百科的URL构造上文中有讲解,这里不再重述。
(3)本次爬虫在详细页中进行,故先需爬取进入详细页的网址链接,进而爬取数据。
(4)通过百度地图API进行用户位置的经纬度转换。
(5)运用Python中的csv库,把爬取的信息存储在本地的CSV文本中。
7.1.1 NoSQL概述
NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。NoSQL数据库有四大分类,分别为:键值存储数据库(如Redis)、列存储数据库(如Hbase)、文档型数据库(如MongoDB)、图形数据库(如Graph)。
7.1.2 MongoDB安装
1.MongoDB数据库安装
2.Pymongo第三方库安装
3.Mongodb可视化管理工具Robomongo安装
7.1.3 MongoDB使用
本书以爬虫实战为主,不会讲解过多的数据库操作知识,读者可自行学习。本小节主要讲解使用Pymongo第三方库在Python环境中创建数据库和集合以及插入爬虫得到的数据,最后讲解如何把集合导出为CSV文件。
初学者可能不太理解数据库和集合的概念,数据库和集合很类似于Excel文件和其中的表格,一个Excel文件可有多个表格,一个数据库也可有多个集合。
7.2.1 关系型数据库概述
关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。也就是说,数据属性与其他数据是有关联的。
7.2.2 MySQL安装
1.MySQL数据库安装
2.Pymysql第三方库安装
3.MySQL可视化管理工具SQLyog安装
7.2.3 MySQL使用
在MySQL的安装路径bin文件夹下打开命令行窗口,输入以下命令,便可建立数据库:
create database mydb;
通过“use mydb”进入mydb数据库,通过下面命令建立数据表:
CREATE TABLE students (
name char(5),
sex char(1),
grade int
)ENGINE INNODB DEFAULT CHARSET=utf8 ;#创建数据表
也可以在SQLyog中进行数据库和数据表的建立,在SQLyog中查看新建好的数据库和数据表
7.3.1 爬虫思路分析
(1)爬取的内容为豆瓣音乐top250的信息,如图所示。
(2)爬取豆瓣图书top250的10页信息,通过手动浏览,以下为前4页的网址:
https://music.douban.com/top250
https://music.douban.com/top250?start=25
https://music.douban.com/top250?start=50
https://music.douban.com/top250?start=75
然后把第一页的网址改为https://music.douban.com/top250?start=0也能正常浏览,故只需更改start=后面的数字即可,以此来构造出10页的网址。
(3)因为详细页的信息更为丰富,本次爬虫在详细页中进行,故先需爬取进入详细页的网址链接,进而爬取数据。
(4)需要爬取的信息有:歌曲名、表演者、流派、发行时间、出版者、评分,如下图所示。
(5)运用Python中的pymongo库,把爬取的信息存储在MongoDB数据库中。
7.4.1 爬虫思路分析
(1)爬取的内容为豆瓣电影top250的信息。
(2)爬取豆瓣图书top250的10页信息,通过手动浏览,以下为前4页的网址:
https://movie.douban.com/top250
https://movie.douban.com/top250?start=25
https://movie.douban.com/top250?start=50
https://movie.douban.com/top250?start=75
然后把第一页的网址改为https://movie.douban.com/top250?start=0也能正常浏览,故只需更改start=后面的数字即可,以此来构造出10页的网址。
(3)因为详细页的信息更为丰富,本次爬虫在详细页中进行,故先需爬取进入详细页的网址链接,进而爬取数据。
(4)需要爬取的信息有:电影名称、导演、主演、类型、制片国家、上映时间、片长和评分,如图所示。
(5)运用Python中的pymysql库,把爬取的信息存储在MySQL数据库中。
8.1.1 多线程和多进程概述
当计算机运行程序时,就会创建包含有代码和状态的进程。这些进程会通过计算机的一个或多个CPU执行。不过,同一时刻每个CPU只会执行一个进程,然后在不同进程间快速切换,这样就给人以多个程序同时运行的感觉。同理,在一个进程中,程序的执行也是在不同线程间进行切换的,每个线程执行程序的不同部分。
8.1.2 多进程使用方法
Python进行多进程爬虫使用了multiprocessing库,本书使用multiprocessing库的进程池方法进行多进程爬虫,使用方法如下代码:
01 from multiprocessing import Pool 02 pool = Pool(processes=4) #创建进程池 03 pool.map(func,iterable[,chunksize])
(1)第一行用于导入multiprocessing库的Pool模块。
(2)第二行用于创建进程池,processes参数为设置进程的个数。
(3)第三行利用map()函数进行进程运行,func参数为需运行的函数,在爬虫实战中,为爬虫函数。iterable为迭代参数,在爬虫实战中,可为多个URL列表进行迭代。
8.1.3 性能对比
多进程爬虫速度要远优于串行爬虫,但是“口说无凭”,本小节将会通过代码对串行爬虫和多进程爬虫进行性能对比。
8.2.1 爬虫思路分析
(1)爬取的内容为简书“首页投稿”热评文章的信息(http://www.jianshu.com/c/bDHhpK),如图所示。
(2)当手动浏览该网页时,会发现没有分页的界面,而是可以一直浏览下去,这说明该网页使用了异步加载。
打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,如图所示。
通过鼠标手动下滑浏览网页,会发现Network选项卡中会加载一些文件,如图所示。
打开第1个加载文件,在Headers部分可以看到请求的URL
在Response部分可看到返回的内容就是文章信息
通过关注,只需修改page后面的数字即可返回出不同的页面,以此来构造URL,本次共爬取1万个URL。
(3)需要爬取的信息有:用户ID、文章发表日期、文章标题、文章内容、浏览量、评论数、点赞数和打赏数,如图所示。
(4)运用多进程爬虫方法以及Python中的pymongo库,进行多进程爬虫,并把爬取的信息存储在MongoDB数据库中。
8.3.1 爬虫思路分析
(1)爬取的内容为转转网二手市场的所有商品信息,这里就要先爬取各个类目的URL。
(2)在进行大规模数据爬取时,需认真观察页面结构,通过观察,二手手机号码结构与其他商品页面结构不相同,故人为剔除其URL。
(3)通过前文中的方法来构造分页URL,但每个类目的页数不同,在这里人为设置100页,如果网页没数据了,可通过程序的方法跳过不抓取。
(4)在商品详细页爬取数据,需要爬取的信息有:商品信息、商品价格、区域、浏览量和商品欲购数量。
(5)运用多进程爬虫方法以及Python中的pymongo库,进行多进程爬虫,并把爬取的信息存储在MongoDB数据库中。
9.1.1 异步加载技术概述
异步加载技术(AJAX),即异步JavaScript和XML,是指一种创建交互式网页应用的网页开发技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
9.1.2 异步加载网页示例
前文中介绍的简书“首页投稿”热评文章的信息,通过下滑进行浏览,并没有分页的信息,而是一直浏览下去,而网址信息并没有改变。传统的网页不可能一次性加载如此庞大的信息,通过分析可判断该网页使用了异步加载技术。
读者也可以通过查看数据是否在网页源代码中来判断网页是否采用了异步加载技术,如图所示,下滑后的简书的文章信息并不在网页源代码中,以此判断使用了异步加载技术。
9.1.3 逆向工程
使用异步加载技术,不再是立即加载所有网页内容,而展示的内容也就不在HTML源码中。这样,通过前文中的方法就无法正确抓取到数据。想要抓取这些通过异步加载方法的网页数据,需要了解网页是如何加载这些数据的,该过程就叫做逆向工程。Chrome浏览器的Network选项卡可以查看网页加载过程中的所有文件信息,通过对这些文件的查看和筛选,找出需抓取数据的加载文件,以此来设计爬虫代码。
9.2.1 爬虫思路分析
(1)爬取的内容为简书笔者用户动态的信息(http://www.jianshu.com/u/9104ebf5e177)。
(2)当首次打开该网页URL,选择动态,会发现网页URL并没有发生变化,如下图所示,所有判断该网页采用了异步加载技术。
(3)打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,可发现网页加载了用户“动态”内容的文件,如图所示。
(4)观察该文件的Response,发现返回的是XML文件,内容也正是用户“动态”内容(如图),每个li标签就是一个用户动态内容。删除timeline后面的字符串也可返回正确的内容,以此构造第一页的URL为http://www.jianshu.com/users/9104ebf5e177/timeline。
(5)通过下滑浏览,会发现也是使用了异步加载技术进行分页处理的,如图9.16所示,以此记录前几页的URL:
http://www.jianshu.com/users/9104ebf5e177/timeline?max_id=105768197&page=2
http://www.jianshu.com/users/9104ebf5e177/timeline?max_id=103239632&page=3
http://www.jianshu.com/users/9104ebf5e177/timeline?max_id=102134973&page=4
(6)通过手工删除URL中的max_id,发现不能返回正常的内容,如图所示,说明max_id是一个很关键的字段,而笔者发现每个页面的max_id都不同,通过观察数字也没有明显的规律,而构造URL的重点就在如何获取max_id的数字了。
(7)上述分析到每个li标签就是用户的一条动态内容,笔者发现,li标签的id字段有着一串没有规律的数字信息。
通过观察发现,前一页最后一个li标签中的id数字刚好是它下一页URL中的max_id数字加1,以此来构造出分页URL。
(8)由于Response返回的是XML文档,便可通过lxml库进行数据的抓取工作,需爬取的内容为用户“动态”类型和时间信息,如图。
(9)最后,把爬取的信息存储在MongoDB数据库中。
9.3.1 爬虫思路分析
(1)爬取的内容为简书七日热门信息(http://www.jianshu.com/trending/weekly)
(2)该网页也是采用了AJAX技术实现分页。打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,可发现翻页的网页文件。
(3)人工删除URL中间部分字符串,发现http://www.jianshu.com/trending/weekly?page=即可返回正确的内容,发现简书七日热门的page到11页就没有信息了,以此构造所有的URL。
(4)本次爬虫在详细页中进行,故先需爬取进入详细页的网址链接,进而爬取数据。
(5)需要爬取的信息有:作者ID、文章名、发布日期、字数、阅读、评论、喜欢、赞赏数量、收录专题。
(6)通过判断元素是否在网页源代码中来识别异步加载技术,发现阅读、评论、喜欢、赞赏数量、收录专题采用了异步加载技术。
(7)阅读、评论、喜欢虽然采用异步加载技术,但其内容在<script>
标签中,可采用正则表达式的方法获取数据。
(8)打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,可发现打赏和收录专题的文件信息。
(9)打赏请求的URL,有一串数字信息,并不能删除
但在网页源代码中找到了这串数字
可通过获取网页源代码中的数字信息构造URL。该URL返回的为JSON数据,可通过json库获取数据。
(10)以同样的方法,找到收录专题的文件
该URL返回的也为JSON数据。
(11)最后,把爬取的信息存储在MongoDB数据库中。
10.1.1 POST方法
Requests库的POST方法使用简单,只需要简单地传递一个字典结构的数据给data参数。这样,在发起请求时会自动编码为表单形式,以此来完成表单的填写。
import requests params = { 'key1':'value1', 'key2':'value2', 'key3':'value3' } html = requests.post(url,data=params) #post方法 print(html.text)
10.1.2 查看网页源代码提交表单
以豆瓣网(https://www.douban.com/)为例,进行表单交互。
(1)打开豆瓣网,定位到登录位置,利用Chrome浏览器进行“检查”,找到登录元素所在的位置。
(2)根据步骤一在网页源代码中找到表单的源代码信息。
(3)对于表单源代码,有几个重要组成部分。分别是form标签的action属性和input标签。Action属性为表单提交的URL。而input为表单提交的字段,input标签的name属性就是提交表单的字段名称。
(4)根据表单源代码,就可以构造表单进行登录网页了:
import requests url = 'https://www.douban.com/accounts/login' params = { 'source':'index_nav', 'form_email':'xxxx', 'form_password':'xxxx' } html = requests.post(url,params) print(html.text)
(5)通过比较未登录和登录豆瓣网页。
看出登入后的右上角有笔者的账户名称。通过代码打印的网页源代码检查是否有此信息来判断是否登录了豆瓣,如下图,说明登录成功。
10.1.3 逆向工程提交表单
对与初学者而言,观察表单的网页源代码可能有些头疼,对input标签不敏感,可能会遗漏一些表单提交的字段。本小节就通过Chrome浏览器的开发者工具中的Network选项卡查看表单交互情况,以此构造提交表单的字段信息
10.2.1 cookie概述
Cookie,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据。互联网购物公司通过追踪用户的cookie信息,来给用户提供相关兴趣的商品。同样,因为cookie保存了用户的信息,我们便可通过提交cookie来模拟登录网站了。
10.2.2 提交cookie模拟登录
同样以豆瓣网为例,查找cookie信息并提交来模拟登录豆瓣网。
(1)进入豆瓣网,打开Chrome浏览器的开发者工具,单击Network选项。
(2)手工输入账号和密码进行登录,会发现Network中会加载许多文件。
(3)这时,并不需要查看登录网页的文件信息,而是直接查看登录后的文件信息,可看到相应的cookie信息。
(4)在请求头中加入cookie信息即可完成豆瓣网的模拟登录:
import requests url = 'https://www.douban.com/' headers = { 'Cookie':'xxxxxxxxxxxxxx' } html = requests.get(url,headers=headers) print(html.text)
(5)通过上文的方法检查是否成功登录了,如图所示,模拟登录成功。
10.3.1 爬虫思路分析
(1)爬取的内容为拉勾网(https://www.lagou.com/)上Python的招聘信息。
(2)通过观察,网页元素不在网页源代码中,说明该网页使用了AJAX技术
(3)打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,可以看到加载招聘信息的文件。在Headers中可以看到请求的网址。
网址的“?”后面字符串可省略。在Response中可看到返回的信息),信息为JSON格式。
(4)当JSON格式很复杂时,可通过“Preview”标签来观察,如图所示。发现招聘信息在content-positionResult-result中,里面的大部分信息是爬虫的抓取内容。
(5)手动翻页,发现网页URL没有发生变化,故也采用了AJAX技术。打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,手动翻页,可发现翻页的网页文件,但发现请求的URL没有发生变化。
通过仔细观察,请求该网页为POST方法,提交的表单数据根据“pn”字段来实现页数变化。
(6)在返回的JSON数据中,可找到招聘信息总数量。
每页是15个招聘信息。而拉勾网默认只有30页信息。通过抓取招聘信息总数量,除上15,如果小于30页,就取计算结果为页面总数量。如果大于30,就取30页。最后,存储数据到MongoDB数据库中。
10.4.1 词云制作
1.个人BDP
前文中讲到个人BDP是一款在线版数据可视化分析工具,并学会了制作地图。本次将利用个人BDP制作词云。
2.jieba分词和TAGUL在线制作词云工具
利用个人BDP制作词云,关键词和词云制作一气呵成。而本小节将会使用Python第三方库jieba,进行文本的关键词提取,再利用TAGUL在线制作词云工具制作词云。
10.4.2 爬虫思路分析
(1)爬取的内容为移动端新浪微博(http://m.weibo.cn)上好友圈的信息
(2)通过新浪微博网页版登录后,打开Chrome浏览器的开发者工具(按F12键),选择左上角手机形状的工具,刷新网页,即可转换为移动端新浪微博。
(3)通过观察,网页元素不在网页源代码中,说明该网页使用了AJAX技术。
(4)打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡,选中XHR项,可以看到加载好友圈信息的文件。在Headers中可以看到请求的网址。
在Response中可看到返回的信息,信息为JSON格式。
(5)通过手动下拉,可以找到下一页的URL。
URL中有next_cursor字段,通过观察第一页URL中的Preview标签,返回的JSON数据中刚好有next_cursor,恰好和本页URL中的数字相同。
通过多次验证,确定正确后,便可通过这样依次构造出下一页的URL。
(6)通过提交cookie信息模拟登录新浪微博,复制cookie信息。
(7)爬取好友圈50页的微博信息,保存到TXT文档中,最后通过分词制作词云。
11.1.1 Selenium概念和安装
Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样。由于这个性质,Selenium也是一个强大的网络数据采集工具,其可以让浏览器自动加载页面,这样,使用了异步加载技术的网页,也可获取其需要的数据。
Selenium模块是Python的第三方库,可以通过pip进行安装:
pip3 install selenium
11.1.2 浏览器选择和安装
Selenium自己不带浏览器,需要配合第三方浏览器来使用。通过help命令查看Selenium的Webdriver功能,查看Webdriver支持的浏览器:
from selenium import webdriver help(webdriver)
查看执行后的结果,如图所示。
11.2.1 模拟浏览器操作
Selenium和PhantomJS的配合使用可以完全模拟用户在浏览器上的所有操作,包括输入框内容填写、单击、截屏、下滑等各种操作。这样,对于需要登录的网站,用户可以不需要通过构造表单或提交cookie信息来登录网站
11.2.2 获取异步加载数据
上文中提到driver.get()方法请求过后的网页源代码中有异步加载的信息,这样便可以轻松获取Javascript数据
11.3.1 CSV文件读取
前文中讲解到使用Python第三方库csv存储数据到CSV文件中。csv库不仅可以存储CSV数据,也可以读取CSV文件的读取。
可通过如下代码读取CSV文件:
import csv fp = open('C:/Users/LP/Desktop/doubanbook.csv',encoding='utf-8') reader = csv.reader(fp) for row in reader: print(row) fp.close()
11.3.2 爬虫思路分析
(1)从QQ邮箱中获取QQ好友号。打开QQ邮箱,选择通讯录
选择部分QQ好友,选择“工具”|“导出联系人”
以CSV文件导出,这样,便可以通过csv库读取CSV文件,并取出好友的QQ号码。
(2)QQ空间好友说说的链接为:http://user.qzone.qq.com/{好友QQ号}/311。首次打开QQ空间,需要登录,如图所示,使用Selenium和PhantomJS,选择账号密码登录。
(3)爬取的内容为好友说说和发表时间。
(4)把爬取数据存储到MongoDB数据库中。
11.4.1 爬虫思路分析
(1)爬取的内容为淘宝网(https://www.taobao.com/)上男士短袖的商品信息,如图所示。
(2)本节爬虫并不是请求该网页,而是使用Selenium和PhantomJS,模拟电脑的搜索操作,输入商品名称进行搜索,如图所示,“检查”搜索框元素。
(3)前文中,都是通过观察不同页面URL规律,来构造多页URL。本节使用Selenium和PhantomJS,模拟电脑的翻页操作,如图所示,“检查”下一页元素。
(4)爬取的内容有商品价格、付款人数、商品名称、商家名称和地址,如图所示。
(5)把爬取数据存储到MongoDB数据库中。
12.1.1 Scrapy安装
由于Scrapy爬虫框架依赖许多第三方库,所以在安装Scrapy前,确保以下第三方库均已安装。
1.lxml库
2.zope.interface库
3.twisted库
4.pyOpenSLL库
5.pywin32库
6.Scrapy库
12.1.2 创建Scrapy项目
以小猪短租的一页租房信息为例,如图所示。进行Scrapy爬虫代码的编写工作。
12.1.3 Scrapy文件介绍
1.items.py
items.py文件的作用为定义爬虫抓取的项目,简单来说,就是定义爬取的字段信息。
2.pipelines.py
pipelines.py文件的主要作用为爬虫数据的处理,在实际爬虫项目中,主要是用于爬虫数据的清洗和入库操作。
3.settings.py
settings.py文件的主要作用是对爬虫项目的一些设置,如请求头的填写、设置pipelines.py处理爬虫数据等。
12.1.4 Scrapy爬虫编写
1.items.py
2.xiaozhuspider.py
3.pipelines.py
4.settings.py
12.1.5 Scrapy爬虫运行
Scrapy爬虫框架的运行也需使用命令行窗口。回到xiaozhu文件夹中,输入下面命令即可运行爬虫,运行结果如图所示。
scrapy crawl xiaozhu
12.2.1 爬虫思路分析
(1)爬取的内容为简书热门专题的信息(http://www.jianshu.com/recommendations/collections?order_by=hot),如图所示
(2)当初次进入热门专题时,进入的是“推荐”,切换为“热门”时,网页URL没有发生变化,这说明该网页使用了异步加载。
打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡。
刷新网页,又会跳转到“推荐”,手动点选“热门”,选择XHR会发现Network选项卡中会加载一个文件。
打开加载文件,在Headers部分可以看到热门专题的URL。
在Response部分可看到返回的内容就是热门专题的信。
(3)简书热门专题分页也采用了异步加载的技术,打开开发者工具,通过手动下滑翻页,查看URL变化情况,可以看出是通过改变page后的数字进行翻页,把第一页的URL改为http://www.jianshu.com/recommendations/collections?page=1&order_by=hot,也可以正常访问,最后观察有38页,以此构造全部URL。
(4)需要爬取的信息有:专题名称、专题介绍、收录文章和关注人数。
(5)采用Scrapy框架进行爬取,通过Feed exports功能把爬虫信息存入CSV文件中。
12.3.1 爬虫思路分析
(1)爬取的内容为知乎Python话题精华的信息(https://www.zhihu.com/topic/19552832/top-answers?page=1)。
(2)爬取50页的信息,通过手动浏览,以下为前4页的网址:
https://www.zhihu.com/topic/19552832/top-answers?page=1
https://www.zhihu.com/topic/19552832/top-answers?page=2
https://www.zhihu.com/topic/19552832/top-answers?page=3
https://www.zhihu.com/topic/19552832/top-answers?page=4
通过观察规律,很容易构造出全部URL.
(3)需要爬取的信息有:Python问题、点赞数、回答问题用户、用户信息和回答内容。
(4)采用Scrapy框架进行爬取,通过pipeline.py把数据存储到MongoDB数据库中。
12.4.1 爬虫思路分析
(1)爬取的内容为简书IT互联网专题的收录文章信息(http://www.jianshu.com/c/V2CqjW?order_by=added_at&page=1)
(2)当初次进入IT互联网专题时,进入的是“最新评论”,切换为“最新收录”时,网页URL没有发生变化,这说明该网页使用了异步加载。
打开Chrome浏览器的开发者工具(按F12键),单击Network选项卡。
刷新网页,又会跳转到“最新评论”,手动点选“最新收录”,选择XHR会发现Network选项卡中会加载一个文件。
打开加载文件,在Headers部分可以看到IT互联网专题收录文章的URL。
在Response部分可看到返回的内容就是收录文章的信息。
(3)翻页也采用了异步加载的技术,打开开发者工具,通过手动下滑翻页,查看URL变化情况。
可以看出是通过改变page后的数字进行翻页,把第一页的URL改为:
http://www.jianshu.com/c/V2CqjW?order_by=added_at&page=1,也可以正常访问,最后构造100页URL。
(4)需要爬取的信息有:用户ID、发表时间、文章标题、阅读量、评论量、喜欢量和打赏量。
(5)采用Scrapy框架进行爬取,通过pipeline.py把数据存储到MySQL数据库中。
12.5.1 爬虫思路分析
(1)爬取的内容为简书推荐作者信息(http://www.jianshu.com/recommendations/users)。
(2)翻页也采用了异步加载的技术,打开开发者工具,通过手动下滑翻页,查看URL变化情况。
可以看出是通过改变page后的数字进行翻页,把第一页的URL改为:
http://www.jianshu.com/recommendations/users?page=1,也可以正常访问,最后观察有38页,以此构造全部URL。
(3)需要爬取的信息有:作者URL、作者ID、最新更新文章、作者类型、关注、粉丝、文章、字数和收获的喜欢。
可以看出为跨页面爬虫,如何使用Scrapy爬虫实现爬虫字段的传递成为该爬虫的重点。
(4)采用Scrapy框架进行爬取,通过pipeline.py把数据存储到MongoDB数据库中。
码字不易,只希望能得到大家的一键三连,感激不尽!