cookie网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息,通过在客户端记录的信息确定用户身份。cookie可以用于反爬,针对这种情况,需要在请求头部中添加cookie,才能在爬取时获得想要的信息。
网站举例:2020年有一段时间要浏览知乎内容,会自动跳转到登陆界面,强制要求登录才能浏览。(目前不再强制要求)
以知乎热榜https://www.zhihu.com/hot为例。首先在浏览器中登录账号,登录之后可以拿到cookie。许多要求登录的网站都有针对cookie的反爬机制,在爬虫里没有添加cookie或者cookie不对,都不能拿到想要的数据。
爬取网站时一般都要添加请求头部,该头部是一个字典,我们在浏览器中拿到请求头部的字符串的形式如下:
'''
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Cookie: BAIKE_SHITONG=%7B%22data%22%3A%22657c3a8ab130bf
'''
可以用查找替换和正则表达式很方便地将字符串转为字典的形式
查找栏输入:(.+): (.+)$
替换栏输入:"$1": "$2",
import requests
url = 'https://www.zhihu.com/hot'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/87.0.4280.88 Safari/537.36',
'cookie': '_xsrf=1SMkDEbBof93pTCRd5MmPz8cmmOuAsaU; _zap=3a8fd847-c5d4-45cf-84a3-24d508f580f6; '
'_ga=GA1.2.2058930090.1594280819; d_c0="AICeuVa2jBGPTuvzpsC3VFkq3TulCqxCfNQ=|1594280816"; tshl=; '
'q_c1=7c1d10a0c4d44df7827bd63892a65ad9|1607330850000|1602672699000; '
'r_cap_id="NmUwNzZjZDRjYTdhNDM4ODg2YTlkNmZkYTkxNjE3Zjk=|1607510595'
'|a6f49873875ddab93fe0ea6af008d72f5b96f328"; '
'cap_id="ZWY2YWYwZjQxMzEwNDBjZDhhNTUyNGE4NTEyYzM3MDk=|1607510595'
'|baf8c8f94ab9f64c28903ff63e86885944f8b9e9"; '
'l_cap_id="MmQ0MjMwYzlkZDgyNGZmZGI5YTgxYzY5ZjJiNDZlZGM=|1607510595'
'|3a728f63321b9be4977408d133ceeecc661802b4"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1607330701,'
'1607493058,1607510544,1608122090; '
'capsion_ticket="2|1:0|10:1608122089|14:capsion_ticket|44:ZTdmNjMyMGFiNWJkNDNkYTk5YzI2MmI5M2M5MjY5ZmU'
'=|f187b250302c7a498c8c732fcd607826b412c49c64a39eb7b6047c9860a40f7b"; '
'SESSIONID=36rAEHCFhr1qyxSxYpI5oe64a5Bl7J5Rh8rx4GF0B89; '
'JOID=V14dBUzOhEkq2abnFM1FVigSNGkI_rw1ap7tqlyk9XZVody3Yil6n3bYq-cbXHSWbCgf_7Nw3niJHKJtQ0JRyG0=; '
'osd=V1oSB0_OgEYo2qbjG89GViwdNmoI-rM3aZ7ppV6n9XJao9-3ZiZ4nHbcpOUYXHCZbisf-7xy3XiNE6BuQ0Zeym4=; '
'z_c0="2|1:0|10:1608122116|4:z_c0|92'
':Mi4xRjdYeENBQUFBQUFBZ0o2NVZyYU1FU1lBQUFCZ0FsVk5CRTNIWUFES1pINUJzUjZxOU1tQm5XZi1xdjdyeUdPVGN3'
'|068ae1decd315ee1b801a77a0883209667cfbf783ef837728ce15dce546b8556"; '
'unlock_ticket="AJAuW3hlfA0mAAAAYAJVTQwG2l8id1FVAAOGj42l8skGeU5lNRJLHg=="; '
'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1608122118; tst=h; '
'KLBRSID=975d56862ba86eb589d21e89c8d1e74e|1608122129|1608122089 '
}
res = requests.get(url, headers=headers)
print(res.content.decode('utf-8'))
HTTP是无状态协议,服务端需要记录用户状态就用某种机制来识别用户,这个机制就是Session。session保存在服务端,有唯一标识。session用来确定用户的身份和保持会话
模拟登录的案例:
需求:突破12306的图片验证码 {result_message: “验证码校验成功”, result_code: “4”},获取车次、剩余座位信息
12306网站采用了ajax技术,爬取车次信息时会发现在网页中有数据而在网页的源码中没有该数据。
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
针对这种情况,我们需要找到在车次信息查询页面上点击查询按钮时的request url,爬取该url才能获得想要的数据
分析:获取图片验证码的网址为:
https://kyfw.12306.cn/passport/captcha/captcha-check?
访问该url应当用post方式,在发起请求时在post的data中传递正确图片的xy坐标。data形式如下,answer对应验证码坐标。
codeStr = input('请输入验证码坐标:')
data = {
'answer': codeStr,
'rand': 'sjrand',
'login_site': 'E'
}
这个坐标可以用qq的截图功能获得,从整张验证码图片的左上角开始截取,鼠标放在正确图片的位置,这时可以要截取图片的像素大小,这就是要用的xy坐标。如果有多个图片,比如图片1、图片2,坐标的填写方式应该是x1,y1,x2,y2
# {result_message: "验证码校验成功", result_code: "4"}
import requests
req = requests.session() # 保持会话
def login():
# 获取图片
pic_response = req.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
codeImage = pic_response.content
fn = open('code2.png', 'wb')
fn.write(codeImage)
fn.close()
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/87.0.4280.88 Safari/537.36 '
}
codeStr = input('请输入验证码坐标:')
data = {
'answer': codeStr,
'rand': 'sjrand',
'login_site': 'E'
}
response = req.post('https://kyfw.12306.cn/passport/captcha/captcha-check', data=data, headers=headers)
print(response.content.decode('utf-8'))
login()
爬取这种网站需要在requests.get函数中传递verify参数,值为False
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/87.0.4280.88 Safari/537.36 '
}
url = 'https://inv-veri.chinatax.gov.cn/'
res = requests.get(url, headers=headers, verify=False)
print(res.text)
python自带正则表达式相关的模块,名称为re
import re
# re.match(pattern, string, flags=0)
# 第一个参数 正则表达式的模块
# 第二个参数 表示要匹配的数据
# 第三个参数 标致位 用于控制正则表达式的匹配方式 例如 是否区分大小写、是否多行匹配
s = 'python and java'
pattern = 'python'
result = re.match(pattern, s)
if result:
print(result.group())
print(result.start())
print(result.end())
print(result.span())
else:
print('没有匹配到')