csdn搜索结果按照阅读数排序

基于这个博主代码的进一步开发https://blog.csdn.net/chenwh_cn/article/details/97647127

三个参数
第一个是要搜索的关键字
第二个是排序后返回前多少项(默认=10)
第三个是遍历的页数(默认=20)(去除广告,一页有10~20条返回结果)
如果是-1就是遍历所有结果,如果你搜的词比较大众,返回结果很多那就停不下来了,目前没有写提前中止的代码,如果写的话应该是用kbhit

python csdn.py 扫雷 20 -1

或者也可以手动

import csdn
c=csdn.Csdn('扫雷',20)
c.run(-1)

注意点
line18改成自己chromedriver.exe的路径,没安装的自己百度
line57&58改成自己的github账号密码

2019/9/29更新:
修正csdn登录框的xpath,由于国庆节小改版导致= ω \omega ω=
修正github登录键的xpath,原因未知
增加了保存到csv文件的函数,采用pandas库的dataframe.to_csv()
如果没有这个库可以自己装一下,本来是用在深度学习的,我这里图方便借用一下

import sys
import time
import re#regular expression
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys

 
class Csdn():
    def __init__(self, searchStr, displayCount):
        self.searchStr = searchStr
        self.displayCount = displayCount
        self.retList = []
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        options.add_argument('log-level=3')
        self.driver = webdriver.Chrome(executable_path=r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe', options=options)
        
    def sortResult(self):
        print('sorting')
        def sortKey(item):
            #匹配字符串中的数字
            counts = re.findall(r"\d+", item[0])
            return int(counts[0])
        #从大到小
        self.retList.sort(key=sortKey, reverse=True)
        
    def displayResult(self):
        if self.displayCount > len(self.retList):
            self.displayCount = len(self.retList)
        for retItem in self.retList[:self.displayCount]:
            print('{0:>10} {1}  {2}'.format(retItem[0],retItem[1],retItem[2]))

    def loginByGithub(self,driver):
        '''
        登录账号,否则不能看后几页的内容
        我采用的是github登录
        用qq会比较麻烦
        '''
        print('使用github登录中')
        print('点击主页登录按钮')
        #driver.find_element_by_xpath('//*[@id="csdn-toolbar"]/div/div/ul/li[4]/a[1]').click()
        driver.find_element_by_xpath('//*[@id="csdn-toolbar"]/div/div/ul/li[3]/a').click()
        
        #弹出一个新界面,切换过去
        handles = driver.window_handles
        csdn0=handles[0]
        csdnLogin=handles[1]
        driver.switch_to.window(csdnLogin)
        print(driver.current_url)
        #点击社交账号登录
        driver.find_element_by_xpath('//*[@id="app"]/div/div/div[1]/div[2]/div[5]/ul/li[4]').click()
        #点击github图标,验证少,容易实现
        driver.find_element_by_xpath('//*[@id="app"]/div/div/div[1]/div[2]/div[5]/ul/li[5]/a[5]').click()
        #弹出github界面,切换过去,如果之前登录过github则是直接成功,需要考虑
        driver.switch_to.window(driver.window_handles[2])
        print(driver.current_url)
        driver.find_element_by_id('login_field').send_keys('youraccount')
        driver.find_element_by_id('password').send_keys('yourpassword')
        #driver.find_element_by_xpath('//*[@id="login"]/form/div[2]/input[7]').click()
        driver.find_element_by_xpath('//*[@id="login"]/form/div[2]/input[8]').click()

        #把多余的界面关掉
        driver.switch_to.window(csdn0)
        driver.close()
        driver.switch_to.window(csdnLogin)
        driver.close()
        #切换回登录过的csdn主界面
        driver.switch_to.window(driver.window_handles[0])

    def run(self,maxPage=20):
        driver = self.driver
        driver.get('https://blog.csdn.net/')
        print(driver.current_url)
        self.loginByGithub(driver)

        driver.find_element_by_id('toolber-keyword').send_keys(self.searchStr)
        driver.find_element_by_id('toolber-keyword').send_keys(Keys.RETURN)
        handles = driver.window_handles
        driver.close()
        driver.switch_to.window(handles[1])
        #结果数
        numStr=driver.find_element_by_class_name('page-nav').find_element_by_class_name('text').text
        print(numStr)
        print('返回搜索1~{}页的整合结果'.format(maxPage))
        
        i=0
        zeroNum=0
        while(True):
            i+=1
            if not((i<=maxPage)or(maxPage==-1)):break
            url='https://so.csdn.net/so/search/s.do?p={pageNum}&q={searchStr}&t=blog&domain=&o=&s=&u=&l=&f='.format(pageNum=i,searchStr=self.searchStr)
            driver.get(url)
            #获取一页搜索结果的list
            sList=driver.find_elements_by_xpath("//dl[@class='search-list J_search']")
            if len(sList)==0:break#遍历完所有结果了
            ret=0
            for s in sList:
                try:
                    strs=s.find_element_by_class_name('author-time').text.split()
                    title=s.find_element_by_xpath('dt/div/a[1]').text
                    if self.searchStr in title:
                        ret+=1
                        self.retList.append((strs[4],strs[3],title))
                except BaseException:
                    #没有阅读数显示时会被捕获
                    continue
            print('page:{},ret:{}'.format(i,ret))

            #如果遇到一大串0就提前中止
            if ret==0:
                zeroNum+=1
                if zeroNum>5:break
            else:
                zeroNum=0

        self.sortResult()
        self.displayResult()
        self.saveToCsv()
        driver.close()
        driver.quit()
  
    def saveToCsv(self):
        import pandas as pd
        df=pd.DataFrame(self.retList)
        if self.displayCount > df.shape[0]:
            saveCount=df.shape[0]
        else:
            saveCount=self.displayCount
        timeStr=time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) 
        csv_name='{}@{}.csv'.format(self.searchStr,timeStr)
        df[:saveCount].to_csv(csv_name,sep=',',header=False,index=True,encoding='gbk')
        print('save to csv successfully')

if __name__ == '__main__':
    argc=len(sys.argv)
    if argc==1:
        searchStr="验证码识别"
        displayCount=20
        pageMax=5
    else:
        searchStr=sys.argv[1]
        if argc==2:
            displayCount=10
            pageMax=20
        elif argc==3:
            displayCount=int(sys.argv[2])
            pageMax=20
        else:
            displayCount=int(sys.argv[2])
            pageMax=int(sys.argv[3])
    csdn = Csdn(searchStr, displayCount)
    csdn.run(pageMax)

几个关键点

1.如果不登录只能看搜索结果的第一页

  目前使用github登录,因为没有验证码。一开始想用qq的,为了绕开滑块验证码,使用的方法是先在电脑上手动登录qq然后网页快捷登录。但是不知道为什么find_element找不到元素,明明确实在浏览器中可以检索到。

2.

  虽然csdn下面的导航栏只有1~20但是是可以通过改url跳到后面几页的,体现在line89这行代码,pageNum是几就是第几页,也不用find_element在点击导航按钮,更快捷
url=‘https://so.csdn.net/so/search/s.do?p={pageNum}&q={searchStr}&t=blog&domain=&o=&s=&u=&l=&f=’.format(pageNum=i,searchStr=self.searchStr)

3.csdn按相关度排序

  初版的时候,我查看了一下返回的结果,很糟糕,有很多都和关键字毫不相关= =。我手动更改url跳到后面几页,发现150页之后都没什么大关系了,有的文章,只是中间提到了一次关键字,但主题不是这个,具体分布可以看最后的图。如果说这些阅读数很高,那就会把前面相关度高但是阅读数低的顶掉了。解决方法没有采用页数限制,因为不同关键字的这个分水岭页数不一样;采用了标题栏中有关键字的文章才放入。具体见line99

4

  需要改进的地方主要是效率,搜索结果随随便便就几百页。需要多线程开多个浏览器同时爬虫。顺带一提,一个浏览器应该不能对多个窗口开多个线程操作,因为find_element只能找当前窗口的元素,会互相干扰





运行结果

关键字“验证码识别”
在这里插入图片描述

相关度调查

  虽然没有直接对每篇文章具体含有多少关键字进行分析,但是通过对每页所有的返回结果分析,标题中含关键字的比例确实随着页数增多而逐渐下降。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值