今天因为需要做了一个爬取知网博硕士论文及中国专利的爬虫,在制作的过程中遇到了不少坑,在网上查资料时都是很老的资源,在现在知网的反爬虫下不起作用,所以我来写这篇文章来供大家参考。(这篇文章主要介绍通过改写获得的网址来避开知网的反爬机制,完成普通文章和以表格为主体的html代码的信息的抓取)
这篇代码主要是抓取指望中关键字为保护渣的博硕士论文以及中国专利信息,其中中国专利信息较难抓取,主要是因为专利的信息在表格中,而表格又是动态的,代码末尾处有提示如何改代码,你可以通过改写代码中key的值,改变抓取内容的关键字,也可以更改抓取的文献内容代码后面有介绍。
代码如下。(代码中每一步都注释的很清楚)
# -*- coding: utf-8 -*-
import time
import re
import random
import requests
import pymysql
from bs4 import BeautifulSoup
headers = {
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, sdch',
'Accept-Language':'zh-CN,zh;q=0.8',
'Connection':'keep-alive',
'Host':'www.cnki.net',
'Referer':'http://search.cnki.net/search.aspx?q=%E4%BD%9C%E8%80%85%E5%8D%95%E4%BD%8D%3a%E6%AD%A6%E6%B1%89%E5%A4%A7%E5%AD%A6&rank=relevant&cluster=zyk&val=CDFDTOTAL',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
}
headers1 = {
'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',
'Connection':'keep-alive',
'Cookie':'Ecp_ClientId=6200426191000935476; SID_sug=111054; cnkiUserKey=c53f825c-b99b-59f4-a41e-dc2604699e98; ASP.NET_SessionId=ut2fqnilpd51bjijpcaxzyfz; SID_search=201087; UM_distinctid=171b64edb7c40c-07684554dd81b4-9393265-144000-171b64edb7d643; Ecp_IpLoginFail=200427221.192.179.83; CNZZDATA2643871=cnzz_eid%3D980108062-1587900042-%26ntime%3D1587975276; CNZZDATA3636877=cnzz_eid%3D1649504557-1587900840-%26ntime%3D1587975276',
'Host':'search.cnki.net',
'Referer':'http://search.cnki.net/search.aspx?q=%e4%bf%9d%e6%8a%a4%e6%b8%a3&rank=relevant&cluster=all&val=',
'Upgrade-Insecure-Requests':'1',
}
#注意,这里一定要设置两个请求头,知网有双重检查,用自己的也行去网上找也行。
connection = pymysql.connect('localhost', 'root', '1234567', 'zhiwang',
charset='utf8')
cursor = connection.cursor() # 打开mysql数据库的连接。
#下面定义一个函数来获得每一篇文章的链接并放在一个列表中。
def get_url_list(start_url):
depth = 10#=========================================================这里可以设置爬取每一种文献的页数,一页有15条信息================================================================================
url_list = []
i=1
for i in range(depth):
try:
url = start_url + "&p=" + str(i * 15)#分析页面网址特征,发现共同点,例如http://search.cnki.net/Search.aspx?q=%E4%BF%9D%E6%8A%A4%E6%B8%A3&rank=relevant&cluster=zyk&val=CCNDTOTAL&p=15里的15决定了你所在的页面。
search = requests.get(url.replace('\n', ''), headers=headers1)#注意设置请求头。
soup = BeautifulSoup(search.text, 'html.parser')
for art in soup.find_all('div', class_='wz_tab'):
if art.find('a')['href'] not in url_list:
rule = '.*aspx?(.*)'
url1 = re.findall(rule, art.find('a')['href'])
url_ture = 'https://kns.cnki.net/KCMS/detail/detail.aspx' + url1[0]
url_ = url_ture
url_list.append(url_)#将获取的网址加入到网址列表中。
print(url_)
#if下面的语句很重要,这里是将获得的网址进行转换,换成我们可以使用的网址。
print("爬取第" + str(i) + "页成功!")
time.sleep(random.randint(1, 3))#设置睡眠时间,防止被服务器屏蔽。
except:
print("爬取第" + str(i) + "页失败!")
return url_list
#下面定义一个函数来从文章页面获得我们要提取的信息。
def get_data(url_list, wordType):
try:
for url in url_list:
if url == pymysql.NULL or url == '':
continue
try:
html = requests.get(url.replace('\n', ''), headers=headers)
print(html)
soup = BeautifulSoup(html.text, 'html.parser')
except:
print("获取网页失败")
try:
if soup is None:
continue
#获取标题
title = soup.find('title').get_text().split('-')[0]
# 获取摘要
summary = 0#用summary==0来判断summary是那种文献中的然后提取。
try:
summary = soup.find('span', id='ChDivSummary').get_text()#博硕士论文中摘要的提取,如果不是博硕士论文则不会赋值,接下来会进入中国专利的论文提取。
except:
summary=0
if summary == 0:
relu = '.*?(.*) '
a = soup.find_all('td', attrs={'class': 'checkItem', 'colspan': '3'})
summary = str(a[2]).replace('\n', '').replace(' ', '')
rule='(.*?) '
summary = re.findall(rule,summary)[0]#中国专利的摘要提取
if summary == 0:
summary = '摘要类型不符合要求'#特殊类型处理
except:
print("部分获取失败")
pass
print("【Title】:" + title)
print("【url】:"+url)
print("【summary】:" + summary)
cursor.execute('INSERT INTO yingwen VALUES (%s,%s, %s)', (title, url,summary))#将获取的信息放到数据库里。
connection.commit()
print("爬取完毕")
finally:
print()
if __name__ == '__main__':
try:
for wordType in ["CMFDTOTAL","CDFDTOTAL","SCPD"]:#这个列表中放的是你想要爬取的文献类型(博士论文或是中国专利。)代码的末尾有对照的信息。
key='保护渣'#改变这里可以改变你爬取文献的关键字。
start_url = "http://search.cnki.net/search.aspx?q=%s&rank=relevant&cluster=zyk&val=%s" % (key,wordType)#拼接网址
url_list = get_url_list(start_url)
print("开始爬取")
get_data(url_list, wordType)
print("一类数据爬取完毕")
print("全部爬取完毕")
finally:
connection.close()#抓取完成,关闭连接。
'''"CDFDTOTAL":博士论文
"CMFDTOTAL":硕士论文
"SCPD": 中国专利'''
在爬取时要注意的的问题:
首先,要设置双请求头,请求头中信息尽量完整。 我们在网站中获得信息页的网址并不是真正的网址,例如那我们从页面中获得的详情页的网址如这个网址http://epub.cnki.net/grid2008/brief/detailj.aspx?filename=1019146259.nh&dbname=CDFDLAST2019
这个是我们获得的网址但是我们点开之后会发现这个链接并不能直接进入详情页,而是跳转到了首页,
原创文章 3获赞 3访问量 105
关注
私信
展开阅读全文
作者:踩坑专业户