请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

线程池提交函数和参数 递归处理下一页只执行几页就不执行了

# 使用线程池爬取csdn
"""
抓取
解析
存储
"""
import re
import ast
from urllib import parse
from datetime import datetime

import requests
from scrapy import Selector

from csdn_spider.models import *

domain = "https://bbs.csdn.net"


def parse_list(url):
    print('*' * 200)
    print("解析列表页: {}".format(url))

    res_text = requests.get(url).text
    sel = Selector(text=res_text)
    all_trs = sel.xpath("//table[@class='forums_tab_table']/tbody/tr")
    for tr in all_trs:
        topic_title = tr.xpath(".//td[3]/a/text()").extract()[0]
        print(topic_title)

    next_page = sel.xpath("//a[@class='pageliststy next_page']/@href").extract()
    if next_page:
        next_url = parse.urljoin(domain, next_page[1])
        task2 = executor.submit(parse_list, next_url)
        thread_list.append(task2)
        # parse_list(next_url)


if __name__ == "__main__":
    from concurrent.futures import ThreadPoolExecutor, as_completed

    executor = ThreadPoolExecutor(max_workers=5)
    last_urls = ['https://bbs.csdn.net/forums/ios']
    # 爬取这个url下的所有标题 和下一页的标题
    thread_list = []
    for url in last_urls:
        task1 = executor.submit(parse_list, url)
        thread_list.append(task1)
        # parse_list(url)

    # https://bbs.csdn.net/forums/ios' 这个url有一百个下一页

    # 使用多线程 executor.submit(parse_list, url) 加不加下面这个代码都只能爬取几页数据
    # 不使用executor.submit 。递归使用parse_list(url)可以爬取全部数据
    # for future in as_completed(thread_list):
    #     data = future.result()
    #     print("-"*60,data)

单线程递归没问题每一页都能爬。使用线程池执行程序也不报错,就是只能爬个几页就结束了。
当我设置断点调试的时候也没找到问题…这是最骚的

正在回答 回答被采纳积分+3

2回答

bobby 2020-03-13 11:50:04
import re
import ast
from urllib import parse
from datetime import datetime

import requests
from scrapy import Selector


domain = "https://bbs.csdn.net"


def parse_list(url):
    print('*' * 200)
    print("解析列表页: {}".format(url))

    res_text = requests.get(url).text
    sel = Selector(text=res_text)
    all_trs = sel.xpath("//table[@class='forums_tab_table']/tbody/tr")
    for tr in all_trs:
        topic_title = tr.xpath(".//td[3]/a/text()").extract()[0]
        # print(topic_title)

    next_page = sel.xpath("//a[@class='pageliststy next_page']/@href").extract()
    if next_page:
        next_url = parse.urljoin(domain, next_page[1])
        print(next_url)
        task2 = executor.submit(parse_list, next_url)
        thread_list.append(task2)


if __name__ == "__main__":
    stop = False
    from concurrent.futures import ThreadPoolExecutor, as_completed

    executor = ThreadPoolExecutor(max_workers=5)
    last_urls = ['https://bbs.csdn.net/forums/ios']
    # 爬取这个url下的所有标题 和下一页的标题
    thread_list = []
    print(len(last_urls))
    for url in last_urls:
        task1 = executor.submit(parse_list, url)
        thread_list.append(task1)
        parse_list(url)

    # https://bbs.csdn.net/forums/ios' 这个url有一百个下一页

    # 主线程退出以后会导致运行中的线程运行完成以后后续排队的任务不执行
    # as_completed只会将参数中的task完成以后就不在执行新的任务,所以采用一个全局变量stop来决定是否退出主线程并关闭线程池
    import time
    while not stop:
        time.sleep(1)


0 回复 有任何疑惑可以回复我~
  • 你给的示例中,stop只在主函数中调用了,并未见stop=True的赋值
    回复 有任何疑惑可以回复我~ 2020-12-17 10:46:58
bobby 2020-03-11 18:48:56

as_completed 这个代码不能注释,不然主线程就容易造成子线程退出

0 回复 有任何疑惑可以回复我~
  • 提问者 仙女座舜 #1
    ....还是没解决
    回复 有任何疑惑可以回复我~ 2020-03-11 19:31:43
  • 提问者 仙女座舜 #2
    老师能不能帮我改一下代码. 最下面的注释给打开,同时thread_list.append(task2)改成as_complete([task2])。还是没用,还是爬几页数据就停了。
    回复 有任何疑惑可以回复我~ 2020-03-11 19:36:52
  • 提问者 仙女座舜 #3
    QAQ用递归怎么写代码才是对的,您能不能贴一下运行正确的代码,怎么改都不能爬完一百页数据QAQ。
    回复 有任何疑惑可以回复我~ 2020-03-11 20:14:45
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号