是肥宅SRP啊 发表于 2023-4-29 11:31:16

python异步协程

本帖最后由 是肥宅SRP啊 于 2023-4-29 14:38 编辑

没加入协程之前,我是可以正常获取到href里的各章网址,也是可以获取到各章节的文字内容的,但是加入协程之后就不行。
协程学的一知半解的,我不知道哪里错了,help!!
import asyncio
import aiohttp
import aiofiles
import requests
from lxml import etree

#获取URL
def get_url():
    url = "https://www.zanghaihua.org/book/40627/"
    headers = {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.12022 SLBChan/8"
    }
    http = requests.get(url,headers = headers)
    http.encoding = "gbk"
    parse_html = etree.HTML(http.text)
    hrefs = parse_html.xpath("//li/a/@href")
    return hrefs

#获取文本
async def get_text(url):
    headers = {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.12022 SLBChan/8"
    }
    async with aiohttp.ClientSession() as session:
      async with session.get(url, headers=headers) as res:
            res.encoding = "utf-8"
            parse_html = await res.text()
            parse_html = etree.HTML(parse_html)
            content = parse_html.xpath('//div[@class="content"]/text()')
            title = parse_html.xpath('//div[@class="reader-main"]/h1/text()')
            # print(title)
            # print(content)
            async with aiofiles.open(f"{title}.text",mode = "w", coding = "utf-8") as f:
                await f.write(content)
#创建协程_
async def get_task(href_list):
    tasks = []
    for href in href_list:
      t = asyncio.create_task(get_text(href))
      tasks.append(t)
    await asyncio.wait(tasks)



def main():
    href_lists = get_url()
    asyncio.run(get_task(href_lists))

isdkz 发表于 2023-4-29 11:31:17

从你的代码来看,你已经开始了异步协程的学习,并将其应用到了抓取网页的任务中。在这里,我会给出一些建议来帮助你改进代码。

1.aiohttp 的响应对象 res 没有 encoding 属性,因此在这里设置 res.encoding = "utf-8" 是错误的。你可以在 res.text() 函数中传入 encoding 参数来指定编码方式,如: await res.text(encoding='utf-8') 。

2. 使用 aiofiles.open() 时,你应该使用 encoding 参数而不是 coding 。

3.title 和 content 都是列表类型,而不是字符串。在写入文件之前,需要将它们转换为字符串。

这里是修改后的代码:

import asyncio
import aiohttp
import aiofiles
import requests
from lxml import etree

#获取URL
def get_url():
    url = "https://www.zanghaihua.org/book/40627/"
    headers = {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.12022 SLBChan/8"
    }
    http = requests.get(url,headers = headers)
    http.encoding = "gbk"
    parse_html = etree.HTML(http.text)
    hrefs = parse_html.xpath("//li/a/@href")
    return hrefs

#获取文本
async def get_text(url):
    headers = {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.12022 SLBChan/8"
    }
    async with aiohttp.ClientSession() as session:
      async with session.get(url, headers=headers) as res:
            parse_html = await res.text(encoding='utf-8')
            parse_html = etree.HTML(parse_html)
            content = parse_html.xpath('//div[@class="content"]/text()')
            title = parse_html.xpath('//div[@class="reader-main"]/h1/text()')
            async with aiofiles.open(f"{title}.txt", mode="w", encoding="utf-8") as f:
                await f.write("\n".join(content))

#创建协程
async def get_task(href_list):
    tasks = []
    for href in href_list:
      t = asyncio.create_task(get_text(href))
      tasks.append(t)
    await asyncio.wait(tasks)

def main():
    href_lists = get_url()
    asyncio.run(get_task(href_lists))

if __name__ == "__main__":
    main()


经过这些修改,代码应该能正常运行并获取各章节的文本内容。希望这对你有所帮助!如果还有其他问题,请随时提问。

isdkz 发表于 2023-4-29 12:08:13

你确定你不用协程就可以?

陶远航 发表于 2023-4-29 12:11:56

根据您提供的代码,似乎没有立即显然的问题。但是我注意到您在async with aiofiles.open处使用了title变量而不是title。

由于title实际上是一个列表,这可能会导致文件名与内容不匹配。您可以尝试更新代码,使用title来获取第一个元素作为字符串。例如:
async with aiofiles.open(f"{title}.text", mode="w", encoding="utf-8") as f:
    await f.write(content)

希望这会解决您的问题!

是肥宅SRP啊 发表于 2023-4-29 14:18:33

isdkz 发表于 2023-4-29 11:34
从你的代码来看,你已经开始了异步协程的学习,并将其应用到了抓取网页的任务中。在这里,我会给出一些建议 ...

老师你好,我按照你修改过后的代码运行了一下,是能运行的,非常感谢。我还有一个小问题想问一下,就是把文本内容爬下来之后,我在pycharm里直接打开的话,在每段文字开头会有四个NBSP的字样,用文档打开的话没有,但是有点丑,每段空了四个空格。我去页面源代码看了一下看到他是有这个“    ”,我想用replace把他replace掉,但是怎么好像没有用?

是肥宅SRP啊 发表于 2023-4-29 14:19:42

陶远航 发表于 2023-4-29 12:11
根据您提供的代码,似乎没有立即显然的问题。但是我注意到您在async with aiofiles.open处使用了title变量 ...

谢谢你,我发现了这个错误了,感谢感谢!

isdkz 发表于 2023-4-29 14:20:40

是肥宅SRP啊 发表于 2023-4-29 14:18
老师你好,我按照你修改过后的代码运行了一下,是能运行的,非常感谢。我还有一个小问题想问一下,就是把 ...

.replace(" ", '') 不行吗?

是肥宅SRP啊 发表于 2023-4-29 14:24:19

isdkz 发表于 2023-4-29 14:20
.replace(" ", '') 不行吗?

await f.write("\n".join(content).replace(" ",""))是这样写吗?我这样写好像没啥变化的样子不知道是不是我写错了

isdkz 发表于 2023-4-29 14:32:19

是肥宅SRP啊 发表于 2023-4-29 14:24
await f.write("\n".join(content).replace(" ",""))是这样写吗?我这样写好像没啥变化的样子不知道 ...

对的,没有什么变化的话你可以把对应的文件放上来给我看一下,最好压缩放到附件里

是肥宅SRP啊 发表于 2023-4-29 14:40:20

isdkz 发表于 2023-4-29 14:32
对的,没有什么变化的话你可以把对应的文件放上来给我看一下,最好压缩放到附件里

是代码文件和爬取的小说内容吗?我放了一个第五章,因为他是从第五章开始出现那个的。

isdkz 发表于 2023-4-29 14:47:31

是肥宅SRP啊 发表于 2023-4-29 14:40
是代码文件和爬取的小说内容吗?我放了一个第五章,因为他是从第五章开始出现那个的。

你放的那个文件我看了,不是多了   而是多了 \xa0 的一个不可见字符

用 .replace('\xa0', '') 来替换掉

是肥宅SRP啊 发表于 2023-4-29 15:10:58

isdkz 发表于 2023-4-29 14:47
你放的那个文件我看了,不是多了   而是多了 \xa0 的一个不可见字符

用 .replace('\xa0', '') 来 ...

好了!谢谢你!
页: [1]
查看完整版本: python异步协程