• [爬虫] 一起来爬知乎娘


    知乎内容需要登陆后才能查看,与之前案例不同,这里要向浏览器提交登录信息。

    首先爬取知乎登录页面

    def getHtmlText(url):
        try:
            r = requests.get(url)
            r.encoding = 'utf-8'
            return r.text
        except:
            return ''
    
    url = 'https://www.zhihu.com/'
    getHtmlText(url)
    '<html><body><h1>500 Server Error</h1>
    An internal server error occured.
    </body></html>
    '

    此时出现 500 Server Error,解决方法为通过 headers={...} 更改用户代理为浏览器

    def getHtmlText(url):
        headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
        try:
            r = requests.get(url, headers = headers)
            r.encoding = 'utf-8'
            return r.text
        except:
            return ''
    

    在知乎登录页面打开Chrome浏览器F12,这里打钩之后新跳转的页面的信息就不会覆盖之前接受到的信息,输入账号密码点击登录,就可以看到需要提交的表单数据。

    版本一:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    import requests
    import re
    import time
    from PIL import Image
    from bs4 import BeautifulSoup
    import json
    
    # 构造 Request headers
    # 登陆的url地址
    logn_url = 'http://www.zhihu.com/#signin'
    
    session = requests.session()
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
    }
    
    content = session.get(logn_url, headers=headers).content
    soup = BeautifulSoup(content, 'html.parser')
    
    
    def getxsrf():
        return soup.find('input', attrs={'name': "_xsrf"})['value']
    
    
    # 获取验证码
    def get_captcha():
        t = str(int(time.time() * 1000))
        captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
        r = session.get(captcha_url, headers=headers)
        with open('captcha.jpg', 'wb') as f:
            f.write(r.content)
            f.close()
        im = Image.open('captcha.jpg')
        im.show()
        im.close()
        captcha = input("please input the captcha
    >")
        return captcha
    
    
    def isLogin():
        # 通过查看用户个人信息来判断是否已经登录
        url = "https://www.zhihu.com/settings/profile"
        login_code = session.get(url, allow_redirects=False).status_code
        if int(x=login_code) == 200:
            return True
        else:
            return False
    
    
    def login(secret, account):
        # 通过输入的用户名判断是否是手机号
        if re.match(r"^1d{10}$", account):
            print("手机号登录 
    ")
            post_url = 'http://www.zhihu.com/login/phone_num'
            postdata = {
                '_xsrf': getxsrf(),
                'password': secret,
                'remember_me': 'true',
                'phone_num': account,
            }
        else:
            print("邮箱登录 
    ")
            post_url = 'http://www.zhihu.com/login/email'
            postdata = {
                '_xsrf': getxsrf(),
                'password': secret,
                'remember_me': 'true',
                'email': account,
            }
        try:
            # 不需要验证码直接登录成功
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = login_page.text
            print(login_page.status)
            print(login_code)
        except:
            # 需要输入验证码后才能登录成功
            postdata["captcha"] = get_captcha()
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = eval(login_page.text)
            print(login_code['msg'])
    
    
    if __name__ == '__main__':
    
        if isLogin():
            print('您已经登录')
        else:
            account = input('请输入你的用户名
    >  ')
            secret = input("请输入你的密码
    >  ")
            login(secret, account)
    

    存在问题:运到验证码为“点击图中倒立文字或移动滑块至”,则登陆失败,跳转到登录界面。听说可以用打码平台解决

    版本二(来自某知乎er):

    打开你要爬取信息的界面,发出请求查看所需 headers,比较重要的有 'User-Agent'‘cookie’,对应添加

    import requests
    import re
    
    url='https://www.zhihu.com/question/22591304/followers'
    headers={
    'User-Agent':
    'Cookie':}
    
    page=requests.get(url,headers=headers).text
    imgs=re.findall(r'<img src="(.*?)_m.jpg',page) 
    

     查看 imgs 即可看到匹配的图片

     

    以下是一段爬取知乎头像的代码:

    # -*- coding: utf-8 -*-
    #py3.6
    import requests
    import urllib
    import re
    import random
    from time import sleep
    
    def main():
        url='https://www.zhihu.com/question/22591304/followers'
        headers={ 'User-Agent':'', 'Cookie':''}
     
        i=1
        for x in range(20,40,20):
            data={'start':'0',
            'offset':str(i),
            '_xsrf':'2e65c02ceeaaa1ac16d193415cf8d5be'}
    
            page=requests.post(url,headers=headers,data=data,timeout=50).text
            imgs=re.findall(r'<img src=\"(.*?)_m.jpg',page) 
            #在爬下来的json上用正则提取图片地址,去掉_m为大图 
            for img in imgs:
                try:
                    img=img.replace('\','')
                    #去掉字符这个干扰成分
                    pic=img+'.jpg'
                    path='d:\zhihu\'+str(i)+'.jpg'
                    #声明存储地址及图片名称
                    urllib.request.urlretrieve(pic,path)
                    #下载图片
                    print(u'下载了第'+str(i)+u'张图片')
                    i+=1
                    sleep(random.uniform(0.5,1))
                    #睡眠函数用于防止爬取过快被封IP
                except:
                    pass
            sleep(random.uniform(0.5,1))
    
    if __name__=='__main__':
        main()
    

      

    貌似 get 和 post 方法返回的 .text 形式不一样, post 会用 \" 转义表示 ”,而 get 不会;

    另外,data 中 '_xsrf' 在 F12 Form Data 中没找到,但必不可少,难道隐藏了?要用抓包工具?

  • 相关阅读:
    java 根据对象属性排序
    无法初始化SFTP协议。主机是SFTP服务器吗
    Spring IOC 学习(三)IOC容器的依赖注入
    Spring-IOC学习-02 IOC容器初始化
    nginx简单使用
    Spring-IOC学习-01 IOC重要的几个接口定义
    Spring-IOC学习
    Http Service
    C#从入门到放弃--字符串类型转数字类型
    VS系列--快捷键的使用
  • 原文地址:https://www.cnblogs.com/P3nguin/p/7536825.html
Copyright © 2020-2023  润新知