菜单

澳门金沙国际听大人讲Python对知网(CNKI)主题文献爬虫

2019年3月25日 - 金沙编程资讯

不久前在演练写爬虫的时候,正巧同学的女对象有要求,大致是爬取知网内的几千个大旨的数额,每二个核心的条数记录有几条的到几千条的两样,总来的来说也好不不难个上万数据级的爬虫了,分析了下知网,发现使用标准检索,能够成功自己的目的,然后经过chrome的developer
tools差不离分析了下了请求数据包,发现知网的询问是分成两步的,第贰步是1个总的请求(查询的规格基本上都在率先步里面了),会回来3个串

博客园已经济体改为了爬虫的篮球场,本文利用Python中的requests库,模拟登陆果壳网,获取cookie,保存到本地,然后这一个cookie作为登陆的凭证,登陆腾讯网的主页面,爬取微博主页面上的难点和呼应难点答疑的摘要。

有关今日头条验证码登陆的标题,用到了Python上2个至关心重视要的图形处理库PIL,假若不行,就把图纸存到本地,手动输入。

初稿刊载在本身的个人微信公众号上,欢迎关怀: 

查找了半数以上材质,反爬虫策略只是为了让爬虫更扑朔迷离,更麻烦,方今貌似没有能一劳永逸的方案。

澳门金沙国际 1

爬取今日头条的严重性的某些:模拟登陆

通过对搜狐登陆是的抓包,能够发现登陆网易,须要post多少个参数,2个是账号,一个是密码,多少个是xrsf。
其一xrsf隐藏在表单里面,每一回登陆的时候,应该是服务器随机发生3个字符串。全体,要效仿登陆的时候,必须求得到xrsf。

用chrome (或许火狐 httpfox 抓包分析)的结果:

image.png

之所以,必供给获得xsrf的数值,注意那是二个动态变化的参数,每一次都差异。

image.png

注意findall和find_all函数的差别。

获得xsrf,下边就足以如法泡制登陆了。
利用requests库的session对象,建立三个对话的利益是,能够把同3个用户的不等请求联系起来,直到会话截止都会活动处理cookies。

image.png

留意:cookies
是当前目录的二个文本,这几个文件保留了果壳网的cookie,借使是首先个登陆,那么自然是从未那些文件的,不能够通过cookie文件来登陆。必须求输入密码。

def login(secret, account):
    # 通过输入的用户名判断是否是手机号
    if re.match(r"^1\d{10}$", account):
        print("手机号登录 \n")
        post_url = 'https://www.zhihu.com/login/phone_num'
        postdata = {
            '_xsrf': get_xsrf(),
            'password': secret,
            'remember_me': 'true',
            'phone_num': account,
        }
    else:
        if "@" in account:
            print("邮箱登录 \n")
        else:
            print("你的账号输入有问题,请重新登录")
            return 0
        post_url = 'https://www.zhihu.com/login/email'
        postdata = {
            '_xsrf': get_xsrf(),
            '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_code)
        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'])
    session.cookies.save()
try:
    input = raw_input
except:
    pass

那是登陆的函数,通过login函数来登陆,post 自身的账号,密码和xrsf
到搜狐登陆认证的页面上去,然后拿走cookie,将cookie保存到当前目录下的文件之中。下次登陆的时候,直接读取那一个cookie文件。

#LWP-Cookies-2.0
Set-Cookie3: cap_id="\"YWJkNTkxYzhiMGYwNDU2OGI4NDUxN2FlNzBmY2NlMTY=|1487052577|4aacd7a27b11a852e637262bb251d79c6cf4c8dc\""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:37Z"; version=0
Set-Cookie3: l_cap_id="\"OGFmYTk3ZDA3YmJmNDQ4YThiNjFlZjU3NzQ5NjZjMTA=|1487052577|0f66a8f8d485bc85e500a121587780c7c8766faf\""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:37Z"; version=0
Set-Cookie3: login="\"NmYxMmU0NWJmN2JlNDY2NGFhYzZiYWIxMzE5ZTZiMzU=|1487052597|a57652ef6e0bbbc9c4df0a8a0a59b559d4e20456\""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:57Z"; version=0
Set-Cookie3: q_c1="ee29042649aa4f87969ed193acb6cb83|1487052577000|1487052577000"; path="/"; domain=".zhihu.com"; path_spec; expires="2020-02-14 06:09:37Z"; version=0
Set-Cookie3: z_c0="\"QUFCQTFCOGdBQUFYQUFBQVlRSlZUVFVzeWxoZzlNbTYtNkt0Qk1NV0JLUHZBV0N6NlNNQmZ3PT0=|1487052597|dcf272463c56dd6578d89e3ba543d46b44a22f68\""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:57Z"; httponly=None; version=0

那是cookie文件的情节

以下是源码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
try:
    import cookielib
except:
    import http.cookiejar as cookielib
import re
import time
import os.path
try:
    from PIL import Image
except:
    pass

from bs4 import BeautifulSoup


# 构造 Request headers
agent = 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'
headers = {
    "Host": "www.zhihu.com",
    "Referer": "https://www.zhihu.com/",
    'User-Agent': agent
}

# 使用登录cookie信息
session = requests.session()
session.cookies = cookielib.LWPCookieJar(filename='cookies')
try:
    session.cookies.load(ignore_discard=True)
except:
    print("Cookie 未能加载")



def get_xsrf():
    '''_xsrf 是一个动态变化的参数'''
    index_url = 'https://www.zhihu.com'
    # 获取登录时需要用到的_xsrf
    index_page = session.get(index_url, headers=headers)
    html = index_page.text
    pattern = r'name="_xsrf" value="(.*?)"'
    # 这里的_xsrf 返回的是一个list
    _xsrf = re.findall(pattern, html)
    return _xsrf[0]





# 获取验证码
def get_captcha():
    t = str(int(time.time() * 1000))
    captcha_url = 'https://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()
    # 用pillow 的 Image 显示验证码
    # 如果没有安装 pillow 到源代码所在的目录去找到验证码然后手动输入
    try:
        im = Image.open('captcha.jpg')
        im.show()
        im.close()
    except:
        print(u'请到 %s 目录找到captcha.jpg 手动输入' % os.path.abspath('captcha.jpg'))
    captcha = input("please input the captcha\n>")
    return captcha





def isLogin():
    # 通过查看用户个人信息来判断是否已经登录
    url = "https://www.zhihu.com/settings/profile"
    login_code = session.get(url, headers=headers, allow_redirects=False).status_code
    if login_code == 200:
        return True
    else:
        return False


def login(secret, account):
    # 通过输入的用户名判断是否是手机号
    if re.match(r"^1\d{10}$", account):
        print("手机号登录 \n")
        post_url = 'https://www.zhihu.com/login/phone_num'
        postdata = {
            '_xsrf': get_xsrf(),
            'password': secret,
            'remember_me': 'true',
            'phone_num': account,
        }
    else:
        if "@" in account:
            print("邮箱登录 \n")
        else:
            print("你的账号输入有问题,请重新登录")
            return 0
        post_url = 'https://www.zhihu.com/login/email'
        postdata = {
            '_xsrf': get_xsrf(),
            '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_code)
        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'])
    session.cookies.save()
try:
    input = raw_input
except:
    pass



## 將main的問題列表輸出在shell上面
def  getPageQuestion(url2):  
  mainpage = session.get(url2, headers=headers)
  soup=BeautifulSoup(mainpage.text,'html.parser')
  tags=soup.find_all("a",class_="question_link")
  #print tags

  for tag in tags:
    print tag.string

# 將main頁面上面的問題的回答的摘要輸出在shell上面
def getPageAnswerAbstract(url2):
    mainpage=session.get(url2,headers=headers)
    soup=BeautifulSoup(mainpage.text,'html.parser')
    tags=soup.find_all('div',class_='zh-summary summary clearfix')

    for tag in tags:
       # print tag
        print tag.get_text()
        print '詳細內容的鏈接 : ',tag.find('a').get('href')


def getPageALL(url2):
    #mainpage=session.get(url2,headers=headers)
    #soup=BeautifulSoup(mainpage.text,'html.parser')
    #tags=soup.find_all('div',class_='feed-item-inner')
    #print "def getpageall "
    mainpage=session.get(url2,headers=headers)
    soup=BeautifulSoup(mainpage.text,'html.parser')
    tags=soup.find_all('div',class_='feed-content')
    for tag in tags:
        #print tag
        print tag.find('a',class_='question_link').get_text()
        # 這裏有一點問題 bs 還是用的不是太熟練
        #print tag.find('a',class_='zh-summary summary clearfix').get_text()
        #print tag.find('div',class_='zh-summary summary clearfix').get_text()


if __name__ == '__main__':
    if isLogin():
        print('您已经登录')
        url2='https://www.zhihu.com'
        # getPageQuestion(url2)
        #getPageAnswerAbstract(url2)
        getPageALL(url2)
    else:
        account = input('请输入你的用户名\n>  ')
        secret = input("请输入你的密码\n>  ")
        login(secret, account)

运转结果:

image.png

澳门金沙国际 2

以下的策略只是扩张爬虫的难度,增加爬虫开销。

接下来才能做第壹步的多少请求(下方的截图对应网页上的不等区域的呼吁报文头和再次来到数据)

git链接:

https://github.com/zhaozhengcoder/Spider/tree/master/spider\_zhihu

本文介绍使用Python爬虫技术连忙得到知网一千多篇有个别主旨的稿子的题材,作者,笔者单位,引用次数,下载次数,揭橥刊物,发布时间,以及文摘。

1.Headers限制

澳门金沙国际 3

反省User-Agent属性,判断是不是为浏览器访问。

检查Referer属性,判断来自。

澳门金沙国际 4

PPS:笔者所精通的爬虫与反爬虫策略

反爬虫最基本的方针:

  1. 反省浏览器http请求里面包车型地铁user-agent字段
  2. 检查http请求的referer(即眼下的那几个页面是从哪个页面跳转过来的)

爬虫策略:
那三个都以在http协议的报文段的反省,同样爬虫端能够很便宜的装置这个字段的值,来自欺欺人服务器。

反爬虫进阶策略:
1.像博客园一样,在登录的表单里面放入1个隐藏字段,里面会有1个任意数,每一次都不平等,那样除非您的爬虫脚本能够分析那一个自由数,不然下次爬的时候就老大了。
2.记下走访的ip,总计访问次数,假设次数太高,能够认为那个ip不寻常。

爬虫进阶策略:
1.像那篇小说提到的,爬虫也能够先解析一下隐藏字段的值,然后再拓展模拟登录。
2.爬虫能够使用ip代理池的主意,来幸免被察觉。同时,也得以爬一会休息一会的法门来下降功效。此外,服务器依据ip访问次数来实行反爬,再ipv6没有健全推广的一代,这些策略会很简单导致加害。(这些是自小编个人的领会)。

反爬虫进进阶策略:
1.数目投毒,服务器在本身的页面上停放很多藏匿的url,那么些url存在于html文件文件之中,可是经过css大概js使他们不会被出示在用户看到的页面上边。(确定保证用户点击不到)。那么,爬虫在爬取网页的时候,很用可能取访问那些url,服务器能够百分百的觉得那是爬虫干的,然后可以回来给他有的谬误的数额,只怕是拒绝响应。

爬虫进进阶策略:
1.相继网站固然要求反爬虫,可是不能把百度,谷歌(Google)如此的搜寻引擎的爬虫给干了(干了的话,你的网站在百度都说搜不到!)。那样爬虫应该就足以伪造是百度的爬虫去爬。(可是ip大概恐怕被查出,因为你的ip并不是百度的ip)

反爬虫进进进阶策略:
给个验证码,让你输入今后才能登录,登录之后,才能访问。

爬虫进进进阶策略:
图像识别,机器学习,识别验证码。但是那些理应对比难,恐怕说耗费相比较高。

参考资料:
廖雪峰的python教程
静觅的python教程
requests库官方文书档案
segmentfault下面有一人的关于网易爬虫的博客,找不到链接了

上学爬虫开头,作者就想着对CNKI核心文献进行爬虫,对感兴趣的大旨文章进行抓取,获取相关小说的着力音信和摘要,方便快速了然某叁个世界的商量进程,重点等等。

以下是网上征集的拿走不到HTTP_REFERE本田CR-V值的境况:

① 在浏览器内平昔敲UEscortL

② windows桌面上的超链接图标

③浏览器内书签

④第壹方软件(如Word,Excel等)内容中的链接

⑤SSL认证网站跳入

⑥;
meta页面设置自动跳转时,在example.com将取不到REFERETiggo ULANDL

⑦使用JavaScript的Location.href或者是Location.replace()

那应该是最普遍的,最中央的反爬虫手段,主假使早先判断你是或不是是真实的浏览器在操作。

                                                                     
 图一.询问记录请求报文头

由此持续的改动,终于完毕此目标。

2.IP限制

限制IP也是累累网站反爬虫的初衷,有个旁人不管写贰个巡回,就从头暴力爬取
,确实会给网站服务器带来一点都不小的承担,而那种频仍的访问,鲜明也不会是真心诚意用户作为,索性果断把您封掉。

当然,攻击者能够通过不停换IP的方式来绕过那种范围。而且封IP会流失用户,一般景色下不会选拔。

澳门金沙国际 5

在此爬虫程序编写制定过程,需求小心多少个难题。

3.动态加载

透过异步加载,一方面是为了反爬虫,一方面也足以给网页浏览带来区别的体会,达成越来越多的效果。很多动态网站都以经过ajax恐怕JavaScript来加载请求的网页。

                                                                       
图二. 对应分化年份的笔录条数重临结果

1. 增选适合的网站输入;

4.验证码

给用户请求次数加3个阀值,超越该阀值,弹出验证码界面。

有关缘何要分成两步,每一个区域对应1个例外的请求,那些都以网站本人的布署,笔者也没做过web开发,这么做有啥亮点作者的确不知底/擦汗,小编的基本点就是仿照它在网页上的伸手,实现批量化的数额获得。

诚如大家进来知网是,www.cnki.net,小编发现对此网站实行爬取,难以获得完整的网站源码,最终发现
能博得完全源码。

5.回到伪造的信息

分明该请求为爬虫请求后,重回虚假混乱的数码扩展筛选复杂度。

以下是引用sexycoder的观点:

反爬虫最基本的政策:

1.反省浏览器http请求里面包车型大巴user-agent字段

2.检查http请求的referer(即当前的那一个页面是从哪个页面跳转过来的)

爬虫策略:

那八个都以在http协议的报文段的反省,同样爬虫端可以很有益的设置那么些字段的值,来自欺欺人服务器。

反爬虫进阶策略:

1.像腾讯网一样,在签到的表单里面放入一个隐藏字段,里面会有三个随便数,每趟都区别,那样除非您的爬虫脚本能够分析这一个自由数,否则下次爬的时候就不行了。

2.笔录走访的ip,总计访问次数,若是次数太高,能够认为那几个ip有毛病。

爬虫进阶策略:

1.像那篇小说提到的,爬虫也得以先解析一下隐藏字段的值,然后再开始展览模拟登录。

2.爬虫能够应用ip代理池的艺术,来制止被发觉。同时,也足以爬一会休息一会的不二法门来下滑效能。别的,服务器根据ip访问次数来进展反爬,再ipv6没有周详推广的时期,那些方针会很不难导致风险。

反爬虫进进阶策略:

1.多少投毒,服务器在大团结的页面上放置很多隐形的url,这么些url存在于html文件文件之中,然则经过css大概js使她们不会被出示在用户观察的页面下面。(确定保证用户点击不到)。那么,爬虫在爬取网页的时候,很用大概取访问这一个url,服务器能够百分之百的觉得那是爬虫干的,然后能够回去给她有个别错误的数目,可能是不容响应。

爬虫进进阶策略:

1.各种网站即便必要反爬虫,可是不可见把百度,谷歌(谷歌(Google))这般的探寻引擎的爬虫给干了(干了的话,你的网站在百度都说搜不到!)。那样爬虫应该就能够以假乱真是百度的爬虫去爬。(不过ip恐怕恐怕被查出,因为你的ip并不是百度的ip)

反爬虫进进进阶策略:

给个验证码,让您输入以后才能登录,登录之后,才能访问。

爬虫进进进阶策略:
图像识别,机器学习,识别验证码。然则这些应该比较难,大概说开销比较高。  

 

澳门金沙国际 6

然后,差不离就摸清楚了那3个数据获得的长河,笔者的思路是先成功3个数目级的多少得到,也正是爬取一条,然后再去扩张,加线程,加ip代理,加user_agent等等。

2. 解析网站U凯雷德L:

在那几个阶段,主要的思路正是基本上要和在网页上的走访保持一致,有限支撑本人拼的url和在网页上访问的时候是均等的,当然是在保管能访问的前提下,能略去的就略去。

将图中的UXC60L复制出来,得到下边包车型地铁U普拉多L:
urllib.unquote() 解码。

解析它原先的呼吁url的时候,使用url转码工具得以将转码现在的url还原,更直白地分析。

解析解码后的ULANDL:
;通过增选分裂的排序,差异的摸索关键词,以及不一致的文献类型,能够明确”q=”字段控制搜索的重中之重词,”rank=” 控制排序情势,“p=” 字段控制了翻页,
并且步长为15。
最后鲜明搜索UCR-VL为:url=’

接下来提多少个细节呢,知网的请求url上,有局地数量段一开端是不了然它的意思的,不过自个儿去拼接待上访问的时候发现,缺了网站就会报错,那时候就足以多尝试多少个不一样的走访,去拿它的请求heads,然后互绝相比,就会意识一些字段是稳定不变的,那种就能够直接照搬,有的吧,是变化的,那种就需求细致去分析到底是什么数据,有啥样含义,知网的就回顾1个皮秒数,那么些本人一伊始就没懂具体意思,后来分析了下感到像时光,然后去取了下当前的纳秒时间,一比较发现差不多是基本上,就当下的皮秒时间拼在了url串上边。

3. 转码难点:

def getMilliTim():
    t = time.time()
    nowTime = t*1000
    return int(nowTime)

在爬取网页进度中,发现赢得的网页源码打字与印刷出来后,是乱码,最后发现是因为网页源码的编码格局并不是UTF-8,因而,为了拿走能够用于解析的的网页源码,须要对网页源码实行转码,首先从原始编码方式转化为通用型的Unicode,然后再转码为:UTF-8,
转码情势:

假使您须求1个优质的上学调换条件,那么你能够设想Python学习调换群:548377875;
尽管您供给一份系统的学习资料,那么你可以考虑Python学习调换群:548377875。

f=requests.get(test,headers=headers)                   #  获得网页源码

简而言之,就是对于有些懂web的爬虫小白,最棒便是还原网站原本的呼吁,那样基本上请求数据就不会有太大标题了。

ftext=f.text.encode(f.encoding).decode(‘utf-8’)     # 
转码成能够分析的编码

在做到了数量级为一的级别后,就起来准备大范围地获取数据了,那时候就要考虑功效以及幸免网站踢人了。

4. 代理IP问题:

在面临了种种socket 10054
10061等颠倒是非,通过百度各种技术,加上了ip代理等部分艺术,最后我要么到位这次任务,当然最后依然增加了文件读取,职务队列等模块,大约正是1个线程专责输出文件,其它五个线程去职责池里面取职分爬数据,详细略过,见代码。有纰漏之处,还请斧正。

在爬虫进程中,爬取少量网页和爬取多量网页存在较大差异。爬取较少网页是,被爬的服务器不会拒绝,当访问过多,就可能造成拒绝访问,被挡住IP的题材。那些时候就须要运用代理IP去拜访。
代理IP完结“遮人耳目”之计,让被访问的服务器呈现的IP地址是爬虫程序设定的IP,而非总括机真实的IP地址,纵然发现是爬虫程序,被屏蔽的IP是代理IP,而非真实的电脑IP地址。

对CNKI网站进行爬虫时,发现当爬取450篇新闻后,IP
就会被挡住,须要填写验证码,导致力不从心连接爬取,因此须求安装代理IP。 
代理IP地址能够去部分网站去爬取,本程序使用了:

5. 分功能设置函数:

为了使得代码逻辑清晰,能够分分歧的目标设置不相同的函数。注意各类函数之间的参数字传送递,不难出错。

6. 网站源码本人的不规则:

在测试程序进度中,大多数稿子爬取成功,但是,存在小一些文章爬取失利,遵照道理,编码一样话,那应该而且打响,同时战败。采纳爬取“成功”和“战败”两篇小说的网页源码,发现存在分化,需要通过技术处理,获得一致结果:

例如:if len(ftext_r.xpath(‘//ul[@class=”break”]/li/text()’))==3:

ws.cell(row=num+1,
column=6).value=ftext_r.xpath(‘//ul[@class=”break”]/li[2]/text()’)[0]

ws.cell(row=num+1,
column=7).value=ftext_r.xpath(‘//ul[@class=”break”]/li[3]/text()’)[0]

if len(ftext_r.xpath(‘//ul[@class=”break”]/li/text()’))==4:

ws.cell(row=num+1,
column=6).value=ftext_r.xpath(‘//ul[@class=”break”]/li[3]/text()’)[0]

ws.cell(row=num+1,
column=7).value=ftext_r.xpath(‘//ul[@class=”break”]/li[4]/text()’)[0]

此处 ul 标签 class属性为 break 下 大概存在4 li 标签, 也能是3个li标签,全部通过判断语句,然后分别处理获取需求的音信。

7. 关键点设置提醒新闻:

在爬取较多网页时,难保障不出难题,必要不断改进程序的适应度,不过,若果出现难点,逐一网页排查难点的工作量太大。能够在每页爬取的时候唤醒是或不是爬取成功。

经过那么些提示新闻,就能够一本万利的一贯到某些出难题的网页,方便排查。

# —————————————

全部Python爬虫代码

#(代码补充表明:标注“参数设置”后边的代码中得以经过不难修改,就能够爬取不一致主旨,分裂页数,使用不一致的代理IP

*—————————————

#!/usr/bin/env python3

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图