爬虫(一)基础

浏览器到网站服务器响应

爬虫就是用代码替代里浏览器,并对返回的信息进行解析

爬虫的应用

12306抢票、黄牛抢特价机票、搜索引擎、微博买赞刷评论、微博抢红包、通过网络机器人提高搜索引擎排名、比价网、获取其他平台点评

伪装UA

UA(User-Agent)在信息头中用于对请求的身份进行识别,某些网站为防止崩溃,会对机器人进行限制。比如发现是个python请求就直接拒绝了。

step1)获取浏览器UA

任意网页右键》》审查元素》》Network》》刷新/保存等任意操作》》Name中选中后任意请求》》Headers 'Request Headers'user-agent

step2)使用字典设置headers

import requests
url2='http://httpbin.org/get'
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
data=requests.get(url2,headers=header)
print(data.text)

使用检查元素寻找网页和代码的对应关系

审查元素》》Elements》》点击左上角指针可定位网页到代码/不选中指针鼠标在代码上下移动可定位代码到网页

爬取豆瓣新书速递内容

step1)requests发送请求,返回test信息

step2)处理为一个BeautifulSoup对象,便于解析

step3)利用审查元素寻找代码和网页的对应关系

step4)利用find 和find_all方法提取信息块

step5) 解析信息块中的内容

step6)存储解析后的数据

简单来说就是:获取——解析——存储  三步

import requests
from bs4 import  BeautifulSoup
#返回网页信息
url='https://book.douban.com/latest'
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
data=requests.get(url,headers=header)
# print(data.text)
#处理为一个便于解析的BeautifulSoup对象
soup=BeautifulSoup(data.text,'lxml')
# print(soup)
#获得信息块
books_left=soup.find('ul',{'class':'cover-col-4 clearfix'})
books_left=books_left.find_all('li')
books_right=soup.find('ul',{'class':'cover-col-4 pl20 clearfix'})
books_right=books_right.find_all('li')
books=list(books_left)+list(books_right)#这里是否使用list对最终结果无影响
# print(len(books))
#对信息块中的每个元素进行解析
img_urls=[]
stars=[]
for book in books:
    #获取图片的地址
    info=book.find('a')#这里使用find还是find_all会对后面的代码有影响
    info=info.find('img').get('src')
    img_urls.append(info)
    # 获取星级
    info2=book.find('p',{'class':'rating'}).get_text()#返回去除html标签后的纯文本
    score=info2.replace('\n','').replace(' ','')
    stars.append(score)
print(stars)

解析信息块常用方法

find#返回第一个带有指定内容的块,注意=相当于python中的字典

find_all#返回所有带有指定内容的块,是一个list

get(key)#获取key对应的信息

get_text()#获取去除带<>的html标签后的纯文本

replace#替换一些内容或去除换行‘\n’或空格' ' 

使用try处理报错信息

有时候一些网站的url会因为更新啊之类的问题而报错,代码需要对这些error有处理能力,不要一出错就停止运行了,那之前处理的都白费了。善用try... except ...

import  requests
url='http://news.baidu.com/'

header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
try:
    data=requests.get(url,headers=header)

except requests.exceptions.ConnectionError as error:#可带多个except,不指明错误类型时,默认所有错误
    print('info :',error)
else:#在所有except之后,可带一个else,未出现异常时执行
    print(data.text)

finally:#任何情况都会执行,一般用于释放文件或网络等资源
    print('end------')

服务器状态码5XX

使用requests.get(url)获得的data,不仅有data.text文本信息,还有data.status_code状态码信息,data.content,对数据范围进行判断,若在500~600之间(if (data!=None) and (500<=data.status_code<600):),可以先暂停(time.sleep(1))后刷新请求(递归)。这个过程可以执行几次(if num <3:)

请求超时

谷歌等网站由于不能打开,请求时会一直卡在请求这一步,可设置timeout时间控制请求超时

data=requests.get(url,timeout=5)

爬虫声明、限制robots.txt

例如百度的声明网址是https://www.baidu.com/robots.txt

打开该网址后第一个是:

User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/

意思是说,UA为Baiduspider时,不能访问http://www.baidu.com/baidu等网址,其他没有注明Disallow的则可以访问。

下面有个代码示范了使用urllib库对robots.txt的解析

import urllib.robotparser
rp=urllib.robotparser.RobotFileParser()
rp.set_url('http://www.baidu.com/robots.txt')
rp.read()
a=rp.can_fetch('Baiduspider','http://www.baidu.com/baidu')
print(a)
b=rp.can_fetch('Baiduspider','http://www.baidu.com/cpro')
print(b)

set_url为robots.txt文件的网址,can_fetch两个参数分别为UA和要检验的网址,返回值为布尔值,a=False,b=True

可通过robots.txt检验当前UA能否访问的url。

动态UA

简单来说,就是有个库可以获得众多浏览器的UA,不需要自己对各个浏览器来一下【审查元素】操作。

from fake_useragent import UserAgent
ua=UserAgent()
print(ua.ie)
print(ua.random)

代理ip

import requests

proxies_dict={'http':'IP:端口','https':'IP:端口'}
data=requests.get(url,proxies=proxies_dict)

乱码编码

先检验编码,后设置编码。这里charset返回的信息是【{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}】表明:编码方式为ASCII编码的可能性是100%

import requests
import chardet
data=requests.get('http://baidu.com')
print(data.text)
print('********************')
charset=chardet.detect(data.content)
print(charset)
data.encoding=charset['encoding']
print(data.text)

正则表达式

形式为re.findall、match、find、search(正则表达式,待检验字符串)

  
()表明要提取的就是括号里的内容
r'xxxxxx'不把引号中的\视为转义符
.除换行符以外的任意字符
*包括0个的任意个字符
{2}同时出现两次前面的字符
非贪婪匹配模式,即匹配尽可能短的字符串
\w大小写字母,数字,下划线
herf链接,比如r'herf="(http.*?)"'
  

模拟登录、验证码

使用cookie的验证用户的验证状态,cookie的手动获取可通过右键审查元素的方法。自动的方法需要提交表单登录,然后获取保存cookie

验证码一般通过:手动输入,图像转字符技术,云打码平台(将验证码、点击下图中的XX等在线反给标注人员,并记录选中图像实际标签)。

存储图片

# 方法一
import requests
img_data=requests.get(img_url).content#二进制内容
with open (str(img_title)+'.jpg','wb') as f:
    f.write(img_data)

# 方法二
import urllib.request as req
link = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=4233772603,2493444113&fm=26&gp=0.jpg'
req.urlretrieve(link, './1.jpg')

修正由于编码问题导致的中文乱码问题

使用ftfy库的fix_text方法

import requests
from ftfy import fix_text

data=requests.get('http://www.baidu.com')
print(data.text)
print(fix_text(data.text))

带页码翻页

以北京市医疗保障局为例:

http://ybj.beijing.gov.cn/2020_zwfw/2020_bmcx/202002/t20200217_1644107.html

翻页方式如下图:

在网页右击->选择检查->打开Network信息-》点击其他页面翻页-》看list里的headers信息

Referer是实际要爬的url,右下方 form data提交了页面的page信息。

对这种需要提交页码的网页,爬虫请求时,提交page信息,脚本如下:

import requests
from bs4 import BeautifulSoup
url = 'https://fw.ybj.beijing.gov.cn/ddyy/ddyy/list'

for page in range(2):  # 爬前2页
    pagedata = {"page":(None, str(page+1))}
    data = requests.get(url, params=pagedata)
    soup = BeautifulSoup(data.text, 'lxml')

自动翻页

不需要翻页,下拉自动加载更多图片的,推测为ajax请求,可用百度图库感受一下

https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=python

在网页右击->选择检查->打开Network信息-》下拉翻页-》点击XHR-》查看headers信息里的Request url-》查看response信息

对response进行json在线解析,可知‘thumbURL’包含了图像url信息。

request url信息为

https://image.baidu.com/search/acjson?tn=resultjson_com&logid=11441412425879201126&ipn=rj&ct=201326592&is=&fp=result&queryWord=python&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=&z=&ic=&hd=&latest=&copyright=&word=python&s=&se=&tab=&width=&height=&face=&istype=&qc=&nc=1&fr=&expermode=&force=&pn=90&rn=30&gsm=5a&1614001042128=

其中‘pn=90&rn=30’表示每次请求30个数据(最大可设置为60),从第90个开始显示,有点查数据库limit pn,pn+rn 的意思。word是我查询的词汇,将这些信息放在request的参数里。https://image.baidu.com/search/acjson是实际请求request的url

import requests
word = 'python编程'
page_img_n = 60  # 设置一页69个图像
url = 'https://image.baidu.com/search/acjson'
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}

for page in range(1, 3):  #爬第一页到第三页
    data = {'word': word, 'pn': page * page_img_n, 'rn' : page_img_n, 'tn' : 'resultjson_com', 'ipn' : 'rj'}
    ret = requests.get(url, headers=header, params=data)
    print(ret)
    print(ret.url)
    print(ret.content.decode())

还有一种简单一点的方法,不用把参数都写成字典的形式,直接把request url抄下来,改一下参数。以必应为例:

Request URL:

https://cn.bing.com/images/async?q=python%e7%bc%96%e7%a8%8b&first=101&count=35&relp=35&tsc=ImageBasicHover&datsrc=I&layout=RowBased&mmasync=1&dgState=x*366_y*1161_h*184_c*2_i*71_r*15&IG=C502AAA6EEEF494F87DA1B21193FD0DE&SFX=3&iid=images.5533

import urllib
from bs4 import BeautifulSoup
word = 'python编程'
page_img_n = 60  # 设置一页69个图像
url = 'https://cn.bing.com/images/async?q={}&first={}&count=35&relp=35&tsc=ImageBasicHover&datsrc=I&layout=RowBased&mmasync=1&dgState=x*366_y*1161_h*184_c*2_i*71_r*15&IG=C502AAA6EEEF494F87DA1B21193FD0DE&SFX=3&iid=images.5533'
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}

for page in range(1, 2):  # 爬第一页到第三页
    # UTF-8编码
    InputData = urllib.parse.quote(word)
    ret = urllib.request.Request(url.format(InputData, str(page*35)), headers=header)  # 从page*35开始的35张
    res = urllib.request.urlopen(ret)
    soup = BeautifulSoup(res.read(), 'html.parser')

    # BeautifulSoup的对象可查看特定class的信息
    for item in soup.select('.iusc'):
        # 通过类属性查看url
        link = eval(item.attrs['m'])['murl']
        print(link)

 

 

---------------------------------------------------------------------------------------
常见报错处理:

  • Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

缺少html解析器

pip install lxml

  • 不信任的镜像源

不用镜像或者改pip配置文件

pip install bs4 

  • csv中中文信息乱码

CSV是用UTF-8编码的,而EXCEL是ANSI编码,若想使保存的csv文件用excel打开时可以正常显示中文,则:

1)在保存文件时设置编码方式  encoding=‘ANSI’   

result.to_csv('douban.csv',index=None,encoding='ANSI')

2)或者用记事本打开,另存为时选择ANSI编码方法

 

 

参考代码:

https://github.com/shenxiangzhuang/PythonDataAnalysis

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值