接上一篇,Python爬虫——爬取知网论文数据(一)
上一篇谈到了如何爬取知网的论文标题和论文作者,这一篇讲一下如何爬取多页,以及如何爬取作者的详细信息。
1. 换页
同样的,我们在搜索结果页按下F12查看网页源代码,将光标定位到翻页按钮上;
#page2 #第二页的selector#page3 #第三页的selector#page4 #第四页的selector
很显然,他们的selector只变了后面的数字,这个数字就是页数。根据这个规律就可以写出一个换页的函数:
# pn表示当前要爬的页数def change_page(driver, pn): driver.find_element_by_CSS_selector('#page' + str(pn)).click() time.sleep(5) content = driver.page_source.encode('utf-8') soup = BeautifulSoup(content, 'lxml') return soup
每次爬取完一页之后就可以调用这个函数切换到下一页,再次爬取下一页的内容。
2. 爬取作者详细信息
首先我们点进某个作者的页面,到地址栏查看url
再点进另一个作者页看一下,其url为:
对比两者可以发现他们的skey、code和v这三个参数不同,由此可知这三个参数影响着你访问的页面内容,其中skey就是当前的作者名。
我们回到搜索结果页,同样F12查看源代码,将光标定位到某个作者名上:
从上图中可以看到,href属性的scode和acode就是上述我们需要的code参数,可是这个v参数是什么呢,这里也没有给出,我们先将skey和code这两个参数替换到url中试一下,如找到作者陈恒
从中拿出skey=陈恒,code=29972400,放入刚才的url中。
可以看到,我们成功访问到了陈恒这个作者的详细信息。那么接下来我们就可以取出每一个作者的名字和a标签href属性的scode值,来作为url的skey和code参数。
代码如下:
# 获取作者详情页url的skey和code, 传入参数是一个a标签def get_skey_code(a): skey = a.get_text().strip() href = str(a.get('href')) # 拿到a标签href的值 code = href[href.find('acode') + 6:] # 拿到code的值 return skey, code
上述代码中传入的a标签在上一篇Python爬虫——爬取知网论文数据(一)中有讲,就是包含作者名的a标签。
现在我们拿到了访问作者详情页的url,要获取作者的信息就很方便了,以陈恒作者为例,在详情页按下F12:
可以看到作者的大学和专业分别对应了第一个和第二个H3标签,获取到这两个标签,并拿出里面的文本信息即可:
h3 = soup.find_all('h3') # 拿到所有h3元素college = h3[0].get_text().strip() # 第一个h3里是大学major = h3[1].get_text().strip() # 第二个h3里是专业
这样我们就拿到了作者的大学和专业信息。如果想获取更多别的信息,可以照着这个方法获取其他元素。
至此,重点部分就结束了,下面贴一下我最后的代码,做了一些封装和一些空值处理,并将爬取到的数据存入了csv文件。
''' 知网论文数据爬取'''from bs4 import BeautifulSoupfrom selenium import webdriverimport timeimport requestsimport csv# 定义论文类class Paper: def __init__(self, Title, authors): self.Title = Title self.authors = authors# 定义作者类class Author: def __init__(self,name, college, major): self.name = name self.college = college self.major = major# 进入知网首页并搜索关键词def driver_open(driver, key_word): url = "https://www.cnki.net/" driver.get(url) time.sleep(2) driver.find_element_by_CSS_selector('#txt_SearchText').send_keys(key_word) time.sleep(2) # 点击搜索按钮 driver.find_element_by_CSS_selector('body > div.wrapper.section1 > div.searchmain > div > div.input-Box > input.search-btn').click() time.sleep(5) content = driver.page_source.encode('utf-8') # driver.close() soup = BeautifulSoup(content, 'lxml') return soupdef spIDer(driver, soup, papers): tbody = soup.find_all('tbody') tbody = BeautifulSoup(str(tbody[0]), 'lxml') tr = tbody.find_all('tr') for item in tr: tr_bf = BeautifulSoup(str(item), 'lxml') td_name = tr_bf.find_all('td', class_ = 'name') td_name_bf = BeautifulSoup(str(td_name[0]), 'lxml') a_name = td_name_bf.find_all('a') # get_text()是获取标签中的所有文本,包含其子标签中的文本 Title = a_name[0].get_text().strip() print("Title : " + Title) td_author = tr_bf.find_all('td', class_ = 'author') td_author_bf = BeautifulSoup(str(td_author), 'lxml') a_author = td_author_bf.find_all('a') authors = [] # 拿到每一个a标签里的作者名 for author in a_author: skey, code = get_skey_code(author) # 获取作者详情页url的skey和code name = author.get_text().strip() # 获取学者的名字 print('name : ' + name) college, major = get_author_info(skey, code) # 在作者详情页获取大学和专业, major是一个数组 au = Author(name, college, major) # 创建一个学者对象 authors.append(au) print('\n') paper = Paper(Title, authors) papers.append(paper) time.sleep(1) # 每调一次spIDer休息1s# pn表示当前要爬的页数def change_page(driver, pn): driver.find_element_by_CSS_selector('#page' + str(pn)).click() time.sleep(5) content = driver.page_source.encode('utf-8') soup = BeautifulSoup(content, 'lxml') return soup# 获取作者详情页url的skey和code, 传入参数是一个a标签def get_skey_code(a): skey = a.get_text().strip() href = str(a.get('href')) # 拿到a标签href的值 code = href[href.find('acode') + 6:] # 拿到code的值 return skey, code# 获取作者的详细信息def get_author_info(skey, code): url = 'https://kns.cnki.net/kCMS/detail/knetsearch.aspx?dbcode=CAPJ&sfIEld=au&skey=' + skey + '&code=' + code + '&v=3lODiQyLcHhoPt6DbD%25mmd2FCU9dfuB5GXx8ZJ7nSrKZfD6N9B5gKP9Ftj%25mmd2B1IWA1HQuWP' header = { 'user-agent': 'Mozilla/5.0 (windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.133 Safari/569.36', 'Connection': 'close' } requests.packages.urllib3.disable_warnings() rsp = requests.get(url, headers = header, verify = False) rsp_bf = BeautifulSoup(rsp.text, 'lxml') div = rsp_bf.find_all('div', class_ = 'wrapper') # 有的学者查不到详细信息 if div: div_bf = BeautifulSoup(str(div[0]), 'lxml') h3 = div_bf.find_all('h3') college = h3[0].get_text().strip() major = h3[1].get_text().strip() # major = major.split(';')[0: -1] print('college:' + college) print('major: ' + major) return college, major print("无详细信息") return None, Noneif __name__ == '__main__': driver = webdriver.Chrome("D:/Software/chorme/chromedriver.exe") soup = driver_open(driver, '知识图谱') # 搜索知识图谱 papers = [] # 用于保存爬取到的论文 # 将爬取到的论文数据放入papers中 spIDer(driver, soup, papers) for pn in range(2, 31): content = change_page(driver, pn) spIDer(driver, content, papers) driver.close() # 写入文件 f_papers_authors = open('./paper_author.csv', 'w', enCoding = 'utf-8', newline = '') writer_p_a = csv.writer(f_papers_authors) # 基于文件对象构建 csv写入对象 writer_p_a.writerow(["name", "college", "major", "paper"]) # csv文件的表头 # 读取每一篇论文 for paper in papers: # 写入paper_author.csv文件 for author in paper.authors: if author.name: # print(author + " ") writer_p_a.writerow([author.name, author.college, author.major, paper.Title]) # 关闭文件 f_papers_authors.close()
我爬到的数据:
以上是内存溢出为你收集整理的Python爬虫——爬取知网论文数据(二)全部内容,希望文章能够帮你解决Python爬虫——爬取知网论文数据(二)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)