Python爬虫技术与应用:原生态网络爬虫开发

Python爬虫技术与应用:原生态网络爬虫开发

3.1 requests库详解

3.1.1 requests语法

1.安装requests包

pip install requests

2.GET请求

基本GET请求,代码如下:

import requests
r=requests.get('http://httpbin.org/get')
print(r.text)

带参数GET请求,代码如下:

import requests
r=requests.get('http://httpbin.org/get?name=williams_z&age=21')
param={'name':'williams_z','age':21}                             #注意要用字典形式
r=requests.get('http://httpbin.org/get',params=param)            #加参数用params函数
print(r.text)

假如想请求JSON文件,可利用JSON()方法解析,以文字为基础且易于让人阅读,同时也方便机器进行解析和生成,代码如下:

    import requests
    import json
    r=requests.get('http://httpbin.org/get')
    print(r.json())
获得二进制数据,主要用以解析图片和视频等,代码如下:

    import requests
    r=requests.get('http://httpbin.org/get')
    print(r.content)

保存二进制数据,代码如下:

import requests
r=requests.get('https://github.com/favicon.ico')
with open('favicon.ico','wb') as f:
    f.write(r.content)
f.close()
#wb:以二进制格式打开一个文件只用于写入
#w:即为write
#f:即file(文件)

添加headers,代码如下:

    import requests
    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52'}
    r=requests.get('https://www.zhihu.com/explore',headers=headers)
    print(r.text)

3.高级操作

文件上传,代码如下:

import requests
file={'file':open('favicon.ico','rb')}
r=requests.post('http://httpbin.org/post',files=files)
print(r.text)

获得Cookie,代码如下:

import requests
r=requests.get('http://www.baidu.com')
print(r.cookies)
for key,value in r.cookies.items():
    print(key+ '=' +value)

证书验证,代码如下:

import requests
from requests.packages import urllib3
urllib3.disable_warnings() #这两句用以消除证书未验证系统弹出的警告
r=requests.get('https://www.12306.cn',verify=False)
print(r.status_code)

代理设置,代码如下:

import requests
proxies={'http':'http://127.0.0.1:9743','http':'https://127.0.0.1:9744',}
r=requests.get('https://www.taobao.com',proxies=proxies)
print(r.status_code)

socks代理,需要先安装requests[socks]模块,代码如下:

pip install requests[socks]
proxies={'http':'socks5://127.0.0.1:9742'}

认证设置,代码如下:

import requests
r=requests.get('http://120.27.34.24:9001',auth=('user','123'))
print(r.status_code)

3.1.2 requests库的使用

1.cookies的用处

关于需要登录的网站该如何抓取呢?例如知乎网站,需要登录才能进入知乎网,有时候又会发现,由于之前登录过,再次登录的时候便不需要输入密码,这就涉及了cookies,在网站开发时或多或少一定会用到,以知乎网为例,当提问、评论、点赞的时候,后台程序要获得的用户信息,下次登录时不需要用户名和密码即可自动登录等都和cookies有关系。

2.什么是cookies

cookie可以翻译为“曲奇、小饼干”,cookie在网络系统中几乎无处不在,当浏览以前访问过的网站时,网页中可能会出现“你好XXX”,这会让人感觉很亲切,就如同吃了一个小甜品一样。这其实是经由访问主机中的一个文件来实现的,这个文件便是cookie。在因特网中,cookie实际上是指少量信息,是由Web服务器创建的,把信息存储在用户计算机上的文件。一般网络用户习惯用其复数形式cookies,指某些网站为甄别用户身份、进行会话跟踪而存储在用户本地终端上的数据,而这些数据通常会经由加密处理。

3.网络爬虫如何利用cookies

能够经由Chrome开发者工具直接获得登录时的cookies信息,在网络爬虫中的请求头中携带cookies信息,从而直接抓取需要登录的网站,cookie的值如图3-1所示。

在这里插入图片描述

经由以上代码运行后,能够成功抓取网页信息,代码如下:

    import requests
    headers={
    'cookie':'PHPSESSID=68q6d1mi0sr4ecbcpv7ptu9gh0',
    'user-agent':'Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Ubun
tuChromium/66.0.3359.139Chrome/66.0.3359.139Safari/537.36'
    }
    r=requests.get('https://www.zhihu.com',headers=headers)
    print(r.text)

4.会话对象

有时候不仅仅抓取网站的一个页面,而是抓取多个页面,这就需要发送多个POST和GET请求,由于http是无状态协议,前后几次的请求是互不相关的。举个例子:前一个requests请求携带cookies信息,成功登录网站,下一个requests请求要抓取另一个新的页面,还是要携带cookies信息的,requests为提供Sessiond对象来维持一个会话。requests请求例子代码如下:

import requests
requests.get('http://httpbin.org/cookies/set/number/123456')
r = requests.get('http://httpbin.org/cookies')
print(r.text)

requests请求例子如图所示。

在这里插入图片描述

请求测试网站时设置cookies值再次请求,从而获得cookies值时返回空值,说明服务器没反应,两次请求是一个对象发起的,事实上两个请求都是计算机上的同一个程序发起的,再次验证http是无状态协议。代码如下:

import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456')
r = s.get('http://httpbin.org/cookies')
print(r.text)

session请求如图3-3所示。

5.身份认证

身份认证也称为“身份验证”或“身份鉴别”,是指在计算机及计算机网络系统中确认操作者身份的过程,进而确定该用户是不是具备对某种资源的访问和使用权限,进而使计算机和网络系统的访问策略变得可靠、有效,制止攻击者充作合法用户取得资源的访问权限,保证系统和数据的安全,以及授权访问者的合法利益。

在这里插入图片描述

有些网站资源需要输入身份验证信息才能访问,许多要求身份认证的Web服务都接受HTTP-Basic-Auth,这是最简短易懂的一种身份认证,并且requests对这种认证方式的支持是直接开箱便可用,能够经由下面这种简短易懂的方式实现,代码如下:

import requests
r=requests.get('https://api.github.com/user',auth=('myacconut','mypassword'))
print(r.status_code)
r=requests.get('https://api.github.com/user',auth=('123','321'))
print(r.status_code)

这里经由github的用户身份验证API,进行测试账号、密码,验证成功返回状态码200,证明没有问题。假如随意输入一个不存在的账号和密码,返回的状态码为401错误,其实是身份验证失败。

6.SSL证书验证

HTTPS的安全基础是SSL,所传输的内容都是经过加密的,而某些网站虽然使用HTTPS协议,但还是会被浏览器提示不安全,例如在Chrome浏览器里面打开链接为https://www.12306.cn/,这时浏览器就会提示“您的连接不是私密连接”这样的话,证书不被CA机构信任的弹窗提醒如图3-4所示。

在这里插入图片描述

这是由于12306的CA证书是中国铁道部自行签发的,而这个证书是不被CA机构信任的,所以这里证书验证就不会通过而这样提示,但是实际上它的数据传输依然是经由SSL加密的。假如要抓取这样的站点,就需要设置忽略证书的选项,否则会提示SSL链接错误,代码如下:

import requests
r = requests.get('https://www.12306.cn')
print(r.status_code)
print(r.text)
#SSLEroor,SSL证书错误,这时能够经由设置verify=False来关闭SSL认证
r=requests.get('https://www.12306.cn',verify=False)
print(r.status_code)
print(r.text)

3.2 正则表达式

3.2.1 正则表达式详解与使用

正则表达式,也称为正规表示法、正规表达式、常规表示法,是计算机科学中的一个概念。

正则表达式使用单个字符串来概述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式往往被用来检索、替换那些匹配某个模式的文本。

很多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建一个功能强大的正则表达式引擎。正则表达式的概念一开始是由UNIX中的工具软件普及开的。正则表达式通常缩写成regex,单数有regexp、regex,复数有regexps、regexes、regexen。

re模块的常用函数如下:

(1)findall查找所有,返回list,代码如下:

import  re
list1 = re.findall("m","mai le fo len mei meme")
print(list1)

(2)search会进行匹配,如果匹配到第一个结果就返回,如果匹配不到则返回None。代码如下:

ret = re.search(r'\d', '5点之前,要给5000万' ).group()
print(ret)

(3)finditer和findall差不多,只不过这时返回的是迭代器,代码如下:

it = re.finditer("m", "mai le fo len, mai ni mei!")
print(it)
for i in it:
    print(i.group()
)

举个例子,假如在写一个网络爬虫,得到一个网页的HTML源码,其中有一段,代码如下:

<html><body><h1>helloworld</h1></body></html>

使用正则表达式进行处理,代码如下:

import re
key = r"<html><body><h1>helloworld</h1></body></html>"  #匹配的文本
p1 = r"<h1>(.*?)</h1>"                          #正则表达式规则
pattern1= re.compile(p1)                        #编译正则表达式
matcher1 = re.findall(pattern1,key)             #在源文本中搜索符合正则表达式的部分
print(matcher1[0])                              #打印因为findall返回的是数组,所以要索引0取值

3.2.2 Python与Excel

Python作为一种脚本语言,相较于Shell具有更强大的文件处理能力,一般Shell在处理纯文本文件时较为实用,而对特殊文件的处理如Excel表格,则Python会更运用自如,主要因为目前它能够调用很多第三方功能包来实现想要的功能,Python读写Excel的方式有很多不同的模块,其在读写的讲法上稍有区别,具体区别如下。

· Python用xlrd和xlwt进行Excel读写。

· Python用openpyxl进行Excel读写。

· Python用pandas进行Excel读写。

1.利用xlrd和xlwt进行Excel读写

Ubuntu环境下,首先是安装第三方模块xlrd和xlwt,代码如下:

#安装包
sudo pip install xlrd
sudo pip install xlwt

xlrd读Excel,代码如下:

import xlrd
book=xlrd.open_workbook('学生信息表.xls')
sheet1=book.sheets()[0]
nrows=sheet1.nrows
print(u'表格总行数',nrows)
ncols=sheet1.ncols
print(u'表格总列数',ncols)
row3_values=sheet1.row_values(2)
print(u'第3行值',row3_values)
col3_values=sheet1.col_values(2)
print(u'第3列值',col3_values)
cell_3_3=sheet1.cell(2,2).value
print(u'第3行第3列的单元格的值:',cell_3_3)

xlrd写Excel,代码如下:

import xlwt #不支持excel2007的xlsx格式
workbook=xlwt.Workbook()
worksheet=workbook.add_sheet('test')
worksheet.write(0,0,'A1data')
workbook.save('excelwrite.xls')

程序运行后,新建excelwrite.xls工作簿并插入text工作表,A1的内容为A1data。

2.利用openpyxl读写Excel,注意这里只能是xlsx类型的Excel

Ubuntu环境下,首先安装的话,运行代码如下:

#安装包
sudo pip install openpyxl

读Excel,代码如下:

from openpyxl.reader.excel import load_workbook
workbook=load_workbook('学生信息表.xlsx')
worksheet=workbook.worksheets[0]
row3=[item.value for item in list(worksheet.rows)[2]]
print(u'第3行值',row3)
col3=[item.value for item in list(worksheet.columns)[2]]
print(u'第3列值',col3)
cell_2_3=worksheet.cell(row=2,column=3).value
print('第2行第3列值',cell_2_3)
max_row=worksheet.max_row
print(u'最大行',max_row)

写Excel,代码如下:

import openpyxl
workbook=openpyxl.Workbook()
sheet=workbook.active
sheet['A1']='hi,python'
workbook.save('new.xlsx')

程序运行后,新建new.xlsx文件,并插入sheet工作表。

3.利用pandas读取Excel

pandas的名称来自于面板数据和Python数据分析。pandas是一个数据处理的包,本身提供许多读取文件的函数,如read_csv、read_excel等,只需一行代码就能实现文件的读取。代码如下:

#Linux安装pandas
sudo pip install pandas

读Excel,代码如下:

import pandas as pd
df=pd.read_excel(r'学生信息表.xls')
print(df)

写Excel,代码如下:

from pandas import DataFrame
data={
'name':[u'张三',u'李四',u'王五'],
'age':[21,22,23],
'sex':[u'男',u'女',u'男']
}
df=DataFrame(data)
df.to_excel('new.xlsx')

程序运行后,新建new.xlsx文件,并在工作表sheet1的A1:D4区域中保存内容。

至此,就完成了Excel的读写。总的来说,这三种方法都很简短易懂,尤其是第三种方法,一行代码就能搞定。在数据处理中,经常会用到pandas这个包,它的功能很强大,当然还有许多其他的包也能够完成Excel的读写。

3.3 实战案例:环球新闻的抓取

1.使用浏览器打开百度

搜索“国内新闻环球网”,如图3-5所示。

在这里插入图片描述

2.查看相关的源文件信息

在打开的界面按住F12键,单击要抓取的新闻标题,新闻标题所在标签如图3-6所示。

在这里插入图片描述

3.导入requests库

import requests

4.请求http页面

使用Python代码来请求http页面,代码如下:

import requests
ur1="http://china.huanqiu.com"
data=requests.get(url)
data.status_code #查看返回值

在这个基础上增加一个打印效果,可以显示返回的请求状态,完整代码如下:

import requests
ur1="http://china.huanqiu.com"
data=requests.get(ur1)
data.status_code
print(data)  #输出返回值

抓取的新闻标题返回结果如图3-7所示。

在这里插入图片描述

结果返回的值为200,该类型状态码表示动作被成功接收、理解和接受。其常见的网页返回值及相对应的含义有:http状态返回代码1xx(临时响应);http状态返回代码3xx(重定向);http状态返回代码4xx(请求错误);http状态返回代码5xx(服务器错误)。

5.使用的模块

在进行模块与库的添加时,要注意Python库中是否已存在,所使用的模块有re、urllib.request等库,没有相应的库可进行安装的代码如下:

pip install re

导入库的代码如下:

#-*-coding: utf-8-*-
import urllib.request
import urllib
import re

6.观察网页规律,抓取相关数据包

通过观察,会发现这个网站的新闻一直往下滑才会有新的加载,是一种懒加载,观察抓包请求会发现,新闻的标题、时间戳、来源、摘要等都在数据包内,请求链接只有offset发生变化,观察网页新闻所在数据包如图3-8所示。

在这里插入图片描述

7.构造发送请求

获取第一页网页源码如图3-9所示。

在这里插入图片描述

8.使用正则表达式解析数据

最后将数据以字典的形式保存,代码如下:

aid_list = re.findall('"aid": "(.*?)",',response)
title_list = re.findall('"title": "(.*?)",',response)
summary_list = re.findall('"summary": "(.*?)",',response)
source_list = re.findall('"source" :.*?"url":"(.*?)"},',response)
#将每一页的标题、编号等数据放到字典里面
data = {
    '编号':aid_list,
    '标题':title_list,
    '摘要':summary_list,
    '来源链接':source_list
}

9.观察新闻的链接

发现每个新闻的href都含有aid,单击进去新闻的网址链接形式为https://china.huanqiu.com/article/44stNassPJQ,如图3-10所示。

在这里插入图片描述

10.遍历aid列表

访问每个新闻的内容进行抓取。观察新闻内容所在标签,会发现每个文章的开始都有一个

,结尾都有一个
,那么就抓取这个里面的内容,使用正则表达式进行匹配,新闻内容所在标签如图3-11所示。

保存新闻内容和环球网首页信息,抓取一页新闻的内容就停1秒,防止触发反爬机制,代码如下:

    import time
    import requests
    import re
    for aid in aid_list:
         zi_url = 'https://china.huanqiu.com/article/' + aid
         response = requests.get(zi_url, headers=headers).text
         text_list = re.findall('<article><section data-type="rtext"><p>(.*)</p>.*?</article>',
response)
         for i in text_list:
             with open('新闻内容.txt','a',encoding='utf-8') as f:
                 f.write(i+'\n'+'-'*100+'\n')
         time.sleep(1)

在这里插入图片描述

11.抓取多页并整合代码

抓取新闻内容如图3-12所示。

在这里插入图片描述

完整的代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib.request
import urllib
import re
from newspaper import Article
import datetime



class BDTB:
    def __init__(self, baseUrl):
        self.baseURL = baseUrl

    def getPage(self):
        try:
            url = self.baseURL
            response = urllib.request.urlopen(url)
            return response.read().decode('utf-8')
        except :
            pass

    def getContent(self):
        page = self.getPage()
        pattern = re.compile('<div class="leftList bgWhite">(.*?)</div>', re.S)
        L = re.findall(pattern, page)
        items = re.findall(re.compile('<li>(.*?)</li>', re.S), L[0])


        resule = []
        for item in items:
            print('-----------------------------------------------------------')
            try:
                title = re.findall(re.compile('<h3>(.*?)</h3>', re.S), item)[0]
                print(title)
                http = re.findall(re.compile('<a.+?href=\"(.+?)\".*>', re.S), item)[0]
                print(http)
                content = Article(http, language='zh')
                content.download()
                content.parse()
                content = content.text
                print(content)
                resule.append(http+"\t"+title+"\t"+content+"\n")
            except:
                title =""
                http = ""
                content = ""
        f = open("新闻信息.txt","w+")
        for i in resule:
            f.write(i)
        f.close()

baseURL = 'http://china.huanqiu.com'
test = BDTB(baseURL)
test.getContent()

print(datetime.datetime.now())

在实际环境中进行抓取的内容不止图3-12中的这一小部分,而数据内容过多会导致在处理数据时遇到一些问题,所以可以在代码中添加一个获得当前时间的语句。

在整体代码的上方或者在结尾处添加一个时间代码,代码如下:

#引入datetime库
import datetime
#获得当前系统时间
print(datetime.datetime.now())

在代码的最后一行添加如下代码,这样在每次抓取完后,当前的系统时间会自动标记在后方,获取当前系统时间如图3-13所示。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值