基于Python对知网(CNKI)主题文献爬虫

原文发表在我的个人微信公众号上,欢迎关注: 

基于Python对知网(CNKI)主题文献爬虫_第1张图片

本文介绍使用Python爬虫技术快速获取知网1000多篇某个主题的文章的题目,作者,作者单位,引用次数,下载次数,发表刊物,发表时间,以及文章摘要。

学习爬虫开始,我就想着对CNKI主题文献进行爬虫,对感兴趣的主题文章进行抓取,获取相关文章的基本信息和摘要,方便快速了解某一个领域的研究进程,重点等等。

经过不断的修改,终于完成此目的。

在此爬虫程序编写过程,需要注意几个问题。

1. 选择合适的网站入口;

一般我们进入知网是,www.cnki.net,我发现对此网站进行爬取,难以获取完整的网站源码,最后发现 http://search.cnki.net/ 能得到完整源码。

基于Python对知网(CNKI)主题文献爬虫_第2张图片

2. 分析网站URL:

将图中的URL复制出来,得到下面的URL:http://search.cnki.net/search.aspx?q=%E7%B2%BE%E5%87%86%E6%89%B6%E8%B4%AB&rank=citeNumber&cluster=all&val=&p=0发现被编码了,需要对复制出来的URL使用 urllib.unquote() 解码。

分析解码后的URL:http://search.cnki.net/search.aspx?q=精准扶贫&rank=citeNumber&cluster=all&val=CJFDTOTAL&p=0 ;通过选择不同的排序,不同的搜索关键词,以及不同的文献类型,可以确定 "q="字段控制搜索的关键词,"rank=" 控制排序方式,“p=” 字段控制了翻页, 并且步长为15。 最终确定搜索URL为:url='http://search.cnki.net/search.aspx?q='+str(keywords)+'&rank=citeNumber&cluster=all&val=CJFDTOTAL&p='+'number'。

3. 转码问题:

在爬取网页过程中,发现得到的网页源码打印出来后,是乱码,最终发现是因为网页源码的编码方式并不是UTF-8,因此,为了得到可以用于解析的的网页源码,需要对网页源码进行转码,首先从原始编码方式转化为通用型的Unicode,然后再转码为:UTF-8, 转码方式:

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

ftext=f.text.encode(f.encoding).decode('utf-8')     #  转码成可以分析的编码

4. 代理IP问题:

在爬虫过程中,爬取少量网页和爬取大量网页存在较大区别。爬取较少网页是,被爬的服务器不会拒绝,当访问过多,就可能造成拒绝访问,被屏蔽IP的问题。这个时候就需要使用代理IP去访问。 代理IP实现“瞒天过海”之计,让被访问的服务器显示的IP地址是爬虫程序设定的IP,而非计算机真实的IP地址,就算发现是爬虫程序,被屏蔽的IP是代理IP,而非真实的计算机IP地址。

对CNKI网站进行爬虫时,发现当爬取450篇信息后,IP 就会被屏蔽,需要填写验证码,导致无法连续爬取,因此需要设置代理IP。  代理IP地址可以去一些网站去爬取,本程序使用了:http://www.xicidaili.com/nt/提供的免费代理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

# -*- coding: utf-8 -*-

"""

Created on Thu Nov  9 21:37:30 2017

@author: liu kuanbin

"""

#-加载将会使用到的函数库

import requests                                   # 读取网页

from lxml import etree                         # 用于解析网页

from openpyxl import Workbook         # 创建表格并用于数据写入

from bs4 import BeautifulSoup            # 解析网页

import random                                      # 随机选择代理Ip

#--获得代理IP列表

def get_ip_list(urlip,headers2):

web_data = requests.get(urlip,headers=headers2)

soup = BeautifulSoup(web_data.text, 'lxml')

ips = soup.find_all('tr')

ip_list = []

for k in range(1, len(ips)):

ip_info = ips[k]

tds = ip_info.find_all('td')

ip_list.append(tds[1].text + ':' + tds[2].text)

return ip_list

#-从代理IP列表里面随机选择一个

def get_random_ip(ip_list):

proxy_list = []

for ip in ip_list:

proxy_list.append('http://' + ip)

proxy_ip = random.choice(proxy_list)

proxies = {'http': proxy_ip}

return proxies

#-定义获取文章列表对应的链接的函数

def get_data(urllist,headers,proxies):

j=0    # 初始化j的取值

for urli in urllist:

try:

j=j+1

num=15*(i-pagestart)+j    # 第多少篇

test=str(urli)

# 是否使用代理去爬虫就在下面这一行代码中,是否添加: proxies=proxies

f=requests.get(test,headers=headers)          #  设置Headers项; 这里添加是否使用代理去访问:

ftext=f.text.encode(f.encoding).decode('utf-8')    # 对具体进行转码,获得可以正常读取的文档;

ftext_r=etree.HTML(ftext)                                     # 对具体页进行 xpath 解析;

ws.cell(row=num+1, column=1).value='第'+str(num)+'篇文章信息'

ws.cell(row=num+1, column=2).value=str(ftext_r.xpath('//title/text()')[0]).replace(' - 中国学术期刊网络出版总库','')   # 获得文章标题

ws.cell(row=num+1, column=3).value=str(ftext_r.xpath('//div[@class="author summaryRight"]/p[1]/a/text()'))         # 获得作者名字

#---------------------------

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]

if len(str(ftext_r.xpath('//div[@class="author summaryRight"]/p[2]/a/text()')))==2:

ws.cell(row=num+1, column=4).value=str(ftext_r.xpath('//div[@class="author summaryRight"]/p[3]/a/text()'))# 获得作者单位

else:

ws.cell(row=num+1, column=4).value=str(ftext_r.xpath('//div[@class="author summaryRight"]/p[2]/a/text()'))

# str(ftext_r.xpath('//div[@class="author summaryRight"]/p[2]/a/text()'))

ws.cell(row=num+1, column=5).value=ftext_r.xpath('//div[@id="weibo"]/input/@value')[0]# 第一作者及所属刊物及时间

ws.cell(row=num+1, column=8).value=str(ftext_r.xpath('//span[@id="ChDivKeyWord"]/a/text()'))# 文章关键词

ws.cell(row=num+1, column=9).value=ftext_r.xpath('//span[@id="ChDivSummary"]/text()')[0]# 获得文章摘要

print('爬虫'+str(15*(pageend-pagestart+1))+'篇文章信息的第'+str(num)+'篇爬取成功!!')

except:

print('爬虫第'+str(i)+'页中的第'+str(j)+'篇爬虫失败')

#---创建表格,待接收数据信息---#

wb = Workbook()    # 在内存中创建一个workbook对象,而且会至少创建一个 worksheet

ws = wb.active       #  获取当前活跃的worksheet,默认就是第一个worksheet

ws.cell(row=1, column=1).value ="No"

ws.cell(row=1, column=2).value ="Title"

ws.cell(row=1, column=3).value ="Author"

ws.cell(row=1, column=4).value ="Institute"

ws.cell(row=1, column=5).value ="Journal"

ws.cell(row=1, column=6).value ="Cites"

ws.cell(row=1, column=7).value ="Download"

ws.cell(row=1, column=8).value ="Keywords"

ws.cell(row=1, column=9).value ="Abstart"

#---------------参数设置

if __name__=='__main__':

pagestart=1

pageend=90

keywords='精准扶贫'  ### 查询的主题

url='http://search.cnki.net/search.aspx?q='+str(keywords)+'&rank=citeNumber&cluster=all&val=CJFDTOTAL&p='

urlip = 'http://www.xicidaili.com/nt/'         # 提供代理IP的网站

headers={

'Referer':'http://search.cnki.net/search.aspx?q=qw:%e7%b2%be%e5%87%86%e6%89%b6%e8%b4%ab&cluster=all&val=&p=0',

'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',

'Cookie':'cnkiUserKey=158f5312-0f9a-cc6a-80c1-30bc5346c174; Ecp_ClientId=4171108204203358441; UM_distinctid=15fa39ba58f5d2-0bbc0ba0169156-31637c01-13c680-15fa39ba5905f1; SID_search=201087; ASP.NET_SessionId=glrrdk550e5gw0fsyobrsr45; CNZZDATA2643871=cnzz_eid%3D610954823-1510276064-null%26ntime%3D1510290496; CNZZDATA3636877=cnzz_eid%3D353975078-1510275934-null%26ntime%3D1510290549; SID_sug=111055; LID=WEEvREcwSlJHSldRa1FhcTdWZDhML1NwVjBUZzZHeXREdU5mcG40MVM4WT0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!',

}

headers2={

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'

}

#------------------------------------------

for i in range(pagestart,pageend+1):

try:

## 得到一个代理 IP

ip_list = get_ip_list(urlip,headers2)        # 获得代理IP列表

proxies = get_random_ip(ip_list)            # 获得随机的一个代理IP

# 获得每一页里面文章的 urllist

url_all=url+str(15*(i-1))

#获得每一页的文章具体文章信息页面的链接

response=requests.get(url_all,headers=headers)        # 获得网页源码   ,proxies=proxies

# print(utf16_response.decode('utf-16'))

file=response.text.encode(response.encoding).decode('utf-8')  # 对网页信息进行转化成为可以正常现实的 UTF-8格式

r=etree.HTML(file)                                            # 获取网页信息,并且解析 使用xpath

urllist=r.xpath('//div[@class="wz_content"]/h3/a[1]/@href')   # 获得当前页所有文章的进入链接

# 获得每页urllist的文章信息,并且存到构建的表格中

get_data(urllist,headers,proxies)

except:

print('第'+str(i)+'页在爬取时候发生错误')

wb.save('知网文章信息汇总.xlsx')     # 最后保存搜集到的数据

最终爬取到的数据:

基于Python对知网(CNKI)主题文献爬虫_第3张图片

通过得到的数据资料,可以用于接卸来的分析,研究“精准扶贫”此类主题文献的各种信息。例如: 那些单位发表的论文最多, 通过词云图可以看出此类文章主要的研究方向等等,可以用于各种有意思的分析。

你可能感兴趣的:(基于Python对知网(CNKI)主题文献爬虫)