前言
最近看到猪哥的爬虫教程后,自己还是很想试一试的。也是偶然的契机,发现了黑客派这个论坛。这才有了下面这个脚本
import requests
# requests V2.21.0
from bs4 import BeautifulSoup as bs
# beautifulsoup4 V4.8.0
# 保存 cookie
session = requests.Session()
# 登录
def login_hacpai():
login_url = 'https://hacpai.com/login'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
'Referer':'https://hacpai.com/login'}
raw_data = {"nameOrEmail":"hahahhahah",
"userPassword":"hahahahahha", "captcha":""}
try:
request = session.post(login_url, headers=headers, json=raw_data)
request.raise_for_status()
except requests.exceptions.HTTPError as err:
print('登录失败!','HTTPError: {}'.format(err))
except Exception as err:
print('登录失败!', 'error: {}'.format(err))
else:
result = request.text.split(',')
respons_ls = result[:2]
result_ls =[]
for i in respons_ls:
result_ls.append(i.split(":")[1])
return result_ls
# 获取签到链接
def get_url():
url = 'https://hacpai.com/activity/daily-checkin'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
'Referer':'https://hacpai.com/'}
try:
request = session.get(url, headers=headers)
respons = request.text
class_= "module__body ft__center vditor-reset"
soup = bs(respons, 'lxml').find('div', class_=class_)
# sign_url_soup = soup.find_all('a', class_="btn green")
for i in soup('a'):
link = i.get('href')
return link
except (SyntaxError, ImportError,
UnicodeEncodeError, AttributeError) as err:
print('error: {}'.format(err))
except Exception as err:
print('请求失败!', 'error: {}'.format(err))
# 签到
def sign(url):
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
'Referer':'https://hacpai.com/activity/checkin'}
try:
request = session.get(url, headers=headers)
request.raise_for_status()
except requests.exceptions.HTTPError as err:
print('请求失败!','HTTPerror: {}'.format(err))
except Exception as err:
print('请求失败!', 'error: {}'.format(err))
else:
respons = request.text
soup = bs(respons, 'lxml').find('div', class_="vditor-reset")
for s in soup.div.strings:
s = s.replace(' ', '')
print(s,end=' ')
def main():
sign_in_url = 'https://hacpai.com/activity/checkin'
result_ls = login_hacpai()
if result_ls[0] == 'false':
print('登录失败!', result_ls[1], sep='\n')
else:
print('登录成功!')
url = get_url()
if url == None:
print('未找到签到链接。')
elif 'points' in url:
print('今日你已经签过到了。')
print('可以点击或复制链接:{} 查看‘.format(sign_in_url))
else:
sign(url)
if __name__ == "__main__":
main()
在写这个脚本的过程中遇到了不少问题:
- 模拟登录
在模拟登录的过程中遇到了第一个问题:
用户名,密码都对,就是无法登录。
import requests
session = requests.Session()
login_url = 'https://hacpai.com/login'
headers = {...}
data = {...}
try:
request = session.post(login_url, headers=headers)
request.raise_for_status()
except requests.exceptions.HTTPError as err:
print('登录失败!','error: {}'.format(err))
except Exception as err:
print('登录失败!', 'error: {}'.format(err))
else:
print(request.text)
''' 输出结果 '''
{"sc":false,"msg":"用户不存在"}
后来参考了 @mufengcoding 的脚本,发现传入的表单数据是 JSON 类型的。于是导入 json 库(注:省略号表示没有改动过的代码)
import requests
import json
...
raw_data = {...}
try:
request = session.post(login_url, headers=headers, json=raw_data)
request.raise_for_status()
except:
...
...
然后阅读官方文档发现还有更简单的写法
此处除了可以自行对 dict 进行编码,你还可以使用 json 参数直接传递,然后它就会被自动编码。这是 2.4.2 版的新加功能:
url = 'https://api.github.com/some/endpoint' payload = {'some': 'data'} r = requests.post(url, json=payload)
更改成如下代码:
import requests
...
headers = {...}
raw_data = {...}
try:
request = session.post(login_url, headers=headers,
json=raw_data)
request.raise_for_status()
2.获取签到链接
登录成功后,接下来的问题就是获取签到的链接。
在开发者工具里很容易在签到页面里获取到链接。我遇到的问题是如何把链接提取出来。通过观察签到链接除了域名,请求的资源路径外还有一个传给服务器的参数。通过关键词在网页源代码上查找,发现在 script 标签内发现了我想要的参数。我想,通过提取 script 标签里的内容把想要的值拿出来,写了下面功能:
from bs4 import BeautifulSoup as bs
...
def get_token():
url = '...'
headers = {...}
raw_data = {...}
request = requests.get(url, headers=headers)
respons = request.text
soup = bs(respons, 'lxml')
for i in soup.find('script').strings:
print(i)
...
但就是无法拿到我想要的值,输不出那个字典,不知是我的逻辑出现了问题,还是说这个想法本身就是有问题。
不过还好,我有了第二个想法,直接把链接提取出来,... 好吧,是我想太多
...
def get_url():
...
try:
request = session.get(url, headers=headers)
respons = request.text
soup = bs(respons, 'lxml')
for i in soup.find_all('a', class_="btn green"):
link = i.get('href')
return link
except Exception as err:
print('请求失败!', 'error: {}'.format(err))
...
3.输出签到结果
虽然说在这里获取标签里的值没什么大问题,但我还是要在这感谢我那个麻烦的想法,它让我写这个功能的时候省了不少力。
最后
这还不是这个脚本的最终形态,里面还会加其他内容。(可能不是什么重要的内容,我对这个脚本的定位是复习学过的知识点)
源码
更新说明
- 增加友好输出
- 去除输出的响应和一些不必要的异常信息
参考链接
Requests 文档
Beautiful Soup 4.4.0 文档
python3.7 实现自动签到
猪哥爬虫专栏
签到活动更新
复习:字符串的操作方法,自定义函数,处理多种异常的不同写法,HTTP,文件的读取,列表,字典添加元素
get:爬虫一般步骤,requests, beautifulsoup 第三方库简单使用
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于