山东大学创新项目实训个人工作日志(二十三)

本文记录了在爬取全国景点数据过程中遇到的问题及解决方案。最初在马蜂窝网站遇到JS混淆代码导致的访问障碍,通过研究和尝试,转而使用穷游网获取数据。采用多进程提高爬取速度,并针对数据量大、偶发获取失败的问题,采取分批爬取和延时策略,最终成功爬取到所有景点信息,为后续网页展示提供丰富内容。
摘要由CSDN通过智能技术生成

景点图片爬取(改进)
经过测试发现,之前爬到的数据并不是全部的数据,据估计,全国共两千多个城市和地区,数以万计的景点,而之前仅仅是将每个城市的一小部分景点爬了出来,所以现在需要做的就是把所有数据全部爬取出来。
在一开始采用的依旧是马蜂窝,但是经过反复尝试,发现它在访问景点详情页的时候,返回的并不是网页源码,而是一段JS混淆代码:

<script>document.cookie=('_')+('_')+('j')+('s')+('l')+('_')+('c')+('l')+('e')+('a')+('r')+('a')+('n')+('c')+('e')+('=')+(-~0+'')+([2]*(3)+'')+((1<<1)+'')+(2+'')+(2+6+'')+((2<<2)+'')+(+!+[]*2+'')+(-~[2]+'')+(1+3+'')+((1<<1)+'')+('.')+(-~[2]+'')+((2^1)+'')+(-~(8)+'')+('|')+('-')+(-~0+'')+('|')+((1+[0])/[2]+'')+('J')+('T')+('c')+('e')+('q')+('b')+(1+5+'')+('U')+('x')+('q')+('X')+('h')+('b')+(3+6+'')+('J')+('V')+('D')+('F')+('H')+('R')+('%')+(0+1+0+1+'')+('F')+('N')+('r')+('%')+(-~1+'')+('F')+('Q')+('c')+('%')+((1+[2]>>2)+'')+('D')+(';')+('m')+('a')+('x')+('-')+('a')+('g')+('e')+('=')+((2^1)+'')+(3+3+'')+(~~''+'')+(~~''+'')+(';')+('p')+('a')+('t')+('h')+('=')+('/');location.href=location.pathname+location.search</script>
                        

经过网上查阅多个资料,得知这段代码返回的是一个新的cookie,只有把它解码出来才能正确访问。
但是这段代码过于复杂,网上查阅资料也没有查到什么有用的信息,经过反复尝试(request、selenium),只能仅使用马蜂窝爬取景点图片,换别的网站爬取详细信息。
经过几个网站对比观察,最终采用了穷游网。
在这里插入图片描述
我选择从上面这个网页爬取所有城市列表,共170页,获取每个城市ID,然后利用开发者工具抓包可以发现在景点列表页面更换页码时有json文件传入,所以我们需要遍历每一页,获取所有的景点。
在这里插入图片描述
由于爬取数据量巨大,此方法还采用了多进程的方式,以提高速度。

def get_data(html_data):
    global allList
    # print(allList)
    selector = parsel.Selector(html_data)
    lis = selector.xpath('//ul[@class="plcCitylist"]/li')
    if len(lis)<15:
        print(str(len(lis)),html_data)
    for li in lis:
        travel_place = li.xpath('.//h3/a/text()').get()  # 目的地
        travel_place = travel_place.replace('\xa0','')
        onecitylist={}
        pid = li.xpath('.//p[@class="addPlanBtn"]/@data-pid').get()
        # print(travel_place, travel_people, travel_hot, travel_url, travel_imgUrl,pid, sep=' | ')
        page = 1
        while page < 500:
            headers = {
                'authority': 'place.qyer.com',
                'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
                'accept': 'application/json, text/javascript, */*; q=0.01',
                'x-requested-with': 'XMLHttpRequest',
                'sec-ch-ua-mobile': '?0',
                'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
                'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'origin': 'https://place.qyer.com',
                'sec-fetch-site': 'same-origin',
                'sec-fetch-mode': 'cors',
                'sec-fetch-dest': 'empty',
                'referer': 'https://place.qyer.com/hong-kong/sight/',
                'accept-language': 'zh-CN,zh;q=0.9',
                'cookie': '_qyeruid=CgIBAWC4PHp2qkJVmSkPAg==; new_uv=1; new_session=1; _guid=Rc6e04dd-9db6-cafc-afa0-e9515fac0d3f; ql_guid=QL5c19c9-1f38-4377-82a6-18242efa0235; source_url=https%3A//www.qyer.com/; isnew=1622686857075; __utma=253397513.1025643824.1622686844.1622825628.1622888267.5; __utmc=253397513; __utmz=253397513.1622888267.5.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmt=1; ql_created_session=1; ql_stt=1622888267070; ql_vts=5; frombaidu=1; PHPSESSID=23bf82872f55096d2a8720eb8dfeb705; __utmb=253397513.10.10.1622888267; ql_seq=10',
            }

            params = (
                ('action', 'list_json'),
            )

            data = {
                'page': page,
                'type': 'city',
                'pid': pid,
                'sort': '32',
                'subsort': 'all',
                'isnominate': '-1',
                'haslastm': 'false',
                'rank': '6'
            }
            print(page)
            page = page+1
            response = requests.post('https://place.qyer.com/poi.php', headers=headers, params=params, data=data)

            # NB. Original query string below. It seems impossible to parse and
            # reproduce query strings 100% accurately so the one below is given
            # in case the reproduced version is not "correct".
            # response = requests.post('https://place.qyer.com/poi.php?action=list_json', headers=headers, data=data)
            try:
                result = json.loads(response.text)
            except Exception as e:
                # page = page-1
                print('error'+response.text)
                time.sleep(3)
                page = page-1
                continue
            data = result['data']['list']
            # print(data)
            if len(data)==0:
                break
            for dat in data:
                name = dat['cnname']
                enname = dat['enname']
                score = dat['grade']
                imgsrc = dat['photo']
                rank = dat['rank']
                try:
                    dis=dat['comments'][0]['text']
                except:
                    dis=''
                # detail_url = 'https:'+dat['url']
                # detail_html = send_request(detail_url)
                # soup = BeautifulSoup(detail_html, "html.parser")
                # try:
                #     dis = soup.find('div',{'class':'compo-detail-info'}).text.replace(' ','')
                # except:
                #     dis = ''
                onesceniclist = {}
                onesceniclist['fname'] = enname
                onesceniclist['description'] = dis
                onesceniclist['rank'] = rank
                onesceniclist['imgsrc'] = imgsrc
                onesceniclist['score'] = score
                onecitylist[name] = onesceniclist
                # print(onecitylist)
        allList[travel_place] = onecitylist
        # print(allList)
        # count = count+1
        print('城市:'+travel_place)
        time.sleep(3)
    return allList

经过尝试,发现在获取每一页城市列表时有时会出现获取不到的情况,因此爬到的城市还是不够多,所以我在每一页爬完时让程序sleep一段时间,然后再继续,但是问题依旧存在。
之后又把程序改为了按照城市单个进行爬取的方式,但是因为城市太多,这必然要消耗更多的时间。
最后,我选择了分页爬取的方式,一次仅爬取5-10页的城市,这样即使有问题,也能及时更改过来,重新获取信息。

	all_task = []
    with ProcessPoolExecutor(max_workers=13) as executor:
        for page in range(1, 4): #172
            # print(page)
            url = f'https://place.qyer.com/china/citylist-0-0-{page}/'
            all_task.append(executor.submit(main, url))
            time.sleep(1)
    # for value in as_completed(all_task):
    #     l = value.result()
    #     allList = dict(**allList, **l)
    #     filename = 'allScenic.json'
    #     with open(filename, 'w') as file:
    #         json.dump(allList, file)
    wait(all_task, return_when=ALL_COMPLETED)
    for value in all_task:
        l = value.result()
        try:
            allList = dict(**allList, **l)
        except:
            for key, value in l.items():
                allList[key] = value

即使如此,爬取到所有数据依旧耗费了大量的时间,不过最后总算是成功地爬了下来,这样在网页展示景点的时候,内容将会更加丰富。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
未来社区的建设背景和需求分析指出,随着智能经济、大数据、人工智能、物联网、区块链、云计算等技术的发展,社区服务正朝着数字化、智能化转型。社区服务渠道由分散向统一融合转变,服务内容由通用庞杂向个性化、服务导向转变。未来社区将构建数字化生态,实现数据在线、组织在线、服务在线、产品智能和决策智能,赋能企业创新,同时注重人才培养和科研平台建设。 规划设计方面,未来社区将基于居民需求,打造以服务为中心的社区管理模式。通过统一的服务平台和应用,实现服务内容的整合和优化,提供灵活多样的服务方式,如推送式、订阅式、热点式等。社区将构建数据与应用的良性循环,提高服务效率,同时注重生态优美、绿色低碳、社会和谐,以实现幸福民生和产业发展。 建设运营上,未来社区强调科学规划、以人为本,创新引领、重点突破,统筹推进、整体提升。通过实施院落+社团自治工程,转变政府职能,深化社区自治法制化、信息化,解决社区治理中的重点问题。目标是培养有活力的社会组织,提高社区居民参与度和满意度,实现社区治理服务的制度机制创新。 未来社区的数字化解决方案包括信息发布系统、服务系统和管理系统。信息发布系统涵盖公共服务类和社会化服务类信息,提供政策宣传、家政服务、健康医疗咨询等功能。服务系统功能需求包括办事指南、公共服务、社区工作参与互动等,旨在提高社区服务能力。管理系统功能需求则涉及院落管理、社团管理、社工队伍管理等,以实现社区治理的现代化。 最后,未来社区建设注重整合政府、社会组织、企业等多方资源,以提高社区服务的效率和质量。通过建立社区管理服务综合信息平台,提供社区公共服务、社区社会组织管理服务和社区便民服务,实现管理精简、高效、透明,服务快速、便捷。同时,通过培育和发展社区协会、社团等组织,激发社会化组织活力,为居民提供综合性的咨询和服务,促进社区的和谐发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值