2021SC@SDUSC
简介
根据项目进度安排,需要爬取百度学术生成数据集来测试不同模型的性能表现。然而在实际爬取时遇到了例如页面重复、页面无法访问等问题。
页面重复问题描述及解决方案
在爬取结束后发现出现了大量的重复页面,一方面浪费了大量时间,另一方面去重需要花费额外的经历。起初,我尝试将页面的第一篇论文题目作为该页面的唯一标识,通过集合来去重,然而这种方式依然无法避免时间浪费的问题。
通过对于算法和百度文库的进一步分析,问题源头逐渐浮出水面。在最初的爬虫程序中有一个page_num参数,表示期望爬取的页面数量。通过对url中“pn=?”的替换实现了对所有检索的遍历。
next_page = fir_page.replace("pn=10", "pn={:d}".format(i * 10))
然而部分关键词的检索结果达不到page_num的数值,例如搜索“检索”只有68页

当pn=?的数值超过临界值时,百度学术的处理方式是回退到第一页,然后继续爬取,正因上述机制,出现了页面重复的问题。
为了解决该问题,我对页面进行了进一步分析。当页面存在下一页是会由一个右箭头,如图:

可以对页面进行分析来确定是否存在右箭头,如果存在右箭头,那么可以继续遍历,逻辑如下:
next_icon_soup = soup_new.find(id='page')
if next_icon_soup == None:
# 为none时整个页面都为none
print('None_for_next')
continue
next_icon_soup2 = next_icon_soup.find_all('a')[-1].find(class_='c-icon-pager-next')
if next_icon_soup2 == None:
break
然而在解决该问题时我发现在访问某些页面时返回结果是乱码,此时next_icon_soup2一定为None,即便存在下一页也被迫退出。因此我首先获取next_icon_soup2的父元素,如果父元素不存在,那么一定说明返回结果是乱码,将该页忽略。
页面无法访问问题描述及解决方案
正如前文所提到的,在访问某些页面时返回结果可能为乱码,这对去重也造成了一定的困难,只是单纯的忽略会造成大量数据丢失。引起该问题的根源可能是网站的反爬虫机制,因此最初的想法是每次爬取后睡眠1s来避免被发现,然而效果并不理想。
进一步分析,我尝试对无法访问的页面更换爬虫的访问头,更换后正常访问。基于此,我采取了如下机制:首先使用请求头A进行爬取,如果返回为乱码,更换请求头B,如果仍为乱码再次更换请求头A,因此类推,当更换超过10次仍不能访问后,放弃该页面。采取此机制大多数页面均可正常爬取。
接下来的问题是如何判断爬取的结果为乱码。经过分析,我发现乱码的页面有一个元素类名为“timeout-img”,当页面中出现该元素时,将该页面判定为无法访问的页面。
time_out = soup_new.find(class_='timeout-img')
if time_out_num > 10:
fail_num += 1
flag = False
print('fail...')
break
该部分整体实现如下:
while time_out != None:
time_out_num += 1
time.sleep(1)
print(next_page)
print(' timeout...')
response = requests.get(next_page,headers = headers2)
soup_new = BeautifulSoup(response.text, "lxml")
# 检查是否超时
time_out = soup_new.find(class_='timeout-img')
if time_out_num > 10:
fail_num += 1
flag = False
print('fail...')
break
小结
解决了上述问题后,爬虫正常运行并构建了符合要求的数据集。
运行结果如下(关键词:牛肉):

部分数据集截图如下:

完整代码:
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import pandas as pd
import requests
import re
from collections import defaultdict
headers = {
'Use

最低0.47元/天 解锁文章
3080

被折叠的 条评论
为什么被折叠?



