其他分享
首页 > 其他分享> > 【东南亚小语种项目】泰文文献双语标题和双语摘要爬取

【东南亚小语种项目】泰文文献双语标题和双语摘要爬取

作者:互联网

这里写自定义目录标题

0.介绍项目目标

1.网站分析

1.1 寻找文档的uri规律

在这里插入图片描述

# ps:【】表示连接的区别
# 第一篇文档
http://cuir.car.chula.ac.th/handle/123456789/
72181?
src=%2Fsimple-search%3Fquery%3D%26filter_field_1%3Dtype%26filter_type_1%3Dequals%
26filter_value_1%3DThesis%26sort_by%3Ddc.date.issued_dt%26order%3Ddesc%26rpp
%3D10%26etal%3D0%26start%3D0%26brw_total%3D64845%26brw_pos%
3D0&query=

# 第二篇文档
http://cuir.car.chula.ac.th/handle/123456789/
71235?
src=%2Fsimple-search%3Fquery%3D%26filter_field_1%3Dtype%26filter_type_1%3Dequals%
26filter_value_1%3DThesis%26sort_by%3Ddc.date.issued_dt%26order%3Ddesc%26rpp%
3D10%26etal%3D0%26start%3D0%26brw_total%3D64845%26brw_pos%
3D1&query=

# 第三篇文档
http://cuir.car.chula.ac.th/handle/123456789/
71233?
src=%2Fsimple-search%3Fquery%3D%26filter_field_1%3Dtype%26filter_type_1%3Dequals%
26filter_value_1%3DThesis%26sort_by%3Ddc.date.issued_dt%26order%3Ddesc%
26rpp%3D10%26etal%3D0%26start%3D0%26brw_total%3D64845%26brw_pos%
3D2&query=

# 最后一篇文档
http://cuir.car.chula.ac.th/handle/123456789/
27447?src=%2Fsimple-search%3Fquery%3D%26filter_field_1%3Dtype%26filter_type_1%3Dequals%
26filter_value_1%3DThesis%26sort_by%3Ddc.date.issued_dt%26order%3Ddesc%
26rpp%3D10%26etal%3D0%26start%3D64840%26brw_total%3D64845%26brw_pos%
3D64844&query=

# 但是经过多篇比对,我们发现每一篇文献的不同之处在于这两个地方:
http://cuir.car.chula.ac.th/handle/123456789/【72181】?
src=%2Fsimple-search%3Fquery%3D%26brw_total%3D73726%
26brw_pos%3D【0】&query=

# 而其他地方是一样的,这是否就是规律呢?先不着急下定论,
# 因为这个页面有一个return to list,我怀疑这是一个展示页而不是论文真正存放的物理路径。
	
第一篇:http://cuir.car.chula.ac.th/handle/123456789/72181
第二篇:http://cuir.car.chula.ac.th/handle/123456789/71235
第三篇:http://cuir.car.chula.ac.th/handle/123456789/71233
第四篇:http://cuir.car.chula.ac.th/handle/123456789/73078
第五篇:http://cuir.car.chula.ac.th/handle/123456789/69502
第六篇:http://cuir.car.chula.ac.th/handle/123456789/71254
第20篇:http://cuir.car.chula.ac.th/handle/123456789/77274
第60篇:http://cuir.car.chula.ac.th/handle/123456789/75905

最后一篇:http://cuir.car.chula.ac.th/handle/123456789/27447

检测:
http://cuir.car.chula.ac.th/handle/123456789/55
http://cuir.car.chula.ac.th/handle/123456789/77960
# 从55开始一直到77960都存在文献

1.2 寻找html规律

2.爬取操作

2.1 多线程实现访问和爬取

# 首先导入所有我们需要的包
import requests
import sys
import io
import threading
from bs4 import BeautifulSoup

# 这句直接复制粘贴即可,是处理python的io流读写文本时候的乱码问题,统一utf8【utf8有泰文集】,不然会受到gbk的影响
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')

# 创建三个线程类进行3个函数调用,这是threading模块的用法,可以自行学习后回来看
# 要注意这里是class而不是一个方法,可以照抄就行,重点是class里面的一个run方法,
# run方法需要调用我们执行函数,比如我这里调用的就是我待会要执行爬取功能的函数processDocument
class thread1(threading.Thread):
    def __init__(self, threadID, name, counter):    
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        # 55,26023表示我们要爬取的范围,1表示这是第一个线程,具体看下面的函数形参
        processDocument(55,26023,1)
        print ("退出线程:" + self.name)
class thread2(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        processDocument(26023,51991,2)
        print ("退出线程:" + self.name)
class thread3(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        processDocument(51991,77961,3)
        print ("退出线程:" + self.name)
    

# 爬取函数,我只对一个进行注释,后面两个是重复的函数,可以直接复用,但是注意num形参的不同,thread_no表示当前线程序号
# num1,num2是指我们要爬取的序列号范围,我们从分析网站之后得到文档的有效序号是55-77960,
# 那么我们分三个线程,均分这一批文献,分别是55,26023 | 26023,51991 | 51991,77961。
# 因为range函数是左闭右开,所以最后要加一77961.
def processDocument(num1,num2,thread_no):
    for serial_num in range(num1,num2):
    	# 这两个变量可以自己加上去之后自己打印输出查看结果
        fail_count = 0
        success_count = 0
        document_URL = 'http://cuir.car.chula.ac.th/handle/123456789/'+str(serial_num)
        try:
        	# 这里一定要用try except语块,否则会因为爬取连接过多导致一些异常而终止。
            response = requests.get(document_URL, timeout=2)
            # 获取状态码,状态码为200的时候访问成功
            status = response.status_code
            # 如果访问成功则写入文件
            if status == 200:
                # print(document_URL)
                success_count += 1
				# with打开文件后,用a模式追加字符encoding='utf-8'
				# 结果我们可以看到多个文件
            	with open("uri"+str(thread_no)+".txt","a") as file:
                    file.write(document_URL+"\n")
        except:
            fail_count += 1
    print(success_count)

# 创建线程对象,thread1,thread2,thread3都是刚刚定义的类名
thread_1 = thread1(1, "Thread-1", 1)
thread_2 = thread2(2, "Thread-2", 2)
thread_3 = thread3(3, "Thread-3", 3)

# 开启线程,自动调用run函数
thread_1.start()
thread_2.start()
thread_3.start()

2.2 html 处理

def processDocument(num1,num2,thread_no):
    for serial_num in range(num1,num2):
    	# 这两个变量可以自己加上去之后自己打印输出查看结果
        fail_count = 0
        success_count = 0
        document_URL = 'http://cuir.car.chula.ac.th/handle/123456789/'+str(serial_num)
        try:
        	# 这里一定要用try except语块,否则会因为爬取连接过多导致一些异常而终止。
            response = requests.get(document_URL, timeout=2)
            # 获取状态码,状态码为200的时候访问成功
            status = response.status_code
            # 如果访问成功则写入文件
            if status == 200:
                # print(document_URL)
                success_count += 1
                # 成功了我们就不写入查看了,我们直接把访问成功的网站的html文档传过去
                # 这里写txt也可以,只是我们最后的目标是txt文件
                # response.text是uri网站对应的html代码,可以自行打印查看
                processSoup('数据集1.tsv',response.text)
        except:
            fail_count += 1
    print(success_count)
    
# 有了uri,我们就可以不断进行自动访问,然后下载html进行元素内容精准定位和获取了
# 我们定义一个函数用于处理html
# filename是我们要存放结果的文件,html_text是我们获取到的html文本
def processSoup(filename,html_text):
	# soup对象的创建需要一个html文本,和一个解析器,我们使用默认提供的lxml即可
    soup = BeautifulSoup(html_text,'lxml')
   
    # 下面字段获取内容的方式大同小异,自行查看soup.find()函数,我们这里只用到find函数的两个字段,
    # soup.find('标签名',class_='类名'),这样就可以唯一定位到我想要的内容,
    # 但是我们需要的是标签中间的字符串而不包括标签,所以我们还需要进行.string操作。至于内容在哪个类里,自己去网页f12查看元素即可。
    # ps:为什么是class_?而不是class=?因为class是python的关键字,soup为了区分而换了一个关键字代表html的类。
    title = soup.find('td',class_='metadataFieldValue dc_title').string
    other_title = soup.find('td',class_='metadataFieldValue dc_title_alternative').string
    abstract = soup.find('td',class_='metadataFieldValue dc_description_abstract').string
    other_abstract = soup.find('td',class_='metadataFieldValue dc_description_abstractalternative').string
    degree_discipline = soup.find('td',class_='metadataFieldValue dc_degree_discipline').a.string
	
	# 一般来说,网页title就是泰文标题,other_title就是英文标题,但是在爬取过程中我们发现了存在title是英文标题先的,而other_title才是泰文标题,因此我们需要加一个过滤方法
    thai_title = title
    en_title = other_title
    thai_abstract = abstract
    en_abstract = other_abstract

	# 过滤方法,保证title就是泰文标题,other_title就是英文标题
    for i in range(10):
    	# 提供一个随机数
        index = random.randint(1,20)
        # 简单排除停止词,如果我们随机的字符是停止词,我们重新提供随机数
        if(thai_title[index] == ',' or thai_title[index] == ' ' or thai_title[index] == '.' or thai_title[index] == '(' or thai_title[index] == ')' or thai_title[index] == '?' or thai_title[index] == '!'):
            continue
        else:
        	# 如果我们随机到的字符不是停止词,那么判断它是不是英文,注意还要考虑大小写,小写英文的ascii是97-122,而大写是65-80。中间一些其他的ascii可以忽略
            if(ord(title[1])>=65 and ord(title[1])<=122):
            	# 如果该字符是英文,则title是特殊情况,也就是title是英文标题,
            	# other_title才是泰文标题,我们进行简单转换
                thai_title = other_title
                en_title = title
                thai_abstract = other_abstract
                en_abstract = abstract
            break

   # 把爬取下来的字段都写入到文件中
    with open(filename,'a',encoding='utf-8') as file:
        file.write(thai_title+",")
        file.write(en_title+",")
        file.write(thai_abstract+",")
        file.write(en_abstract+",")
        file.write(degree_discipline+"\n")
    return

2.3 tsv转换

	# 这里需要加一个参数newline='',不然会有诡异的换行
    with open(filename,'a',encoding='utf-8',newline='') as file:
        tsv_w = csv.writer(file,delimiter='\t')
        #tsv_w.writerow(['thai_title','en_title','thai_abstract','en_abstract','degree_discipline'])
        tsv_w.writerow([thai_title,en_title,thai_abstract,en_abstract,degree_discipline])
        #file.write(thai_title+",")
        #file.write(en_title+",")
        #file.write(thai_abstract+",")
        #file.write(en_abstract+",")
        #file.write(degree_discipline+"\n")

3.完整代码

# 首先导入所有我们需要的包
import requests
import sys
import io
import threading
from bs4 import BeautifulSoup

# 这句直接复制粘贴即可,是处理python的io流读写文本时候的乱码问题,统一utf8【utf8有泰文集】,不然会受到gbk的影响
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')

# 创建三个线程类进行3个函数调用,这是threading模块的用法,可以自行学习后回来看
# 要注意这里是class而不是一个方法,可以照抄就行,重点是class里面的一个run方法,
# run方法需要调用我们执行函数,比如我这里调用的就是我待会要执行爬取功能的函数processDocument
class thread1(threading.Thread):
    def __init__(self, threadID, name, counter):    
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        # 55,26023表示我们要爬取的范围,1表示这是第一个线程,具体看下面的函数形参
        processDocument(55,26023,1)
        print ("退出线程:" + self.name)
class thread2(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        processDocument(26023,51991,2)
        print ("退出线程:" + self.name)
class thread3(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开始线程:" + self.name)
        processDocument(51991,77961,3)
        print ("退出线程:" + self.name)
    

# 爬取函数,我只对一个进行注释,后面两个是重复的函数,可以直接复用,但是注意num形参的不同,thread_no表示当前线程序号
# num1,num2是指我们要爬取的序列号范围,我们从分析网站之后得到文档的有效序号是55-77960,
# 那么我们分三个线程,均分这一批文献,分别是55,26023 | 26023,51991 | 51991,77961。
# 因为range函数是左闭右开,所以最后要加一77961.
def processDocument(num1,num2,thread_no):
    for serial_num in range(num1,num2):
    	# 这两个变量可以自己加上去之后自己打印输出查看结果
        fail_count = 0
        success_count = 0
        document_URL = 'http://cuir.car.chula.ac.th/handle/123456789/'+str(serial_num)
        try:
        	# 这里一定要用try except语块,否则会因为爬取连接过多导致一些异常而终止。
            response = requests.get(document_URL, timeout=2)
            # 获取状态码,状态码为200的时候访问成功
            status = response.status_code
            # 如果访问成功则写入文件
            if status == 200:
                success_count += 1
                processSoup('数据集'+thread_no+'.tsv',response.text)
				
        except:
            fail_count += 1
    print(success_count)

# 有了uri,我们就可以不断进行自动访问,然后下载html进行元素内容精准定位和获取了
# 我们定义一个函数用于处理html
# filename是我们要存放结果的文件,html_text是我们获取到的html文本
def processSoup(filename,html_text):
	# soup对象的创建需要一个html文本,和一个解析器,我们使用默认提供的lxml即可
    soup = BeautifulSoup(html_text,'lxml')
   
    # 下面字段获取内容的方式大同小异,自行查看soup.find()函数,我们这里只用到find函数的两个字段,
    # soup.find('标签名',class_='类名'),这样就可以唯一定位到我想要的内容,
    # 但是我们需要的是标签中间的字符串而不包括标签,所以我们还需要进行.string操作。至于内容在哪个类里,自己去网页f12查看元素即可。
    # ps:为什么是class_?而不是class=?因为class是python的关键字,soup为了区分而换了一个关键字代表html的类。
    title = soup.find('td',class_='metadataFieldValue dc_title').string
    other_title = soup.find('td',class_='metadataFieldValue dc_title_alternative').string
    abstract = soup.find('td',class_='metadataFieldValue dc_description_abstract').string
    other_abstract = soup.find('td',class_='metadataFieldValue dc_description_abstractalternative').string
    degree_discipline = soup.find('td',class_='metadataFieldValue dc_degree_discipline').a.string
	
	# 一般来说,网页title就是泰文标题,other_title就是英文标题,但是在爬取过程中我们发现了存在title是英文标题先的,而other_title才是泰文标题,因此我们需要加一个过滤方法
    thai_title = title
    en_title = other_title
    thai_abstract = abstract
    en_abstract = other_abstract

	# 过滤方法,保证title就是泰文标题,other_title就是英文标题
    for i in range(10):
    	# 提供一个随机数
        index = random.randint(1,20)
        # 简单排除停止词,如果我们随机的字符是停止词,我们重新提供随机数
        if(thai_title[index] == ',' or thai_title[index] == ' ' or thai_title[index] == '.' or thai_title[index] == '(' or thai_title[index] == ')' or thai_title[index] == '?' or thai_title[index] == '!'):
            continue
        else:
        	# 如果我们随机到的字符不是停止词,那么判断它是不是英文,注意还要考虑大小写,小写英文的ascii是97-122,而大写是65-80。中间一些其他的ascii可以忽略
            if(ord(title[1])>=65 and ord(title[1])<=122):
            	# 如果该字符是英文,则title是特殊情况,也就是title是英文标题,
            	# other_title才是泰文标题,我们进行简单转换
                thai_title = other_title
                en_title = title
                thai_abstract = other_abstract
                en_abstract = abstract
            break

   # 把爬取下来的字段都写入到文件中
   # 这里需要加一个参数newline='',不然会有诡异的换行
   with open(filename,'a',encoding='utf-8',newline='') as file:
       tsv_w = csv.writer(file,delimiter='\t')
       #tsv_w.writerow(['thai_title','en_title','thai_abstract','en_abstract','degree_discipline'])
       tsv_w.writerow([thai_title,en_title,thai_abstract,en_abstract,degree_discipline])
       #file.write(thai_title+",")
       #file.write(en_title+",")
       #file.write(thai_abstract+",")
       #file.write(en_abstract+",")
       #file.write(degree_discipline+"\n")
   return

# 创建线程对象,thread1,thread2,thread3都是刚刚定义的类名
thread_1 = thread1(1, "Thread-1", 1)
thread_2 = thread2(2, "Thread-2", 2)
thread_3 = thread3(3, "Thread-3", 3)

# 开启线程,自动调用run函数
thread_1.start()
thread_2.start()
thread_3.start()

4.结果展示

在这里插入图片描述

标签:name,title,self,双语,爬取,html,泰文,thai,class
来源: https://blog.csdn.net/NineWaited/article/details/121504938