python爬虫的东西

知网

image.png

这目录直接提取

image.png

<a class="fz14" href="/kns/detail/detail.aspx?QueryID=30&CurRec=2&dbcode=SOPD&dbname=SOPD2018&filename=USD828895(S1)" target="_blank">Trigger mechanism</a>

<a class="fz14" href="/kns/detail/detail.aspx?QueryID=30&CurRec=3&dbcode=SOPD&dbname=SOPD2018&filename=US10076922(B2)" target="_blank">Customizable document for producing a security document, customized security document and production of such a security document</a>

#这个是获取第二页的数据的方法,需要传入上面处理出来的页数
    def fanye(self,page):
        #第一页已经抓取了,从第二页开始,然后到最后一页
        for i in  range(2,page+1):
            #构造第二页的url
            page_url='http://kns.cnki.net/kns/brief/brief.aspx?curpage={0}&RecordsPerPage=50&QueryID=0&ID=&turnpage=1&tpagemode=L&dbPrefix=SCOD&Fields=&DisplayMode=listmode&PageName=ASP.brief_result_aspx&isinEn=0#J_ORDER&'.format(i)
            response=self.connect(page_url)
            soup=bs(response.text,'html.parser')
            #调用上面的获取详情的函数
            self.xq_url_get(soup)

image.png

<a href="?curpage=2&RecordsPerPage=20&QueryID=30&ID=&turnpage=1&tpagemode=L&dbPrefix=SCOD&Fields=&DisplayMode=listmode&PageName=ASP.brief_result_aspx&isinEn=0#J_ORDER&" title="键盘的“← →”可以实现快速翻页">2</a>

<a href="?curpage=3&RecordsPerPage=20&QueryID=30&ID=&turnpage=1&tpagemode=L&dbPrefix=SCOD&Fields=&DisplayMode=listmode&PageName=ASP.brief_result_aspx&isinEn=0#J_ORDER&" title="键盘的“← →”可以实现快速翻页">3</a>

目录提取,有img的有下一层。

image.png

image.png

image.png

目录是 NaviGroup

其这几个参数比较重要

Host: kns.cnki.net Referer: http://kns.cnki.net/kns/brief/result.aspx?dbprefix=CISD&catalogName=ZJCLS User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36

下面几个需要构造url

Query string parameters

code: A tpinavigroup: CISDtpiresult catalogName: ZJCLS __: Fri Oct 26 2018 18:31:53 GMT+0800 (中国标准时间)

image.png

其构造函数放在下面

  #底层的目录进行处理
    def children_tag(self):
        #由于是post请求,所以需要先构造相应的data
        from_data={
                 'ua':1.25,
                 'PageName': 'ASP.brief_result_aspx',
                 'DbPrefix': 'SCOD',
                 'DbCatalog': '专利数据总库',
                 'ConfigFile': 'SCOD.xml',
                 'db_opt': 'SCOD',
                 'db_value': '中国专利数据库,国外专利数据库',
                 'his': '0',
                 '__': '%s %s' % (time.strftime('%a %b %d %Y %H:%M:%S GMT+0800'), ' (中国标准时间)')}
        #遍历底层的目录
        for i in self.mulu_list:
            #底层目录的编号
            print(i)
            #需要传入的值,所以用字典的添加方式将值添加到from_data
            from_data['NaviCode']=i
            #这个访问的网站是做打开数据库的操作,让cookies出现在他们网页地图上,否则无法得到相应的数据
            ss = self.connect(searchHandler_url, data=from_data, mothed='POST')
            #访问失败则重新访问一次,如果还不可以则打印相应的url
            if ss==404:
                time.sleep(random.randint(5,7))
                ss = self.connect(searchHandler_url, data=from_data, mothed='POST')
                if ss==404:
                    print(searchHandler_url)
                else:
                    #成功则调用下面的函数,获得相应的数据页面
                    self.data_get()
            else:
                self.data_get()

image.png

Search页面的 fromdate 也很重要

action: 
NaviCode: A
catalogName: ZJCLS
ua: 1.25
isinEn: 0
PageName: ASP.brief_result_aspx
DbPrefix: CISD
DbCatalog: 标准数据总库
ConfigFile: CISD.xml
db_opt: CISD
his: 0
__: Fri Oct 26 2018 18:37:02 GMT+0800 (中国标准时间)
import requests, random,re
from settings import *
from multiprocessing import Process,queues
from bs4 import BeautifulSoup as bs

searchHandler_url='http://kns.cnki.net/kns/request/SearchHandler.ashx'
data_url='http://kns.cnki.net/kns/brief/brief.aspx'
mulu_list=['A','B','C','D','E','F','G','H','I','J']

# 连接类(——主要作用用requests访问页面——)
class Conect(object):
    #连接方法,用requests访问网站,有两种方法(post和get)
    def connect(self, url, proxies=None, mothed='GTE', data=None):
        #无法访问进行3次尝试,如果还不行,就返回404
        for z in range(1, 4):
            #异常捕获,否则无法访问则会报错
            try:
                if mothed == 'GTE':
                    response = self.s.get(url, headers=self.headers,data=data, proxies=proxies, timeout=90)

                else:
                    response = self.s.post(url, data=data, headers=self.headers, proxies=proxies, timeout=90)
            #错误则进行休眠
            except Exception:
                print('无法连接网络,正在进行第%d次尝试' % z)
                time.sleep(random.randint(3, 7))
                #判断已经访问错误几次了,如果大于等于3,则返回404,反之则跳过
                if z < 3:
                    pass
                else:
                    print('三次未访问成功的网站:', url)
                    # 这里将无法访问3次则记录错误信息日志记录
                    return 404
            #网页中可能本身存在404,找不到网页的情况,这种时候直接返回404
            else:
                if response.status_code == 404:
                    return 404

                #正常情况,返回的是网页源码,解码格式我直接采用了utf-8,可根据网站需要更换
                else:
                    response.encoding = 'utf-8'
                    return response

#主程序
class zhiwang_zhuanli(Conect):
    #创建Session,可自动记录访问的cookies
    s = requests.Session()
    #访问的请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
        'Host': 'login.cnki.net',
        'Referer': 'http://www.cnki.net/'
    }
    #这个列表是用来装底层目录的列表
    mulu_list=[]
    #由于是多进程,所以需要类接收一个参数,最外层目录编号
    def __init__(self,code_abc):
        self.__go__(code_abc)

    # 运行程序(一般多线程都放在这个函数里面)
    def __go__(self,code_abc):
        #由于我无法确定每个有多少层目录,所以我用递归的方式,调用了反复调用自身,传入的长度首先是2
        lenge=len(code_abc)
        while lenge>0:
            #对code_abc进行重新赋值,可以减小反复占用内存
            code_abc=self.mulu(code_abc)
            #对lenge重新赋值,重复调用本身函数,直到无二级以上的分类为止
            lenge=len(code_abc)
        #处理底层目录
        self.children_tag()


    #未用上,这个本来是可以改变Session的cookies,但是我发现后面也可以获得cookies
    def cookies_get(self):
        rsponse=404
        while rsponse==404:
            rsponse=self.connect(login_url,proxies=self.proxies)
            time.sleep(random.randint(4,10))

    #对目录进行处理的方法,每次访问一层,直到全部底层的目录的都加入到self.mulu_list
    def mulu(self,code_abc):
        #修改referer,否则无法拿到值
        self.headers['Referer'] = 'http://kns.cnki.net/kns/brief/result.aspx?dbprefix=SCOD'
        #host也不同,所以要做修改
        self.headers['Host']='kns.cnki.net'
        #创建一个非底层目录保存列表
        f_list=[]
        # 用遍历的方式来访问每个非底层的目录
        for i in code_abc:
            #构造需要访问的url
            mulu_url_pj=mulu_url+'?code='+i+'&tpinavigroup='+'SCODtpiresult'+'&__='+time.strftime('%a %b %d %Y %H:%M:%S GMT+0800')
            #访问相应的url
            sz=self.connect(mulu_url_pj)
            #判断,如果访问为404,则pass
            if sz==404:
                print('目录访问失败!')
            else:
                #访问成功的进行解析
                soup=bs(sz.text,'html.parser')
                dd=soup.findAll('dd')
                for dd_tag in dd:
                    img=dd_tag.find('img')
                    xuhao_tag=dd_tag.find('a').get('onclick')
                    if img==None:
                        #提取序号
                        bianhao=self.dd_re(xuhao_tag)
                        #将底层的目录放在类的列表中
                        self.mulu_list.append(bianhao)
                    else:
                        #将非底层的目录放在一个列表中
                        bianhao=self.dd_re(xuhao_tag)
                        f_list.append(bianhao)
        #返回非底层的列表
        return f_list


    # 对编号进行裁剪,得到相应的值
    def dd_re(self, string):
        xuhao = re.split('\'', string)[1]
        return xuhao


    #底层的目录进行处理
    def children_tag(self):
        #由于是post请求,所以需要先构造相应的data
        from_data={
                 'ua':1.25,
                 'PageName': 'ASP.brief_result_aspx',
                 'DbPrefix': 'SCOD',
                 'DbCatalog': '专利数据总库',
                 'ConfigFile': 'SCOD.xml',
                 'db_opt': 'SCOD',
                 'db_value': '中国专利数据库,国外专利数据库',
                 'his': '0',
                 '__': '%s %s' % (time.strftime('%a %b %d %Y %H:%M:%S GMT+0800'), ' (中国标准时间)')}
        #遍历底层的目录
        for i in self.mulu_list:
            #底层目录的编号
            print(i)
            #需要传入的值,所以用字典的添加方式将值添加到from_data
            from_data['NaviCode']=i
            #这个访问的网站是做打开数据库的操作,让cookies出现在他们网页地图上,否则无法得到相应的数据
            ss = self.connect(searchHandler_url, data=from_data, mothed='POST')
            #访问失败则重新访问一次,如果还不可以则打印相应的url
            if ss==404:
                time.sleep(random.randint(5,7))
                ss = self.connect(searchHandler_url, data=from_data, mothed='POST')
                if ss==404:
                    print(searchHandler_url)
                else:
                    #成功则调用下面的函数,获得相应的数据页面
                    self.data_get()
            else:
                self.data_get()


    #获得数据列表的网站,这个只是访问第一页,后面几页需要重新构造
    def data_get(self):
        #这里由于headers都是一样的,所以我没有做修改
        url=data_url+'?'+'pagename=ASP.brief_result_aspx&'+'isinEn=0&'+'dbPrefix=SCOD&'+'dbCatalog=%e4%b8%93%e5%88%a9%e6%95%b0%e6%8d%ae%e6%80%bb%e5%ba%93&'+"ConfigFile=SCOD.xml&"+'research=off&'+'S=1'
        response=self.connect(url)
        #访问失败则跳过
        if response==404:
            print(url)
        else:
            #访问成功的则对页面做后面的处理
            page=self.data_re(response)
            self.fanye(page)

    #获取页数的函数
    def data_re(self,response):
        #解析打开的网页
        text=response.text
        soup=bs(text,'html.parser')
        #抓取包含页数的地方,如果抓不到,则代表没有第二页,则返回0
        page=soup.find('span',{'class':'countPageMark'})
        if page==None:
            #这里调用的方法是获取文章详情的url
            self.xq_url_get(soup)
            return 0
        else:

            self.xq_url_get(soup)
            #由于抓取到的是字符串,而且都是1/%d,这种格式,所以我直接裁掉前面的,得到页数
            num=re.sub('1/','',page.text)
            #返回int型页数
            return int(num)

    #这个是获取第二页的数据的方法,需要传入上面处理出来的页数
    def fanye(self,page):
        #第一页已经抓取了,从第二页开始,然后到最后一页
        for i in  range(2,page+1):
            #构造第二页的url
            page_url='http://kns.cnki.net/kns/brief/brief.aspx?curpage={0}&RecordsPerPage=50&QueryID=0&ID=&turnpage=1&tpagemode=L&dbPrefix=SCOD&Fields=&DisplayMode=listmode&PageName=ASP.brief_result_aspx&isinEn=0#J_ORDER&'.format(i)
            response=self.connect(page_url)
            soup=bs(response.text,'html.parser')
            #调用上面的获取详情的函数
            self.xq_url_get(soup)


    #每页中都有文章详情的链接,所以用这个方法提取
    def xq_url_get(self,soup):
        xq_url_tag = soup.find('table', {'class': "GridTableContent"})
        xq_url_list = xq_url_tag.findAll('a')
        for url in xq_url_list:
            # print('文章网站:', 'http://kns.cnki.net' + url.get('href'))
            pass


if __name__ == '__main__':
    #五个进程,调试的时候我用的是一个
    # for i in range(5):
    for i in range(1):
        P1=Process(target=zhiwang_zhuanli,args=([mulu_list[i],mulu_list[9-i]],))
        P1.start()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏有趣的django

Flask快速入门 flask快速入门

2180
来自专栏desperate633

Java并发之“饥饿”和“公平锁”(Starvation and Fairness)java中发生线程饥饿的原因java中实现公平锁公平锁性能考虑

如果一个线程的cpu执行时间都被其他线程抢占了,导致得不到cpu执行,这种情况就叫做“饥饿”,这个线程就会出现饥饿致死的现象,因为永远无法得到cpu的执行。解决...

1231
来自专栏Aloys的开发之路

Java杂项

JDK JDK(Java Development Kit)是一个写Java程序所需的开发环境。它由一个处于操作系统层之上的运行环境,还有开发者编译、调试和运行J...

3237
来自专栏码云1024

c++DLL编程详解

4826
来自专栏大内老A

[WCF]缺少一行代码引发的血案

这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性。具体来...

1956
来自专栏机器学习算法与Python学习

Python:爬虫系列笔记(7) -- 爬去糗事百科段子

转自:静觅 » Python爬虫实战一之爬取糗事百科段子 前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧。那么这次为大家带来,Python...

3985
来自专栏Java编程技术

高并发编程必备基础(上)

借用Java并发编程实践中的话"编写正确的程序并不容易,而编写正常的并发程序就更难了",相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没...

1042
来自专栏Linyb极客之路

并发编程之读写锁

一、读写锁 ReadWriteLock 读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同...

9475
来自专栏mini188

技术笔记:Delphi多线程应用读写锁

在多线程应用中锁是一个很简单又很复杂的技术,之所以要用到锁是因为在多进程/线程环境下,一段代码可能会被同时访问到,如果这段代码涉及到了共享资源(数据)就需要保证...

2786
来自专栏Java面试通关手册

Java多线程学习(四)等待/通知(wait/notify)机制

我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailc...

2293

扫码关注云+社区

领取腾讯云代金券