# -*- coding: utf-8 -*-
"""
Created on Sat May 20 15:02:58 2023
@author: JUJU
"""
from bs4 import BeautifulSoup
import json
import os
import asyncio
import aiohttp
import pandas as pd
import nest_asyncio
import pymysql
#设置当前工作文件夹
path='D:/pycharm/PyCharm 2023.1/project/wlpc/notes/Journals/国际贸易问题'
os.chdir(path)
nest_asyncio.apply()
#生成检索目录与url链接
year=2023
end_year=2015
volumnlist=[]
urls=[]
while year>=end_year:
month=12
if year==2023:
month=3
while month>0:
item=str(year)+'年 第'+str(month)+'期'
if month>=10:
url='https://gjmw.cbpt.cnki.net/WKC/WebPublication/wkTextContent.aspx?colType=4&yt='+str(year)+'&st='+str(month)
else:
url='https://gjmw.cbpt.cnki.net/WKC/WebPublication/wkTextContent.aspx?colType=4&yt='+str(year)+'&st=0'+str(month)
urls.append(url)
volumnlist.append(item)
month-=1
else:
while month >0:
item=str(year)+'年 第'+str(month)+'期'
if month>=10:
url='https://gjmw.cbpt.cnki.net/WKC/WebPublication/wkTextContent.aspx?colType=4&yt='+str(year)+'&st='+str(month)
else:
url='https://gjmw.cbpt.cnki.net/WKC/WebPublication/wkTextContent.aspx?colType=4&yt='+str(year)+'&st=0'+str(month)
urls.append(url)
volumnlist.append(item)
month-=1
year-=1
#保存目录与url链接
with open('国际贸易问题(目录及链接).json','w',encoding='utf8') as f:
volum_dic=dict(zip(volumnlist,urls))
v_json = json.dumps(volum_dic,sort_keys=False, indent=4, ensure_ascii=False,separators=(',', ': '))
f.write(v_json)
#反馈
print('国际贸易问题(目录及链接).json存储完成')
table=[]
# 获取网页(文本信息)
async def fetch(session, url):
async with session.get(url) as response:
return await response.text(encoding='utf-8')
async def parse(text):#解析网页
soup=BeautifulSoup(text,'lxml')
a=soup.select('#e3 .column_titbox_title a')
b=a[0].text
print(b)
year=int(b[0:4])
month=int(b[5:7])
tags=soup.find('ul', class_="column_contbox_zxlist")('li')
for tag in tags:
tag_h3=tag.find('h3')
title=tag_h3.text
href=tag_h3.a['href']
abt='https://gjmw.cbpt.cnki.net/WKC'+str(href[2:])
#摘要链接
tag_samp=tag.find('samp')
authors=tag_samp.text
tag_span=tag.find('span')('a')[2]
href=tag_span['href']
download_link='https://gjmw.cbpt.cnki.net/WKC'+str(href[2:])
#文章下载链接
nub=tag_span=tag.find('span')('font')[0]
number=nub.text
table.append([year,month,title,authors,abt,download_link,number])
return table
async def download(url):
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=64,verify_ssl=False)) as session:
html = await fetch(session, url)
await parse(html)
tasks = []
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(download(url)) for url in urls]
tasks = asyncio.gather(*tasks)
loop.run_until_complete(tasks)
df = pd.DataFrame(table, columns=['年份','月份','标题','作者','摘要链接','下载链接','下载次数'])
df.to_csv('./国际贸易问题.csv',index=False)
print('数据导出为csv成功!')
conn=pymysql.connect(host="localhost",user="root",password='root',
cursorclass=pymysql.cursors.DictCursor)
try:
# 创建游标
cur = conn.cursor()
# 执行sql查询语句
cur.execute("create database Jounrals")
print('数据库创建成功')
# 关闭游标
cur.close()
# 关闭数据库连接
conn.close()
except pymysql.err.MySQLError as _error:
print('数据库创建失败')
raise _error
try:
db=pymysql.connect(host="localhost",user="root",password='root',
database='Jounrals')
df.to_sql("国际贸易问题",db,if_exists="append")
print('数据库写入成功')
except:
print('数据库写入失败')
print('任务完成\n','*'*20)
以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:
这似乎是一个使用asyncio模块进行异步爬虫时出现的ConnectionAbortedError。这通常是因为建立的连接过多导致的。
asyncio模块使用的是协程,每个协程在等待I/O操作时可以让出控制权,所以可以实现高并发。但是,协程本身并不是线程,它们共享同一个事件循环,因此也共享同一个网络连接池。如果协程数量过多,会导致网络连接池中所有的连接都被占用,新的连接无法建立,此时会抛出ConnectionAbortedError。
一些解决方法如下:
python
async with ClientSession(connector_owner=False, limit=100) as session:
...
python
aiohttp.tcp_connector.TCPConnector(limit=200)
python
sem = asyncio.Semaphore(100)
async def crawler():
async with sem:
...
这将限制同时运行的协程数量为100。
使用异步锁。也可以使用asyncio.Lock来实现异步锁,在请求连接前先获取锁,释放锁后关闭连接,以达到限制连接数的目的。
协程内重试。在协程内catch住ConnectionError并重试,以避免新的连接无法建立。
使用线程池。可以使用线程池来发起连接,然后把连接交给asyncio的事件循环,这可以避免asyncio的事件循环直接创建过多连接。
很遗憾没有重现问题。跑了n多遍都是正常的。
倒是有个ssl错误,aiohttp版本__version__ = "3.8.4"
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=64, ssl=False)) as session:
ConnectionAbortedError : SSL handshake is taking longer than 60.0 seconds : aborting the connection
连接中止错误:SSL握手耗时超过60.0秒:正在中止连接
根据报错中文释义,可以分析是SSL握手超时导致链接中断
下面是可能原因和思路建议:
1、首先检查网络连接问题
思路:尝试重新连接到网络,或使用其他稳定网络再重新进行测试。
2、防火墙问题
思路:检查防火墙是否有阻止、拦截 ssl
3、系统资源不足
思路:检查下电脑运行盘服是否有足够的内存和处理器资源来运行程序
如果上面的尝试确认OK,可以使用其他思路:通过try except 语句来定位捕获异常、通过多次重连,跳过报错、减少任务等
网络连接问题、防火墙问题、系统资源问题、代理、异常捕获、增加重试机制、增大线程池和减少最大连接数量都尝试过,依旧没有解决这个问题。
【更新】解决了,原因是由于阻塞操作没有挂起导致的
loop.run_until_complete(tasks)
改成
loop.run_until_complete(asyncio.wait(tasks))