关于python爬虫:python-requests-爬取nexus库依赖包数据

前言因为nexus库自带API没有输入依赖包对应的创立工夫(blobCreated)、上传工夫(blobUpdated),为方便管理依赖包只好从页面返回的数据进行爬取(可能应用nexus-cli能够获取,然而没有细究这个办法) 思路我这边应用的nexus库版本为 3.19.1-01,上面是在nexus库API接口信息中能够查问到对于依赖包信息的接口 /v1/components该版本输入的信息中只蕴含个别的 group、name、downloadUrl、repository等音讯,没有上传工夫相干的信息,然而在Browse 中能够查问到相干的信息通过浏览器开发工具能够查问到,该信息来自/service/extdirect 这个申请地址 依据接口申请负载能够看到,该接口须要传入两个参数别离是repo地址以及一个id参数,认真钻研之后发现该id与nexus 自带API(/v1/components)输入的id并非一样,而是来自同一个申请地址不同action的id名为 assetId而这个申请须要传入的参数别离是repo地址以及node信息,node信息能够通过'group'+'name'+'version'信息获取。那么查问到这一步思路就造成闭环了,整体思路如下:通过nexus库自带API接口别离获取:'group'+'name'+'version' 信息,组合成node信息,进而获取到assetId信息,通过assetId信息获取对应的依赖包详细信息。既然思路清晰了,那就开始备菜做饭(敲代码调试)吧~ 实现获取node节点信息 AKA 'group'+'name'+'version'信息nexus_url = 'http://192.168.1.1:8081/' #nexus库地址nexus_username = 'admin' #nexus账号nexus_password = 'admin123' #nexus明码repository = ['aliyun','maven-releases'] #nexus库 repo地址names = []groups = []versions = []downloadUrls = [] #这里顺便获取下载地址,没太大用处能够疏忽asset_ids = []def components_api(repository): #申请components接口获取依赖包包根本信息 print('running components_api\t'+repository) #申请参数 query_params = { 'repository' : repository, #传入的repo信息 'extension' : 'jar' #依赖包类型 } #申请API接口 response = requests.get( nexus_url + '/service/rest/v1/components', params=query_params, auth=(nexus_username, nexus_password) #API接口须要鉴权 ) #判断接口状态 if response.status_code != 200: print('获取依赖项信息失败,状态码:{}'.format(response.status_code)) print(response.content) exit() #将接口返回数据转化为json格局用于解决 response_data = response.json() # print(response_data) global name,group,version,downloadUrl for items in response_data['items']: name = format(items['name']) group = format(items['group']) version = format(items['version']) names.append(name) groups.append(group) versions.append(version) for asset in items['assets']: if asset['path'].endswith('.jar'): downloadUrl = format(asset['downloadUrl']) downloadUrls.append(downloadUrl) #执行工夫 end = datetime.datetime.now() print('components_api totally time is ' , end - start)依据node信息获取assetIdheaders = { #申请头信息 nexus库,cookie信息及token信息依据nexus库账号获取 'X-Requested-With': 'XMLHttpRequest', 'X-Nexus-UI': 'true', 'NX-ANTI-CSRF-TOKEN': '0.1427667210133794', 'Content-Type': 'application/json', 'Origin': nexus_url, 'Referer': nexus_url, 'Cookie': 'NX-ANTI-CSRF-TOKEN=0.1427667210133794; NXSESSIONID=9b2057c6-a456-4f94-85d7-90dcb07eb9e6' }random_number = random.randint(50, 120) #增加一个随机数用于接口操作的tiddef get_nodeinfo(repository): #依据components_api获取的信息拼接取得node门路及asset_id print('get_nodeinfo\t'+repository) api_url = nexus_url + "/service/extdirect" for i in range(len(names)): Groups = [group.replace('.', '/') for group in groups] #将groups中的‘.’转换为‘/’ node = Groups[i]+'/'+names[i]+'/'+versions[i] payload = json.dumps({ "action": "coreui_Browse", "method": "read", "data": [{ "repositoryName" : repository, "node": str(node) }], "type": "rpc", "tid": random_number }) response = requests.request("POST", api_url, headers=headers, data=payload) if response.status_code != 200: #判断接口状态 print('获取依赖项信息失败,状态码:{}'.format(response.status_code)) print(response.content) exit() response_data = response.json() global asset_ids for item in response_data['result']['data']: #依据接口返回数据获取assetid if item['text'].endswith('.jar'): asset_ids.append(item['assetId']) #将API数据中的assetId存入变量asset_ids #执行工夫 end = datetime.datetime.now() print('get_nodeinfo totally time is ' , end - start)依据assetId获取依赖包详细信息INFO_NAME = []INFO_REPO = []INFO_CTIME = []INFO_UTIME = []INFO_DURL = []INFO_GID = []INFO_AID = []INFO_VERSION = []def get_assetid_info(repository): #通过assetid获取jar具体信息包含上传工夫及创立工夫 api_url = nexus_url + "/service/extdirect" for i in range(len(asset_ids)): aid = asset_ids[i] payload = json.dumps({ "action": "coreui_Component", "method": "readAsset", "data": [ aid, repository ], "type": "rpc", "tid": random_number }) response = requests.request("POST", api_url, headers=headers, data=payload) global INFO_NAME,INFO_REPO,INFO_CTIME,INFO_UTIME,INFO_DURL,INFO_GID,INFO_AID,INFO_VERSION response_data = response.json() if response.status_code != 200: print('get_assetid_info 获取依赖项信息失败,状态码:{}'.format(response.status_code)) if response_data['result']['success'] != True: print('get_assetid_info 获取依赖项信息失败,状态码:{}'.format(response.status_code)) else: item = response_data['result']['data'] durls = nexus_url+'/repository/'+repository+'/'+item['name'] #输入信息 print('包名:'+item['name'],'\n'+ '所在repo:',item['repositoryName'],'\n'+'创立工夫:',item['blobCreated'],'\n'+'更新工夫:',item['blobUpdated'],'\n'+'下载地址:',durls) #将信息增加到汇合用于后续解决入库 INFO_NAME.append(item['name']) INFO_REPO.append(item['repositoryName']) INFO_CTIME.append(item['blobCreated']) INFO_UTIME.append(item['blobUpdated']) INFO_DURL.append(durls) INFO_GID.append(item['attributes']['maven2']['groupId']) INFO_AID.append(item['attributes']['maven2']['artifactId']) INFO_VERSION.append(item['attributes']['maven2']['version']) #执行工夫 end = datetime.datetime.now() print('get_assetid_info totally time is ' ,end - start)成果执行成果: ...

April 24, 2023 · 2 min · jiezi

关于python爬虫:uiautomator2-操作手机

uiautomator2 操作手机目录[TOC] 一: 需要:手机插入电脑端后,能够从电脑端管制手机进行微信公众号的信息爬取 二: 抉择uiautomator2调研的起因?uiautomator2底层是Google提供的用来做安卓自动化测试的UiAutomator。 UiAutomator性能很强: 能够对第三方App进行测试获取屏幕上任意一个App的任意一个控件属性,并对其进行任意操作测试逻辑可能用python编写:将uiautomator中的性能凋谢进去,而后再将这些http接口封装成Python库UiAutomator的性能能够满足操控手机,获取组件进而提取想要的信息;uiautomator2是一个python库。基于这些方面的思考,抉择了uiautomator2进行理论调研三: 环境搭建3.1 装置python库uiautomator2(次要库)weditor(直观获取组件档次)jupyter(notebook笔记不便调试记录)3.2 配置adb环境下载adb ADB和Fastboot for Windows: https://dl.google.com/android...ADB和Fastboot for Mac: https://dl.google.com/android...ADB和Fastboot for Linux: https://dl.google.com/android...配置环境变量 windows:控制面板->零碎与平安->零碎->高级零碎设置->环境变量,将adb门路增加到PATH中linux: 编辑.bashrc, 增加export PATH=$PATH:adb门路, 而后执行source .bashrc四: 应用4.1 连贯手机 检测手机是否正确配置关上手机的开发者性能,并开启调试性能应用usb线连贯电脑时,usb用处抉择“传输文件”在命令行中应用adb devices查看是否胜利检测到获取手机连贯后的识别码import oscmd = "adb devices"r = os.popen(cmd)text = r.read() # adb devices命令的执行后果r.close() row = text.split("\n")[1]if not bool(row): print("未检测到设施")raise Exception("未检测到设施")else: con_str = row.split('\t')[0]print(con_str) # 获取识别码 应用uiautomator2连贯手机import uiautomator2 as u2d = u2.connect(con_str)print(d.info)4.2 操作微信搜寻公众号 微信版本信息d.app_info("com.tencent.mm")关上微信 输出中文的时候须要应用fastinputImed.set_fastinput_ime(True) 先关掉微信重新启动d.app_stop("com.tencent.mm")d.app_start("com.tencent.mm") # 微信 获取状态栏大小(后续滑动的时候会用到)status_bar_selector = d.xpath('//*[@resource-id="com.android.systemui:id/status_bar"]')status_bar_x, status_bar_y, status_bar_width, status_bar_height = status_bar_selector.get().rectprint(status_bar_x, status_bar_y, status_bar_width, status_bar_height)查找公众号 ...

August 17, 2022 · 2 min · jiezi

关于python爬虫:通过robotstxt中的Sitemap-寻找网站各个入口地址

# -*- coding:utf-8 -*-import requestsfrom lxml import etreedef get_sitemapinfo(robots_url): """ 性能:获得robots.txt中的Sitemap网址 返回sitemap 例如 https://www.qidian.com/newsitemap2/pcfixedsitemap.xml :param robots_url :return: https://www.qidian.com/newsitemap2/pcfixedsitemap.xml """ response = requests.get(robots_url).text try: link = response.split("Sitemap:")[-1].strip() return link except: print("以后网站robots协定 未蕴含Sitemap")def get_links(sitemap_url,rule): """ 性能:获得Sitemap下所有的入口地址 返回links 例如 ['https://www.qidian.com/all_pub/chanId13700/', 'https://www.qidian.com/all_pub/chanId14100/', 'https://www.qidian.com/all_pub/chanId14400/'] :param sitemap_url sitemap的地址 :param rule xpath匹配规定 :return: https://www.qidian.com/newsitemap2/pcfixedsitemap.xml """ response = requests.get(sitemap_url) r = etree.HTML(response.text.encode("UTF-8")) links = r.xpath(rule) return linksif __name__ == "__main__": ## 开始执行程序 # robots.txt地址 url = "https://www.qidian.com/robots.txt" sitemap_url = get_sitemapinfo(robots_url=url) links = get_links(sitemap_url=sitemap_url, rule="//url/loc/text()") print(f"links:{links}")

August 16, 2022 · 1 min · jiezi

关于python爬虫:爬虫加密字体解密

在爬取文本信息过程中 遇到字体是加密的须要把 方块数字 转换为十进制再依据woff文件中的映射关系进行对应转换须要留神的是这个字体文件url是 每距离几分钟就变动的 如发现和上一次申请的地址不一样 须要再次申请 新的woff文件具体代码如下 from fontTools.ttLib import TTFontif __name__ == '__main__': # 1 依据剖析进去的关系,初始化 把cmap 中的name 与 网页显示文本映射关系 relation_table = {'period': '.', 'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9' } # 2 获取到提取到的UTF-8 的值 text = '' # 3 下载文件并且获取文件中的 cmap 映射 ,上面简化案例假若曾经获取到了字体文件 # cmap= {100233: 'period', 100235: 'three', 100236: 'seven', 100237: 'six', 100238: 'nine', 100239: 'five', 100240: 'eight', 00241: 'two', 100242: 'one', 100243: 'four', 100244: 'zero'} font = TTFont('nxCOAYDu.woff') cmap = font.getBestCmap() # 4 转换逻辑 print(f'begin convert:text is {text}') text_list = list(text) for index, ch in enumerate(text_list): en_number = cmap.get(ord(ch), None) if en_number: alpha_str = relation_table.get(en_number, None) if alpha_str: text_list[index] = alpha_str text_final = ''.join(text_list) # 最初输入的就是页面上的数字 print(f'end convert:text is {text_final}')

August 12, 2022 · 1 min · jiezi

关于python爬虫:原创微博-关键词-爬虫

本文所有教程及源码、软件仅为技术钻研。不波及计算机信息零碎性能的删除、批改、减少、烦扰,更不会影响计算机信息零碎的失常运行。不得将代码用于非法用处,如侵立删 记一次阿里云盾滑块验证剖析并通过操作环境win10 、 macPython3.9数据接口搜寻 https://**********?containerid=100103type%3D{chanenl}%26q%3D{quote(self.words)}&page_type=searchall&page={page}user info https://**********?title=%E5%9F%BA%E6%9C%AC%E8%B5%84%E6%96%99&value={userid}'proxy配置==应用socks需装置 :pip install -U 'requests[socks]'== def _proxy(self): """ 调用 :return: """ # 判断IP是否过期 new_time = datetime.datetime.now() if self.expire_time and new_time < datetime.datetime.strptime(self.expire_time, "%Y-%m-%d %H:%M:%S"): # # 以后工夫小于到期工夫证实可用 # if new_time < datetime.datetime.strptime(self.expire_time, "%Y-%m-%d %H:%M:%S"): print(f'以后应用IP:{self.proxies} 过期工夫:{self.expire_time}') return proxy = Proxy() ip_port, expire_time = proxy.main() self.headers = proxy.headers self.proxies = { 'http': 'socks5://{}'.format(ip_port), 'https': 'socks5://{}'.format(ip_port) } self.expire_time = expire_time依据关键词获取userid def _get_userid(self, response): userid = [] content = json.loads(response) cards = content['data']['cards'] # 数据列表 for card in cards: if card['card_type'] != 11: # 状态=11返回的是用户数据列表 continue for card_group in card['card_group']: userid.append(card_group['user']['id']) # 用户id return userid依据userid获取信息 def _parse_json(self, res): content = json.loads(res) data = {} data['用户id'] = content['data']['userInfo']['id'] # userid data['用户名'] = content['data']['userInfo']['screen_name'] # 用户名 # 性别 sex = content['data']['userInfo']['gender'] data['性别'] = '女' if sex == 'f' else '男' data['微博认证名称'] = content['data']['userInfo']['verified_reason'] # 微博认证名称 data['简介'] = content['data']['userInfo']['description'] # 简介 data['粉丝数量'] = content['data']['userInfo']['followers_count'] # 粉丝数量 data['公布微博量'] = content['data']['userInfo']['statuses_count'] # 公布微博量 data['关注量'] = content['data']['userInfo']['follow_count'] # 关注量 data['用户头像'] = content['data']['userInfo']['profile_image_url'] # 用户头像 data['挪动端地址'] = content['data']['userInfo']['profile_url'] # 挪动端地址 data['关键词'] = self.words return data数据保留 def _save_xls(self, data): """ 保留数据 data : 字典格局 必须和表头长度一样 :return: """ # 判断文件是否存在 如果存在则读取而后插入新数据,不存在则创立一个新DataFrame并增加表头 file = f'{PATH}/数据/关键词-{self.words}.xlsx' Header = ['用户id', '用户名', '性别', '微博认证名称', '简介', '粉丝数量', '公布微博量', '关注量', '用户头像', '挪动端地址', '关键词'] if not os.path.exists(f'{PATH}/数据'): os.mkdir(f'{PATH}/数据') if not os.path.exists(file): # 创立一个新的文件 并写入表头 df = pd.DataFrame(columns=Header) else: # 读取现有文件 df_read = pd.read_excel(file) df = pd.DataFrame(df_read) # 定义一行新数据 data为一个字典 new_data = pd.DataFrame(data, index=[1]) # 自定义索引为:1 ,这里也能够不设置index # 把定义的新数据增加到原数据最初一行 ignore_index=True,示意不按原来的索引,从0开始主动递增 df = df.append(new_data, ignore_index=True) # 保留数据 sheet_name工作表名 index是否增加索引 header表头 df.to_excel(file, sheet_name=self.words, index=False, header=True)数据: ...

June 19, 2022 · 2 min · jiezi

关于python爬虫:西瓜视频url地址解码

https://blog.csdn.net/weixin_...

January 18, 2022 · 1 min · jiezi

关于python爬虫:Python库性能测试之re和lxml效率对比

前言闲来无事,想起来之前在简书发过的文章还没搬过去,正想搬一篇lxml和re效率比照的,后果发现代码没了,索性重写一次。 先上后果: 只做解析加取数据,re比lxml快了300%!解析加pandas解决数据,re比lxml快40%其实这个测试后果应该没什么好纠结的,预计应该是re优于lxml,二者都优于beautifulsoup。 因为很少用beautifulsoup,所以这次没测试它。 注意事项为了防止网络稳定,测试时不应该把网络申请工夫计算进去,这里应用参数传入要解析的HTML。 另外,解析语句的写法优劣会在极大水平上影响后果,所以个别工作重点应该放在表达式的写法上。 小技巧导出list列表数据的时候间接来一个pandas,省时省力 代码# -*- encoding: utf-8 -*-'''@File : test-re-lxml.py@Time : 2021年12月18日 22:33:10 星期六@Author : erma0@Version : 1.0@Link : https://erma0.cn@Desc : 测试re lxml效率'''import reimport timeimport pandas as pdimport requestsfrom lxml import etreefrom itertools import zip_longest# ahtml = requests.get('http://test.cn/').textahtml = '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>教育网盘</title><style type="text/css"><!--td { font-size: 12px;}a:link { text-decoration: none;}body { font-size: 12px;}a:visited { text-decoration: none;}a:hover { color: #FF0000; text-decoration: underline;}--></style></head><body><table width="90%" border="0" align="center" class="list"><tr bgcolor=#BFE6FD height="20"> <td width="42" align=center>图标</td> <td width="381" align=center>文件名</td> <td width="98" align=center>所属用户</td> <td width="85" align=center>大小</td> <td width="132" align=center>更新工夫</td></tr><div class=main_content_2 id=content><!-- Copyright(C) 2005-2010 All Rights Reserved. --><tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/pdf.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f1%c6%fb%b0%fc%b0%b2%d7%b0%ca%a9%b9%a4%bc%bc%ca%f5%bd%bb%b5%d7.pdf>1汽包装置施工技术交底.pdf</a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>871.49 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%cb%ae%c0%e4%b1%da%b0%b2%d7%b0%ca%a9%b9%a4%bc%bc%ca%f5%bd%bb%b5%d7.doc>水冷壁装置施工技术交底.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%2f%cb%ae%c0%e4%b1%da%b0%b2%d7%b0%ca%a9%b9%a4%bc%bc%ca%f5%bd%bb%b5%d7.doc' title='查看文件 水冷壁装置施工技术交底.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>139.66 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%cb%ae%d1%b9%ca%d4%d1%e9%bc%bc%ca%f5%bd%bb%b5%d7+-+%b8%b1%b1%be.doc>水压试验技术交底 - 正本.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%2f%cb%ae%d1%b9%ca%d4%d1%e9%bc%bc%ca%f5%bd%bb%b5%d7+-+%b8%b1%b1%be.doc' title='查看文件 水压试验技术交底 - 正本.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>173.44 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%d1%cc%b5%c0%b0%b2%d7%b0%ca%a9%b9%a4%bc%bc%ca%f5%bd%bb%b5%d7+-+%b8%b1%b1%be.doc>烟道装置施工技术交底 - 正本.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%bc%bc%ca%f5%bd%bb%b5%d7%2f%2f%d1%cc%b5%c0%b0%b2%d7%b0%ca%a9%b9%a4%bc%bc%ca%f5%bd%bb%b5%d7+-+%b8%b1%b1%be.doc' title='查看文件 烟道装置施工技术交底 - 正本.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>130.84 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f(%d7%ee%d6%d5%a3%a9%c9%bd%ce%f7%b6%ab%d2%e5%b8%c9%cf%a8%bd%b9%b9%a4%b3%cc%ca%a9%b9%a4%d7%e9%d6%af%c9%e8%bc%c60610.doc>(最终)山西东义干熄焦工程施工组织设计0610.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f(%d7%ee%d6%d5%a3%a9%c9%bd%ce%f7%b6%ab%d2%e5%b8%c9%cf%a8%bd%b9%b9%a4%b3%cc%ca%a9%b9%a4%d7%e9%d6%af%c9%e8%bc%c60610.doc' title='查看文件 (最终)山西东义干熄焦工程施工组织设计0610.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>2.4 M</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%b6%ab%d2%e5%b8%c9%cf%a8%bd%b9%b9%f8%c2%af%cb%ae%d1%b9%ca%d4%d1%e9%b7%bd%b0%b8(1)10.10.docx>东义干熄焦锅炉水压试验计划(1)10.10.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%b6%ab%d2%e5%b8%c9%cf%a8%bd%b9%b9%f8%c2%af%cb%ae%d1%b9%ca%d4%d1%e9%b7%bd%b0%b8(1)10.10.docx' title='查看文件 东义干熄焦锅炉水压试验计划(1)10.10.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>103.62 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%c9%bd%ce%f7%b8%c9%cf%a8%bd%b9%b9%f8%c2%af%cb%ae%c0%e4%b1%da%b0%b2%d7%b0%b7%bd%b0%b80507.doc>山西干熄焦锅炉水冷壁装置计划0507.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%c9%bd%ce%f7%b8%c9%cf%a8%bd%b9%b9%f8%c2%af%cb%ae%c0%e4%b1%da%b0%b2%d7%b0%b7%bd%b0%b80507.doc' title='查看文件 山西干熄焦锅炉水冷壁装置计划0507.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>711.05 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%b6%ab%d2%e5%c6%fb%b0%fc%b5%f5%d7%b0%ca%a9%b9%a4%b7%bd%b0%b8+0710.docx>东义汽包吊装施工计划 0710.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%b6%ab%d2%e5%c6%fb%b0%fc%b5%f5%d7%b0%ca%a9%b9%a4%b7%bd%b0%b8+0710.docx' title='查看文件 东义汽包吊装施工计划 0710.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>989.66 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2fPQR044(12Cr2MoG%a3%ac273%a1%c113)SMAW%2bGTAW.doc>PQR044(12Cr2MoG,273×13)SMAW+GT...</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2fPQR044(12Cr2MoG%a3%ac273%a1%c113)SMAW%2bGTAW.doc' title='查看文件 PQR044(12Cr2MoG,273×13)SMAW+GTAW.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>20.24 M</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%b9%f8%c2%af%ba%b8%bd%d3%ca%a9%b9%a4%b7%bd%b0%b80525.doc>锅炉焊接施工计划0525.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%b9%f8%c2%af%ba%b8%bd%d3%ca%a9%b9%a4%b7%bd%b0%b80525.doc' title='查看文件 锅炉焊接施工计划0525.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>711.5 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/doc.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%c9%bd%ce%f7%b6%ab%d2%e5%b9%f8%c2%af%b8%d6%bc%dc%b0%b2%d7%b0%ca%a9%b9%a4%b7%bd%b0%b80520.doc>山西东义锅炉钢架装置施工计划0520.doc</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%c9%bd%ce%f7%b6%ab%d2%e5%b9%f8%c2%af%b8%d6%bc%dc%b0%b2%d7%b0%ca%a9%b9%a4%b7%bd%b0%b80520.doc' title='查看文件 山西东义锅炉钢架装置施工计划0520.doc ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>1.08 M</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%b6%ab%d2%e5230T%b8%c9%cf%a8%bd%b9%d3%e0%c8%c8%b9%f8%c2%af%b0%b2%d7%b0%b7%bd%b0%b8.docx>东义230T干熄焦余热锅炉装置计划.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%b6%ab%d2%e5230T%b8%c9%cf%a8%bd%b9%d3%e0%c8%c8%b9%f8%c2%af%b0%b2%d7%b0%b7%bd%b0%b8.docx' title='查看文件 东义230T干熄焦余热锅炉装置计划.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>418.04 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%b6%ac%bc%be%ca%a9%b9%a4%b7%bd%b0%b8+11.11.docx>夏季施工计划 11.11.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%bc%bc%ca%f5%2f%ca%a9%b9%a4%b7%bd%b0%b8%2f%2f%b6%ac%bc%be%ca%a9%b9%a4%b7%bd%b0%b8+11.11.docx' title='查看文件 夏季施工计划 11.11.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>47.07 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/pdf.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f1%c6%fb%b0%fc%b0%b2%d7%b0%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.pdf>1汽包装置平安技术交底.pdf</a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>908.46 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%d3%e0%c8%c8%b9%f8%c2%af%c8%eb%bf%da%d1%cc%b5%c0%b0%b2%d7%b0%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx>余热锅炉入口烟道装置平安技术交底.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%d3%e0%c8%c8%b9%f8%c2%af%c8%eb%bf%da%d1%cc%b5%c0%b0%b2%d7%b0%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx' title='查看文件 余热锅炉入口烟道装置平安技术交底.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>50.87 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%d3%e0%c8%c8%b9%f8%c2%af%b8%d6%bd%e1%b9%b9%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx>余热锅炉钢结构平安技术交底.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%d3%e0%c8%c8%b9%f8%c2%af%b8%d6%bd%e1%b9%b9%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx' title='查看文件 余热锅炉钢结构平安技术交底.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>50.86 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%b5%f5%d7%b0%d6%b8%bb%d3%b0%b2%c8%ab%bd%bb%b5%d7.docx>吊装指挥平安交底.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%b5%f5%d7%b0%d6%b8%bb%d3%b0%b2%c8%ab%bd%bb%b5%d7.docx' title='查看文件 吊装指挥平安交底.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>13.59 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%cb%ae%d1%b9%ca%d4%d1%e9%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx>水压试验平安技术交底.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%cb%ae%d1%b9%ca%d4%d1%e9%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx' title='查看文件 水压试验平安技术交底.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>48.24 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%d2%c6%b6%af%bd%c5%ca%d6%bc%dc%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7+-+10.31.docx>挪动脚手架平安技术交底 - 10.31.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%d2%c6%b6%af%bd%c5%ca%d6%bc%dc%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7+-+10.31.docx' title='查看文件 挪动脚手架平安技术交底 - 10.31.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>45.41 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> <tr bgcolor=#E8F0FF height=20><td width=25 align=center><img src=http://pan.test.com/filetype/docx.gif></td><td><a href=homeapply.aspx?down=ok&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%d3%e0%c8%c8%b9%f8%c2%af%cb%ae%c0%e4%b1%da%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx>余热锅炉水冷壁平安技术交底.docx</a><a href='http://pan.test.com/show.aspx?type=4&filepath=HNAZ%2f%b0%b2%c8%ab%2f%b0%b2%c8%ab%bd%bb%b5%d7%2f%2f%d3%e0%c8%c8%b9%f8%c2%af%cb%ae%c0%e4%b1%da%b0%b2%c8%ab%bc%bc%ca%f5%bd%bb%b5%d7.docx' title='查看文件 余热锅炉水冷壁平安技术交底.docx ' target=_blank><img src=http://pan.test.com/pics/edit.gif border=0></a> <font color=#999999></font></td><td width=120 align=center>HNAZ</td><td width=120> <div lign=center>50.98 K</div></td><td width=120><div align=center>2021-11-23</div></td></tr> </div><tr> <td colspan="5" align=center><div align="center">总共记录数:3276页码:<a href=http://test.com/newshare.aspx?page=10 class=page>...</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=11 class=page>11</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=12 class=page>12</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=13 class=page>13</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=14 class=page>14</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=15 class=page>15</a>&nbsp;&nbsp;<span class=10>16</span>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=17 class=page>17</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=18 class=page>18</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=19 class=page>19</a>&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=20 class=page>20</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href=http://test.com/newshare.aspx?page=21 class=page>...</a><a href=http://test.com/newshare.aspx?page=1>第一页</a><a href=http://test.com/newshare.aspx?page=15>上一页</a><a href=http://test.com/newshare.aspx?page=17>下一页</a><a href=http://test.com/newshare.aspx?page=164>最末页</a>第16页/共164页 </div></td> </tr></table></body></html>'''def get_lxml(html): d = etree.HTML(html) link = d.xpath('//tr/td[2]/a[1]/@href') title = d.xpath('//tr/td[2]/a[1]/text()') passwd = d.xpath('//tr/td[2]/font/text()') user = d.xpath('//tr/td[3][@width="120"]/text()') size = d.xpath('//tr/td[4]/div/text()') time = d.xpath('//tr/td[5]/div/text()') datas = list(zip_longest(link, title, passwd, user, size, time, fillvalue='')) datas = pd.DataFrame(datas, columns=['link', 'title', 'passwd', 'user', 'size', 'time']) datas['link'] = datas['link'].str.strip() datas.to_csv('result-lxml.csv') # print(len(datas)) return datasdef get_re(html): datas = [] # datas= r.findall(html) datas = re.findall(rep, html, re.S) # for data in datas: # link, title, passwd, user, time # pass # print(len(datas)) datas = pd.DataFrame(datas, columns=['link', 'title', 'passwd', 'user', 'size', 'time']) datas['link'] = datas['link'].str.strip() datas.to_csv('result-re.csv') return datasif __name__ == '__main__': rep = r"<td><a href=([\s\S]*?)>([\s\S]*?)</a>[\s\S]*?<font color=#999999>([\s\S]*?)</font>[\s\S]*?center>([\s\S]*?)</td><td width=120> <div lign=center>([\s\S]*?)</div></td><td width=120><div align=center>([\s\S]*?)</div>" r = re.compile(rep, re.S) for name, function in [('lxml', get_lxml), ('re', get_re)]: start = time.time() for i in range(500): function(ahtml) # function(ahtml) end = time.time() print(name, end - start)后果lxml 2.1219968795776367re 1.341965675354004re比lxml快了靠近40% ...

December 19, 2021 · 4 min · jiezi

关于python爬虫:node爬虫爬取网页图片

前言周末本人在家闲着没事,刷着微信,玩着手机,发现自己的微信头像该换了,就去网上找了一下头像,看着图片,本人就想着作为一个码农,能够把这些图片都爬取下来做成一个微信小程序,说干就干,理解一下根本都晓得怎么做了,整顿分享一波给大家。 目录装置node,并下载依赖搭建服务申请咱们要爬取的页面,返回json装置node咱们开始装置node,能够去node官网下载nodejs.org/zh-cn/,下载实现后运行node应用, node -v装置胜利后会呈现你所装置的版本号。 接下来咱们应用node, 打印出hello world,新建一个名为index.js文件输出 console.log('hello world')运行这个文件 node index.js就会在控制面板上输入hello world 搭建服务器新建一个·名为node的文件夹。 首先你须要下载express依赖 npm install express 复制代码再新建一个名为demo.js的文件 目录构造如图: !img](https://p1-jj.byteimg.com/tos...) 在demo.js引入下载的express const express = require('express');const app = express();app.get('/index', function(req, res) {res.end('111')})var server = app.listen(8081, function() { var host = server.address().address var port = server.address().port console.log("利用实例,拜访地址为 http://%s:%s", host, port)})运行node demo.js简略的服务就搭起来了,如图: !img](https://p1-jj.byteimg.com/tos...) 申请咱们要爬取的页面申请咱们要爬取的页面 npm install superagentnpm install superagent-charsetnpm install cheeriosuperagent 是用来发动申请的,是一个轻量的,渐进式的ajax api,可读性好,学习曲线低,外部依赖nodejs原生的申请api,实用于nodejs环境下.,也能够应用http发动申请 superagent-charset避免爬取下来的数据乱码,更改字符格局 cheerio为服务器特地定制的,疾速、灵便、施行的jQuery外围实现.。 装置完依赖就能够引入了 var superagent = require('superagent');var charset = require('superagent-charset');charset(superagent);const cheerio = require('cheerio');引入之后就申请咱们的地址,https://www.qqtn.com/tx/weixi...,如图: ...

December 8, 2021 · 2 min · jiezi

关于python爬虫:高级爬虫实战系统掌握破解反爬技能-挑战高薪

download:高级爬虫实战-零碎把握破解反爬技能 挑战高薪自己公司筹备换SpringCloud微服务,最近正在学习这方面的货色,总结一下浅显易懂的资料,分享一下。 运行环境: jdk8+mysql+IntelliJ IDEA+maven 我的项目技术 springboot+maven+Hibernate+thymeleaf 数据库文件 链接: https://pan.baidu.com/s/1qZVl4Qw 明码:2ngr 链接: https://pan.baidu.com/s/1nxqqvsX 明码: cc4r 我的项目截图 一、json 接口开发 在以前的spring 开发的时候需要咱们提供json接口的时候需要做的配置 1.增加 jackjson 等相干jar包 2.配置spring controller扫描 3.对接的方法增加@ResponseBody 就这样咱们会常常因为配置谬误,导致406谬误等等,spring boot如何做呢,只需要类增加@RestController即可,默认类中的方法都会以json的格局返回 二、自定义Filter Spring Boot主动增加了OrderedCharacterEncodingFilter和HiddenHttpMethodFilter,并且咱们可能自定义Filter 两个步骤: 1.实现Filter接口,实现Filter方法 2.增加@Configuration 注解,将自定义Filter加入过滤链 三、自定义Property 配置在application.propertie定义配置(这里要首先把redis服务起来,其余地方有用到redis,不起会报错,保障数据库连接正确) 测试通过 四、数据库操作 1、增加相jar包 2、添配置文件 hibernate.hbm2ddl.auto参数的作用次要用于:主动创建|更新|考据数据库表结构,有四个值: (1)、create: 每次加载hibernate时都会删除上一次的生成的表,而后根据你的model类再从新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。 (2)、create-drop :每次加载hibernate时根据model类生成表,然而sessionFactory一敞开,表就主动删除。 (3)、update:最罕用的属性,第一次加载hibernate时根据model类会主动建立起表的结构(前提是先建立好数据库),当前加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 利用第一次运行起来后才会。 (4)、validate :每次加载hibernate时,考据创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,然而会插入新值。 dialect 次要是指定生成表名的存储引擎为InneoDBshow-sql 是否打印出主动生产的SQL,便利调试的时候查看 3、增加实体类和Dao SpringBoot入门整合开发java Web我的项目实例 dao只需继承JpaRepository类就可能,几乎可能不必写方法,可能根据方法名来主动的生产SQL,比如findByUserName 会主动生产一个以 userName 为参数的查问方法,比如 findAlll 主动会查问表外面的所有数据,比如主动分页等等。。 Entity中不映射成列的字段得加@Transient注解,不加注解也会映射成列 SpringBoot入门整合开发java Web我的项目实例测试 SpringBoot入门整合开发java Web我的项目实例 五、Spring boot中Redis的使用 ...

October 26, 2021 · 1 min · jiezi

关于python爬虫:Python爬虫教程四

一、线程、过程、协程的概念 线程:是过程的一个执行单元,是过程内可调度实体。比过程更小的独立运行的根本单位。线程也被称为轻量级过程。 过程:是并发执行的程序在执行过程中调配和治理资源的根本单位,是一个动静概念,竞争计算机系统资源的根本单位。 协程:是一种比线程更加轻量级的存在。一个线程也能够领有多个协程。其执行过程更相似于子例程,或者说不带返回值的函数调用。 二、多线程 1.单线程:两个局部的工作,执行完后面再执行前面工作。 2.多线程 通过输入后果,能够看到两个线程是同时进行工作的,但工作执行由CPU决定(能够创立多个线程)。 3.第二种多线程办法 其输入后果与第一种形式相似,可通过后果看出两个线程在同时工作。 4.建设多个子线程。 三、多过程 其逻辑与多线程逻辑基本相同。 四、线程池及过程池 咱们可通过线程池和过程池进行多个线程或过程的并行运算。 1.线程池 2.过程池 五、协程 1.协程:协程是比线程更小的一种执行单元,你能够认为是轻量级的线程,当程序遇见IO操作时,能够抉择切换到其余工作上,更适宜于用来实现彼此相熟的程序组件,如单干式多任务,迭代器,有限列表和管道。 宏观上是一个工作一个工作进行切换,切换条件是IO操作;宏观上为多个工作一起执行(多任务异步操作)。 2.异步协程及同步操作。 同步操作输入后果:运行工夫9秒,根本为等待时间。 异步操作: 异步操作输入后果:4秒的工夫根本为最长等待时间,两个工夫比照可看出异步操作为同时启动多个工作。 3.应用异步协程实战下载柔美图库图片,抉择三张图片下载地址进行简略的下载,学习aiohttp模块的利用,与requests模块进行比照。 输入后果: 4.实战爬取百度小说西游记全文。 其页面源代码中没有小说内容,关上开发者工具,点击查看全副章节。 找到题目内容及题目内容所在链接。上面寻找小说具体内容及内容所在链接,点击任意一章进入。 上面进行小说内容爬取,小说内容较多,咱们应用异步协程的形式进行爬取,通过book_id、c_id进行传参,可通过批改book_id即可爬取百度小说中其余小说的内容。 

October 9, 2021 · 1 min · jiezi

关于python爬虫:python爬虫教程一

 Python版本:python3.6 应用工具:pycharm 一、第一个爬虫程序 取得网址源代码。如下图获取百度页面源代码。 二、Web申请过程 1. 服务器渲染:在服务器中间接把数据和html整合在一起,返回给浏览器。(在页面源代码中能看到数据) 2. 客户端渲染:第一次申请只有一个html骨架,第二次申请拿到数据,进行数据展现。(在页面源代码中,看不到数据) 三、requests入门 1. 获取搜狗引擎搜寻周杰伦页面源代码。 2. 呈现报错,网页存在反爬,解决反扒。 3. 批改代码,使其更加灵便获取不同搜寻内容对应不同页面源代码。 4.当申请形式为POST时,以百度翻译为例获取页面源代码。 5. 当想要爬取数据与网页框架不在一起时。以豆瓣电影排行榜为例。需先找到所需爬取数据地位。 将其参数变量进行封装,补充网址参数,其参数信息地位及代码如下: 留神:应用完爬虫程序后,敞开爬虫程序。 如上示例需应用resp.close()敞开爬虫程序。 四、数据解析 本文中将介绍三种解析形式:re解析、bs4解析、xpath解析。 1、re解析:Regular Expression,正则表达式,一种应用表达式的形式对字符串进行匹配的语法规定。 长处:速度快、效率高、准确性高 毛病:上手难度较高 语法:应用元字符进行排列组合用来匹配字符串(元字符是具备固定含意的特殊符号),罕用元字符: . 匹配除换行符以外的任意字符 a|b 匹配字符a或b \w 匹配字母或数字或下划线 \W 匹配非字母或数字或下划线 \s 匹配任意空白符 \S 匹配非空白符 \d 匹配数字 \D 匹配非数字 […] 匹配字符组中的字符 [^…] 匹配除字符组中的所有字符 ^ 匹配字符串的开始 $ 匹配字符串的完结 量词:管制元字符呈现的次数 * 反复零次或屡次 + 反复一次或屡次 ? 反复零次或一次 {n} 反复n次 {n,} 反复n次或更屡次 {n,m} 反复n到m次 (1)re模块应用,findall() 匹配字符串中所有的合乎正则的内容 ...

September 14, 2021 · 1 min · jiezi

关于python爬虫:爬虫docker-部署-python-selenium-firefoxheadless

外观往往和事物的自身齐全不符,世人都容易为外表的装璜所坑骗。—— 莎士比亚 《威尼斯商人》一. 概述上一篇文章 【爬虫】python+selenium+firefox应用与部署详解 介绍了 selenium 传统形式部署与应用,须要装置浏览器、装置浏览器对应的驱动等,对于我来说配置还是比拟繁琐,有没有没有简略的配置形式呢?有,那就是应用 docker 来部署,接下来将介绍如何应用 docker 部署 python + selenium + firefox-headless。 二. docker 装置 selenium/standalone-firefoxselenium docker hub 地址:https://hub.docker.com/u/sele...拜访下面的地址,抉择一个对应浏览器镜像,这里抉择 selenium/standalone-firefox,如下图所示: 疾速开始更多配置与应用能够查看 github:https://github.com/SeleniumHQ...应用上面的命令启动一个 Firefox 的 docker 容器: $ docker run --name firefox -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:3.141拜访 http://localhost:4444 测试 webDriver,如下图所示: 拜访 http://localhost:4444/wd/hub/... 跳转到 selenium 控制台,如下图所示: 留神: 当为蕴含浏览器的镜像执行docker运行时,请应用标记 --shm-size 2g 来应用主机的共享内存始终应用带有残缺标签的 Docker 镜像来固定特定的浏览器和网格版本。为什么须要设置 --shm-size 2g: 这是一个已知的解决方案,以防止在docker容器内浏览器解体,2gb的shm大小是任意的,但已知能够很好地工作,您的特定用例可能须要不同的值,倡议依据您的须要调整这个值。 能够应用上面的命令进入到 firefox 容器中: docker exec -it firefox bash应用上面命令,能够看到容器中曾经装置好了 firefox 和 geckodriver: ...

August 17, 2021 · 2 min · jiezi

关于python爬虫:Python爬取爱奇艺网剧隐秘的角落弹幕数据实现简单可视化附源码

Python爬取爱奇艺网剧《隐秘的角落》弹幕数据,实现简略可视化(附源码) 明天指标爬取201865 条《隐秘的角落》弹幕数据 工具应用开发环境: win10、python3.6 开发工具: pycharm 相干模块 : requests,stylecloud 思路剖析1、爬虫获取数据爱奇艺的弹幕数据是以 .z 模式的压缩文件存在的,先获取 tvid 列表,再依据 tvid 获取弹幕的压缩文件,最初对其进行解压及存储,大略就是这样一个过程。 def get_data(tv_name,tv_id): url = 'https://cmts.iqiyi.com/bullet/{}/{}/{}_300_{}.z' datas = pd.DataFrame(columns=['uid','contentsId','contents','likeCount']) for i in range(1,20): myUrl = url.format(tv_id[-4:-2],tv_id[-2:],tv_id,i) print(myUrl) res = requests.get(myUrl) if res.status_code == 200: btArr = bytearray(res.content) xml=zlib.decompress(btArr).decode('utf-8') bs = BeautifulSoup(xml,"xml") data = pd.DataFrame(columns=['uid','contentsId','contents','likeCount']) data['uid'] = [i.text for i in bs.findAll('uid')] data['contentsId'] = [i.text for i in bs.findAll('contentId')] data['contents'] = [i.text for i in bs.findAll('content')] data['likeCount'] = [i.text for i in bs.findAll('likeCount')] else: break datas = pd.concat([datas,data],ignore_index = True) datas['tv_name']= str(tv_name) return datas共爬获得到201865 条《隐秘的角落》弹幕数据。 ...

August 16, 2021 · 1 min · jiezi

关于python爬虫:Python爬虫豆瓣网热门话题保存文本本地数据并实现简单可视化

Python爬虫豆瓣网热门话题保留文本本地数据,并实现简略可视化。前言明天给大家分享Python爬虫豆瓣网热门话题保留文本本地数据 开发环境:windows10python3.6.4 开发工具:pycharm库:requests、WordCloud、pandas、jieba 代码展现 词云生成 爬虫代码过程1、保留短评数据通过浏览器“查看”剖析,失去URL数据接口。在一直往下刷新页面的过程中,发现URL中只有“start”参数一直产生变动,顺次为0,20,40,60,80--- 同时,为了破解“豆瓣”的防爬虫机制,申请数据时需携带“申请头(headers)”中的“User-Agent”和“Referer”两个参数。 源码import requestsfor i in range(0,200,20): # 通过浏览器查看,失去数据的URL起源链接 url = 'https://m.douban.com/rexxar/api/v2/gallery/topic/125573/items?' \ 'sort=new&start={}&count=20&status_full_text=1&guest_only=0&ck=null'.format(i) # 破解防爬虫,带上申请头 # 这两个不能省略 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0".3809.100 Safari/537.36', 'Referer': 'https://www.douban.com/gallery/topic/125573/?from=gallery_trend&sort=hot'} # 发送申请,获取响应 reponse = requests.get(url, headers=headers) html = reponse.json() # 解析数据,取得短评 # 保留到本地 for j in range(19): abs = html['items'][j]['abstract'] with open("want_after.txt", "a", encoding='utf-8') as f: f.write(abs) print(abs)2、词云可视化把数据保留之后,须要利用“jieba”对数据进行分词;进而,通过分词后的数据绘制词云“wordcloud”,可视化展现数据。 from wordcloud import WordCloudimport matplotlib.pyplot as pltimport pandas as pdimport jieba# 取得wordcloud 须要的 文本格式with open("want_after.txt", "r", encoding='utf-8') as f: text = ' '.join(jieba.cut(f.read(),cut_all=False)) # print(text)backgroud_Image = plt.imread('豆瓣.jpg') # 背景图# 词云的一些参数设置wc = WordCloud( background_color='white', mask=backgroud_Image, font_path='SourceHanSerifCN-Medium.otf', max_words=200, max_font_size=200, min_font_size=8, random_state=50, )# 生成词云word_cloud = wc.generate_from_text(text)plt.imshow(word_cloud)plt.axis('off')wc.to_file('后果.jpg') ...

August 13, 2021 · 1 min · jiezi

关于python爬虫:Python爬虫鲁迅先生经典语录保存到Excel表格附源码

Python爬虫鲁迅学生《经典语录》保留到Excel表格(附源码)前言明天用Python 爬取鲁迅学生《经典语录》,间接开整~ 代码运行成果展现 开发工具Python版本: 3.6.4 相干模块 requests lxml pandas 以及Python自带的模块 思路剖析1、获取数据 通过“好句子迷”网站,获取网页。 http://www.shuoshuodaitupian.com/writer/128_1利用request模块,通过URL链接,获取html网页,下一步进行网页剖析。 其中,URL只有最初一部分产生扭转(1-10 :代表第1页--第10页的全部内容) # 1、获取数据headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " \ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36", }for i in range(0, 9): url = "http://www.shuoshuodaitupian.com/writer/128_" + str(i + 1) # 1-10页 result = requests.get(url, headers=headers).content.decode() 2、解析数据通过Xpath语句解析,别离获取句子的内容、起源和评分等,如图所示。 把获取的每一组数据,放在一个字典里,再把字典追加到一个列表中。 源码: # 2、解析数据html = etree.HTML(result)div_list = html.xpath('//div[@class="item statistic_item"]')div_list = div_list[1:-1]for div in div_list: # 遍历每一条信息 item = {} # ./ 留神从以后节点,向下获取 item['content'] = div.xpath('./a/text()')[0] item['source'] = div.xpath('./div[@class="author_zuopin"]/text()')[0] item['score'] = div.xpath('.//a[@class="infobox zan like "]/span/text()')[0] item_list.append(item)print("正在爬取第{}页".format(i + 1))time.sleep(0.1)保留数据:把上述获取的数据放到一个列表中后,可通过pandas模块把数据类型转变为DataFrame,进而能够轻松地保留到excel文件中。为避免中文乱码,留神编码格局。3、保留数据df = pd.DataFrame(item_list) # 把数据存成csv文件df.to_csv('鲁迅经典语录.csv', encoding='utf_8_sig') # 保障不乱码依照评分进行排序之后的后果,如下图。 ...

August 12, 2021 · 1 min · jiezi

关于python爬虫:python-正则表达式-re-模块总结

孤单中,你能够取得所有,除了品格。—— 司汤达《红与黑》概述后面一篇文章 python应用正则表达式从json字符串中取出特定字段的值 简略应用了 re 模块的办法,然而对其余的办法并不相熟,为了更全面的理解和应用 python 中的 re,这里将本人学习的过程记录下来。 应用爬虫爬取网页数据的过程中,须要利用各种工具解析网页中的数据,比方:etree,BeautifulSoup,scrapy 等工具,然而性能最弱小的还是正则表达式,上面将对 python 的 re 模块办法做一个总结。 Python 通过 re 模块提供对正则表达式的反对。应用 re 的个别步骤是: 应用 re.compile(正则表达式) 将正则表达式的字符串模式编译为Pattern实例应用Pattern实例提供的办法解决文本并取得匹配后果(一个Match实例)应用Match实例取得信息,进行其余的操作一个简略的例子: # -*- coding: utf-8 -*-import reif __name__ == '__main__': # 将正则表达式编译成Pattern对象 pattern = re.compile(r'hello') # 应用Pattern匹配文本,取得匹配后果,无奈匹配时将返回None match = pattern.match('hello world!') if match: # 应用Match取得分组信息 print(match.group()) # 输入后果:hello 应用原生字符串定义正则表达式能够不便的解决转义字符的问题 原生字符串的定义形式为:r'' 有了原生字符串,不须要手动增加本义符号,它会主动本义,写进去的表达式也更直观。 1. 应用 rere.compile(strPattern[, flag]): 这个办法是Pattern类的工厂办法,用于将字符串模式的正则表达式编译为Pattern对象。 第一个参数:正则表达式字符串 第二个参数(可选):是匹配模式,取值能够应用按位或运算符'|'示意同时失效,比方 re.I | re.M。 可选值如下: re.I(re.IGNORECASE): 疏忽大小写(括号内是残缺写法,下同)M(MULTILINE): 多行模式,扭转'^'和'$'的行为S(DOTALL): 点任意匹配模式,扭转'.'的行为L(LOCALE): 使预约字符类 \w \W \b \B \s \S 取决于以后区域设定U(UNICODE): 使预约字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性X(VERBOSE): 具体模式。这个模式下正则表达式能够是多行,疏忽空白字符,并能够退出正文。以下两个正则表达式是等价的: ...

August 12, 2021 · 3 min · jiezi

关于python爬虫:临近秋招老油条带你一键爬取阿里百度字节大厂面试真题

前言本文爬虫源码已由 GitHub https://github.com/2335119327/PythonSpider 曾经收录(外延更多本博文没有的爬虫,有趣味的小伙伴能够看看),之后会继续更新,欢送Star。博主 长年游荡于牛客面经区,总结了字节、阿里、百度、腾讯、美团等等大厂的高频考题,然而明天,我教大家如何进行面经爬取,如果能帮到各位小伙伴,麻烦一件三连多多反对,感谢不敬!!! 本次爬取以Java面经为例,学会的小伙伴能够依照法则爬取牛客任意面经 教学进入Java面经区,关上控制台刷新申请 能够发现,发送浏览器中的URL,失去的响应内容是没有面经的,那么面经的数据从何而来???不要焦急,那么多申请咱们接着看! 往下滑,能够看见带json的申请,教训通知我就是这个申请 复制该URL,咱们去浏览器申请该URL,可发现咱们失去了面经的数据 然而,面经是JSON格局,咱们能够复制到在线json解析工具去查看,如下 能够看到data下的discussPosts下保留着所有的帖子即面经信息 然而这个json不像我以前见到的,这个json串没有间接保留帖子详情页的URL,然而咱们能够提供过拜访门路发现法则 能够看见拜访门路有个675866,就是对应json串中的postId,而前面的参数是能够省略的 小技巧想必单页面经是必定不能满足各位小伙伴的,那么如果进行多页爬取呢,不要焦急,我来为大家总结法则,也心愿小伙伴们能一键三连哦!!! 一样的套路,如下图是C++区域的面经JSON字符串,应该不必我多教了吧 残缺代码麻烦各位小伙伴关注公众号,后盾回复 ==爬取大厂面试题== 即可取得残缺源码 后续公众号也会只需公布优质博文,不容爬虫小伙伴们错过哦! 后果展现 最初我是 Code皮皮虾,一个酷爱分享常识的 皮皮虾爱好者,将来的日子里会不断更新出对大家无益的博文,期待大家的关注!!! 创作不易,如果这篇博文对各位有帮忙,心愿各位小伙伴能够==一键三连哦!==,感激反对,咱们下次再见~~~ ==分享纲要== 大厂面试题专栏Java从入门到入坟学习路线目录索引开源爬虫实例教程目录索引更多精彩内容分享,请点击 Hello World (●'◡'●) 本文爬虫源码已由 GitHub https://github.com/2335119327/PythonSpider 曾经收录(外延更多本博文没有的爬虫,有趣味的小伙伴能够看看),之后会继续更新,欢送Star。

July 12, 2021 · 1 min · jiezi

关于python爬虫:Python爬虫小白教学篇豆瓣93超高评分觉醒年代热评爬取生成精美词云

精美词云 《沉睡年代》热评爬取解说 点击好评 多页爬取解说 热评爬取剖析一个热评对应一个class值为comment-item的div标签 所以咱们只需获取全副class值为comment-item的div标签即可获取以后页面全副热评 然而,热评具体又存储在class值为comment-itemdiv标签下的class值为short的span标签下 所以咱们只需获取全副class值为short的span标签即可获取以后页面全副热评 spans = data.find_all(class_="short")for i in spans: global_text += ",".join(jieba.cut(str(i.text).strip())) 残缺代码import matplotlib.pyplot as pltimport wordcloudimport jiebafrom imageio import imreadimport requestsfrom bs4 import BeautifulSoupglobal_text = ""def getDetail(data): global global_text data = BeautifulSoup(data,"html.parser") spans = data.find_all(class_="short") for i in spans: global_text += ",".join(jieba.cut(str(i.text).strip())) # 对获取到的热评分词def toWordCloud(): global global_text mask = imread("./9.png") #设置背景图 wcd = wordcloud.WordCloud( font_path="C:\Windows\Fonts\msyh.ttc", background_color='white', #设置背景色彩 random_state=80, # 色彩品种 mask=mask) wcd.generate(global_text) wcd.to_file("res.jpg") #保留为图片 plt.imshow(wcd) plt.axis('off') plt.show()if __name__ == '__main__': headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64" } url = 'https://movie.douban.com/subject/30228394/comments?percent_type=h&start={}&limit=20&status=P&sort=new_score' for i in range(6,10): new_url = url.format(i * 20) response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' getDetail(response.text) toWordCloud()最初我是 Code皮皮虾,一个酷爱分享常识的 皮皮虾爱好者,将来的日子里会不断更新出对大家无益的博文,期待大家的关注!!! ...

July 12, 2021 · 1 min · jiezi

关于python爬虫:为什么隧道代理没有更换IP

转载:为什么你的隧道代理没有更换IP 有局部小伙伴反馈在客户端应用隧道代理动静版(每次申请更换IP) 的过程中发现没有更换IP,遂狐疑是咱们隧道代理服务器的问题,其实不然。明天咱们就在这里谈谈,为什么会有隧道代理会呈现没有更换IP的状况。 长久连贯须要理解,HTTP/1.1(以及 HTTP/1.0 的各种加强版本)容许 HTTP 在申请解决完结之后将 TCP 连贯放弃在关上状态(并不会立刻敞开),以便为将来的 HTTP 申请重用之前建设的连贯。在申请解决完结之后依然放弃在关上状态的 TCP 连贯被称为长久连贯。而非长久连贯则会在每个申请完结之后敞开。长久连贯会在不同申请之间放弃关上状态,直到客户端或服务端决定将其敞开为止。重用已对指标服务器关上的闲暇长久连贯,就能够避开迟缓的连贯建设阶段。而且,曾经关上的连贯还能够防止慢启动的拥塞适应阶段,以便更疾速地进行数据的传输。 HTTP客户端举例通过下面的内容咱们理解到,开启Keep-Alive能够更疾速的进行数据传输。最常见的应用场景就是浏览器在关上一个网页,并不会为了每个资源都开打一个TCP连贯,而是会同时关上大量TCP连贯,利用Keep-Alive机制,一直利用大量连贯传输少数HTTP申请。因为去除了进行连贯和敞开连贯的开销,因而放慢访问速度。 在一些编程语言开发的HTTP客户端,爬虫框架中,除了会应用异步形式发送申请,也会应用TCP连贯复用来减速解决使用者的申请。 Python-Requests应用Requests提供的Session发送申请时,除了会主动保留cookie,还会应用urllib3底层提供的connection-pooling(连接池) 例如利用requests-session配置隧道代理动静版间断发送3个申请并打印出以后应用的代理IP import timeimport requests username = "txxxxxxxxxxxxx"password = "password"tunnel = "tpsXXX.kdlapi.com"proxies = { "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}, "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}}s = requests.session()for i in range(3): res = s.get('https://dev.kdlapi.com/testproxy', proxies=proxies) print(res.text) time.sleep(1)sucess! client ip: 175.7.196.238 sucess! client ip: 175.7.196.238 sucess! client ip: 175.7.196.238 能够发现三次都是同一个IP,并且应用Wireshark抓包查看,很显著这三次申请都走了一个TCP连贯。 ...

July 7, 2021 · 1 min · jiezi

关于python爬虫:python爬取中国天气网7天天气并保存至本地

1.中国天气网http://www.weather.com.cn/weather/101010100.shtml 2.剖析页面 3.浏览器-F12-定位查看元素嵌套关系 4.导入须要的库 import requestsfrom bs4 import BeautifulSoupimport re5.代码局部 result_list_wt = []def get_page(url): try: kv = {'user-agent':'Mozilla/5.0'} r = requests.get(url,headers = kv) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: return 'error'def parse_page(html, return_list): soup = BeautifulSoup(html, 'html.parser') day_list = soup.find('ul', 't clearfix').find_all('li') for day in day_list: date = day.find('h1').get_text() wea = day.find('p', 'wea').get_text() if day.find('p', 'tem').find('span'): hightem = day.find('p', 'tem').find('span').get_text() else: hightem = '' lowtem = day.find('p', 'tem').find('i').get_text() win = re.findall('(?<= title=").*?(?=")', str(day.find('p','win').find('em'))) wind = '-'.join(win) level = day.find('p', 'win').find('i').get_text() return_list.append([date, wea, lowtem, hightem, wind, level])def print_res(return_list): tplt = '{0:<10}\t{1:^10}\t{2:^10}\t{3:{6}^10}\t{4:{6}^10}\t{5:{6}^5}' result_list_wt.append(tplt.format('日期', '天气', '最低温', '最低温', '风向', '风力',chr(12288))+"\n") for i in return_list: result_list_wt.append(tplt.format(i[0], i[1],i[2],i[3],i[4],i[5],chr(12288))+"\n") def main(): # 城市-城市码txt files = open('city_list.txt',"r") city_name_id = files.readlines() try: # 获取txt-list for line in city_name_id: name_id = line.split('-')[1].replace("['","").replace("\n","") url = 'http://www.weather.com.cn/weather/'+name_id+'.shtml' city_name = line.split('-')[0].replace("['","").replace("\n","") city_china = "\n"+"城市名 : "+city_name+"\n" result_list_wt.append(city_china) html = get_page(url) wea_list = [] parse_page(html, wea_list) print_res(wea_list) files.close() except: print("error") # 将获取后果写入到文件内 msgs = ''.join(result_list_wt) print(msgs) with open('weather.China.txt',"w+") as file: file.write(msgs) if __name__ == '__main__': main()6.city_list.txt ...

June 2, 2021 · 1 min · jiezi

关于pyspider:python爬虫pyspider的第一个爬虫程序大功告成

对于pyspider的装置返回查看前序文章《踩坑记:终于怀着忐忑的情绪实现了对 python 爬虫扩大库 pyspider 的装置》 1、启动pyspider服务1pyspider all2、创立pyspider我的项目 3、我的项目区域阐明 4、从百度首页开始爬取填写百度首页地址点击run开始爬取,点击爬取到的链接执行下一步 任意点击爬取到的链接进入下一步爬取 返回所进入的详情页内容 5、代码编辑区函数 1#!/usr/bin/env python 2# -*- encoding: utf-8 -*- 3# Created on 2021-04-10 11:24:26 4# Project: test 5 6from pyspider.libs.base_handler import * 7 8# 解决类 9class Handler(BaseHandler):10 # 爬虫相干参数配置,全局失效(字典类型)11 crawl_config = {12 'url':'http://www.baidu.com'13 }1415 # 示意每天一次,minutes单位为分钟16 @every(minutes=24 * 60)17 # 程序入口18 def on_start(self):19 # 设置爬虫地址20 self.crawl('http://www.baidu.com', callback=self.index_page)2122 # 示意10天内不会再次爬取,age单位为秒23 @config(age=10 * 24 * 60 * 60)24 # 回调函数、数据解析25 def index_page(self, response):26 # response.doc() 返回的是pyquery对象,因而采纳pyquery对象解析27 for each in response.doc('a[href^="http"]').items():28 # 遍历并回调爬取详情页29 self.crawl(each.attr.href, callback=self.detail_page)3031 # 工作优先级设置32 @config(priority=2)33 # 回调函数、返回后果34 def detail_page(self, response):35 # 返回详情页36 return {37 "url": response.url,38 "title": response.doc('title').text(),39 }更多精彩返回微信公众号【Python 集中营】,专一于 python 技术栈,材料获取、交换社区、干货分享,期待你的退出~ ...

April 11, 2021 · 1 min · jiezi

关于python爬虫:踩坑记终于怀着忐忑的心情完成了对-python-爬虫扩展库-pyspider-的安装

在后面的系列文章中,笔者说了一些爬虫入门的相干知识点以及一些比拟根本的爬虫办法和简略的框架应用等。下一个环节我么一起来看看 pyspider 框架。首先,这款框架的装置就非常令人头疼,破费了好几个小时原本要和女朋友聊天的工夫,老王通过一直的踩坑终于装置胜利了,所以,特地记录一下。 1、pyspider介绍 一个国人编写的弱小的网络爬虫零碎并带有弱小的WebUI。 采纳Python语言编写,分布式架构,反对多种数据库后端,弱小的WebUI反对脚本编辑器,工作监视器,我的项目管理器以及后果查看器。 http://docs.pyspider.org/en/l... 2、根底装置环境介绍 操作系统:Windows10 python 环境:python3.6.8 操作人:老王的小跟班 3、筹备扩大库工具 1# 因为phantomjs官网下载太慢,能够到国内镜像站进行下载 2 3http://npm.taobao.org/dist/phantomjs/ 4 5phantomjs(版本=2.1.1,反对javascript操作) 6 7wheel(反对.whl文件装置) 8 9# pycurl-7.43.0.4-cp36-cp36m-win_amd64.whl下载地址1011https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycurl1213pycurl-7.43.0.4-cp36-cp36m-win_amd64.whl(装置pycurl扩大库)1415wsgidav(版本=2.4.1)1617werkzeug(版本=0.15) 4、开始装置 pyspider 1a.装置phantomjs 2 3# 下载好phantomjs之后,解压之后配置好环境变量 4 5b.装置wheel 6 7python -m pip install wheel 8 9c.装置下载好的pycurl扩大库1011python -m pip install c:/tools/pycurl-7.43.0.4-cp36-cp36m-win_amd64.whl1213d.装置wsgidav依赖库1415# 先卸载以后高版本1617python -m pip uninstall wsgidav1819# 装置指定低版本2021python -m pip install wsgidav=2.4.12223e.装置werkzeug2425# 先卸载以后高版本2627python -m pip uninstall werkzeug2829# 装置指定低版本3031python -m pip install werkzeug=0.153233f.最初装置pyspider3435python -m pip install pyspider5、启动问题 1a.间接启动 2 3pyspider all 4 5b.启动中如果呈现始终在 restarting的状况 6 7# 解决方法:关上一个终端,输出命令启动。再关上一个新的终端启动,此时再敞开第一个终端,第二个终端会启动胜利。 8 9# 为什么?我也不晓得,这是在 Google 上找的解决办法。1011c.第一次启动的工夫比拟长1213d.启动胜利之后拜访地址1415http://localhost:50001617e.启动之后敞开终端,代表pyspider服务也会敞开更多精彩返回微信公众号【Python 集中营】,专一于 python 技术栈,材料获取、交换社区、干货分享,期待你的退出~

April 10, 2021 · 1 min · jiezi

关于python爬虫:requestsBeautifulSoup页面爬取数据对比测试

本文首发于:行者AIQ:BeautifulSoup不是爬虫用的吗,为什么要应用它来做测试? A:在日常工作中会遇到很多数据比照的测试工作,在后端接口有做数据加密,或接口有做鉴权等状况下,咱们再从后端去取参数,消耗的工夫老本有点大。 所以我想...能不能走前端页面下来获取数据呢,网上查了下,果然有从前端页面上爬取数据的工具包,简略学习了下,也算是本人做个笔记记录下。明天咱们次要用到的是requests + BeautifulSoup 以及其余一些工具包来实现该性能。 1. 什么是BeautifulSoup?首先做个介绍,BeautifulSoup是python的一个库,最次要的性能是从网页抓取数据。 其官网解释如下: BeautifulSoup提供一些简略的、python式的函数用来实现导航、搜寻、批改分析树等性能。它是一个工具箱,通过解析文档为用户提供须要抓取的数据,因为简略,所以不须要多少代码就能够写出一个残缺的应用程序。BeautifulSoup主动将输出文档转换为Unicode编码,输入文档转换为utf-8编码。你不须要思考编码方式,除非文档没有指定一个编码方式,这时,BeautifulSoup就不能自动识别编码方式了。而后,你仅仅须要阐明一下原始编码方式就能够了。在理解了该工具包的作用后,咱们写几行代码来简略学习下,咱们就以此网站来做练习吧。 http://www.cntour.cn/ 2. 如何应用BeautifulSoup?2.1 应用该工具的话须要装置对应的环境依赖包,CMD执行以下命令:pip install beautifulsoup4pip install lxml图1. BeautifulSoup环境装置 2.2 在环境装置实现后,咱们来写个小例子用浏览器关上http://www.cntour.cn/ 图2. 待爬取页面信息展现 定位咱们想获取的数据信息,通过element查找该元素。 在复制元素的selector后,编写如下代码: from bs4 import BeautifulSoupimport requestsimport reurl = 'http://www.cntour.cn/'strhtml = requests.get(url)soup = BeautifulSoup(strhtml.text, 'lxml')data = soup.select('#main > div > div.mtop.firstMod.clearfix > div.centerBox > ul.newsList > li:nth-child(1) > a')print(data)通过BeautifulSoup咱们能够获取到html对象,应用lxml解析器后,打印data后可见如下信息: 图3. 获取标签信息 2.3 获取到html对象后,接下来咱们获取整组数据,用于便遍历获取该页面上的题目,连贯和ID从新获取html对象,将<li>标签后的nth-child(1)删除,再从新执行代码。 from bs4 import BeautifulSoupimport requestsimport reurl = 'http://www.cntour.cn/'strhtml = requests.get(url)soup = BeautifulSoup(strhtml.text, 'lxml')# data = soup.select('#main > div > div.mtop.firstMod.clearfix > div.centerBox > ul.newsList > li:nth-child(1) > a')# print(data)data = soup.select('#main > div > div.mtop.firstMod.clearfix > div.centerBox > ul.newsList > li > a')print(data)这样咱们就获取到了html页面,列表上所有的数据对象。 ...

March 30, 2021 · 1 min · jiezi

如何通过网络数据的获取做出这些数据分析项目

作者 | AlfredWu来源 | Alfred数据室最近有很多人在问,我是如何收集网络的数据,如何进行数据处理、数据分析以及可视化呈现的。 也有人问的更具体,关于Python数据分析的一些问题。到底应该怎么学?如何快速入门,以及技术和业务之间的瓶颈如何突破? 因为深度的数据分析往往可以看到事情的本质,而这又是一项在任何情况下都超级加分的技能。总结了一些经验,希望能够给还没入门、或者入门之后就遇到瓶颈的新手一些建议。主要是关于如何系统地进行学习规划,以及可以避免的一些坑。 有的同学看到数据分析几个字,就马上开始Python函数+控制语句、R语言和ggplot库……上来一顿骚操作,还没入门就放弃了。 这就是需求不明确导致的,当然学习方式也值得商榷,那到底数据分析需要什么样的技能呢? 这里作为例子,从招聘网站上找了几个数据分析的岗位,我们来看看具体的要求是怎样的。 其实企业对数据分析师的基础技能需求差别不大,可总结如下: 分析工具:一般要求SPSS/SAS/R/Python等分析工具至少会一种,会两种以上加分,有的企业因内部需求,会指定的一种;数据库:绝大会要求会SQL,部分要求SQL/NoSQL会一种,高级的分析师或者大型企业要求能够处理大数据,需要Hive(较少的需要Hadoop/Spark);统计学:若无相关专业背景,需要具备相应的统计学、概率论等基础知识;数据挖掘:少部分要求会建模,了解基本的算法模型,能够做数据预测,即便不要求,算法也是加分项;结果输出:Excel/PPT/Tableau。Excel和PPT要求的比较多,主要用作常规的数据呈现,与业务部门沟通等,Tableau一般作为可视化或者分析工具的加分项或者要求之一;业务/思维:对某个领域(如电商、金融等)相关业务的了解或具有产品、运营方向的分析经验,有自己的数据分析的方法论和项目经验,具备Data Sence。看上去很简单呀,对吧,但其实你把每个技能拆分开来,都是一个不小的知识体系。如果我们按照数据分析的流程来细分的话,每个部分应该掌握的技能,大概是这样的: 那对于这个技能体系,应该如何进行技能的训练呢?先后顺序是什么?哪些地方可能出现困难和瓶颈? 按数据分析的流程的顺序循序渐进,你会知道每个部分需要完成的目标是什么,需要学习哪些知识点,哪些知识是暂时不必要的。 接下来我们分别从每一个部分讲讲具体应该学什么、怎么学。 - ❶ - 数据获取:爬虫与公开数据 数据是产生价值的原材料,这也是数据分析项目的第一步。 通常我是通过爬虫获取相关数据的,一来数据有很高的时效性,二来数据的来源可以得到保证,毕竟网上的信息是异常丰富的。 这些分布在网上零散的信息,通过爬取整合之后,就有比较高的分析价值。 比如你可以通过爬虫获取招聘网站某一职位的招聘信息,爬取租房网站上某城市的租房信息,获取知乎点赞排行、网易云音乐评论排行列表。基于互联网爬取的数据,你可以对某个行业、某个事件、某类人群进行分析。 在爬虫之前需要先了解一些 Python 的基础知识:数据类型(列表、字典、元组等)、变量、循环、函数……… 以及,如何用 Python 库(urllib、BeautifulSoup、requests等)实现网页爬虫。如果是初学,建议从requests+xpath开始。 当然,并不是说公开数据就没用了,在进行分析的时候,需要一些历史数据进行对比,需要一定的行业标准进行参考的时候,公开数据的价值就体现出来了。 一些科研机构、企业、政府会开放一些数据,还有一些行业研究报告、他人的调查结果,都可以成为你的数据来源。这些数据集通常比较完善、质量相对较高。 - ❷ - 数据存取:SQL语言 我并不是每次都会用到数据库,但很多时候这确实是做数据分析项目的必备技能,包括求职就业,也是必选项。 通常数据库的使用能够让数据存储、管理更方便,同时也能提高数据提取和使用的效率,特别是在数据上了一定的量级之后,谁用谁知道。 大多数的企业,都会以SQL的形式来存储数据,如果你是一个分析师,也至少要懂得SQL的操作,能够查询、提取公司的数据。 SQL作为最经典的数据库工具,为海量数据的存储与管理提供可能,并且使数据的提取的效率大大提升。需要掌握以下技能: 提取特定情况下的数据:企业数据库里的数据一定是大而繁复的,你需要提取你需要的那一部分。比如你可以根据你的需要提取2017年所有的销售数据、提取今年销量最大的50件商品的数据、提取上海、广东地区用户的消费数据……,SQL可以通过简单的命令帮你完成这些工作。数据库的增、删、查、改:这些是数据库最基本的操作,但只要用简单的命令就能够实现,所以你只需要记住命令就好。数据的分组聚合、如何建立多个表之间的联系:这个部分是SQL的进阶操作,多个表之间的关联,在你处理多维度、多个数据集的时候非常有用,这也让你可以去处理更复杂的数据。SQL这部分比较简单,主要是掌握一些基本的语句。当然,还是建议找几个数据集来实际操作一下,哪怕是最基础的查询、提取等。 - ❸ - 数据处理:Pandas/Numpy 爬回来的数据通常是不干净的,数据的重复、缺失、异常值等等,这时候就需要进行数据的清洗,把这些影响分析的数据处理好,才能获得更加精确地分析结果。 那么我们需要用相应的方法去处理,比如重复数据,是保留还是删除;比如残缺数据,我们是直接去掉这条数据,还是用临近的值去补全,这些都是需要考虑的问题。 对于数据预处理,学会 pandas/Numpy (Python包)的用法,应对一般的数据清洗就完全没问题了。需要掌握的知识点如下: 选择:数据访问(标签、特定值、布尔索引等)缺失值处理:对缺失数据行进行删除或填充重复值处理:重复值的判断与删除异常值处理:清除不必要的空格和极端、异常数据相关操作:描述性统计、Apply、直方图等合并:符合各种逻辑关系的合并操作分组:数据划分、分别执行函数、数据重组Reshaping:快速生成数据透视表数据清洗通常被视为脏活,但事实上这步非常重要,这直接决定了你的分析结论的准确性,决定你的项目是否能顺利进行下去。 - ❹ - 数据分析与可视化 这个是从数据中发现信息、挖掘价值的过程,大多数的结论在这个步骤产生,主要做两件事情。 一是对于既定的数据分析主题进行拆解,评估需要从哪些维度进行分析,提取哪些数据,这个步骤很大程度上来源于经验或者对于具体事务的理解; 二是通过探索数据分布的规律、数据的特征,发现从表面看不到的信息,完成这个流程主要是通过数据本身进行探索。 前者对应的是描述性的数据分析,主要考虑数据的指标,看从不同的角度去描述数据能够得出哪些结论。 这个地方就需要对统计学的相关知识有一定的了解,比如: 基本统计量:均值、中位数、众数、百分位数、极值等其他描述性统计量:偏度、方差、标准差、显著性等其他统计知识:总体和样本、参数和统计量、ErrorBar概率分布与假设检验:各种分布、假设检验流程后者则是探索型的数据分析,主要通过绘制数据的分布图形,来观察数据的分布规律,从而提取隐藏的某些信息。 这里就需要对掌握可视化的技能,Python中的Matplotlib/Seaborn都可以完成可视化的工作。可视化既是探索性分析的工具,也可以输出最终结果呈现的图形。 ...

September 19, 2019 · 1 min · jiezi

Python定向爬虫模拟新浪微博登录

当我们试图从新浪微博抓取数据时,我们会发现网页上提示未登录,无法查看其他用户的信息。模拟登录是定向爬虫制作中一个必须克服的问题,只有这样才能爬取到更多的内容。 实现微博登录的方法有很多,一般我们在模拟登录时首选WAP版。 因为PC版网页源码中包括很多的js代码,提交的内容也更多,不适合机器模拟登录。 我们实现微博登录的大体思路是这样的: 用抓包工具把正常登录时要提交的字段都记录下来; 模拟提交这些字段; 判断是否登录成功; 原理很简单,让我们一步一步来实现吧。 一.抓包利器Fiddler 在电脑和互联网之间的通信是通过不同的数据包收发来实现的。 Fiddler可以从中间对数据进行拦截,拷贝一份数据以后再将数据发送给目的端。(这也是为什么说咖啡馆的公共WIFI不安全的原因) 同类的还有WireShark。为何这儿不用WireShark呢? Wireshark太过于专业了,它可以实现抓取各种包,抓下来的包也很乱,针对性没Fiddler那么强。 下载安装 1.下载地址:http://www.telerik.com/fiddler 2.安装方法:fiddler依赖.Net环境,如果已经有则无需配置,直接点击下一步就行。 使用方法 1.启动Fiddler 2.配置Fiddler 点击左上角的“ WinConfig”,找到你使用的浏览器并勾选,点击“Save Changes” 3.使用Fiddler开始抓包 打开浏览器访问WAP版新浪微博网站weibo.cn Fiddler窗口左侧找到weibo.cn /pub/的数据包,并双击,这时我们就能够在右侧看到抓取到的信息. 找到Cookies字段,这正是我们需要的. 二.Cookies与保持登录 关于Cookies 维基百科是这样解释的: Cookie(复数形态Cookies),中文名称为“小型文本文件”或“小甜饼”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。 通俗来说就是服务器端为了确认用户终端的身份而设定的一种加密标识,它是存储在本地终端上的。 当然,随着Cookies技术的发展,Cookies的作用已经不止于用户身份标识。 当登陆一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。 如果勾选了,那么下次访问同一个网站时,用户会发现没输入用户名和密码就已经登录了。 这正是因为前一次登陆时服务器发送了包含登录凭据(用户名+密码的某种加密形式)的Cookie到用户的硬盘上。 第二次登录时,如果该Cookies尚未到期,浏览器会发送该Cookies,服务器验证凭据,于是不必输入用户名和密码就让用户登录了。 三.Cookies模拟登录 下面将介绍使用 Fiddler 获取新浪微博 Cookies,然后使用 Requests 提交 Cookies 从而实现模拟登录。 抓取登录数据包 使用Fiddler抓取数据包. 获取Cookies 打开新浪微博WAP版页面(weibo.cn),点击登录,然后填写账号密码,勾选“记住登录状态”,切记要勾选此项. ...

July 13, 2019 · 2 min · jiezi

python学习教程python版大富翁游戏开发源代码分享

本文实例为大家分享了python版大富翁游戏的具体代码,供大家参考,具体内容如下 # -*- coding: utf-8 -*- '''在学习过程中有什么不懂得可以加我的python学习交流扣扣qun,934109170,群里有不错的学习教程、开发工具与电子书籍。与你分享python企业当下人才需求及怎么从零基础学习好python,和学习什么内容。''' # code by: 物网141 王璞劼Khalil# name: 理工大富翁beta2.0# describe: 基于python的一个2D大富翁游戏'''1.游戏地图为自己使用各种网络素材制作; 各种按钮和选项,小图标等也是使用PS制作。2.声音效果主要为背景音乐和几种游戏中音效;3.游戏设定了两个类:玩家和建筑 玩家的参数和方法都在代码中给出; 具体有:移动方法、位置判断方法、 购买房屋方法、添加小房子方法、 事件判断方法。4.玩家在大富翁的主要操作是投掷骰子,由随机函数 进行判定然后进行移动,进行位置判断,然后开始 进行相关的判定。5.游戏中的按键有:是、否、和结束回合; 每个按键由没按下与按下两种状态的图片组成, 这个设计花费了一定时间。 还有 开始游戏 和 扔骰子 的两个明暗按钮, 由pygame优化后的一个函数实现。6.玩家的位置与电脑重叠时会将双方的位置进行一定 偏移,防止进行覆盖,分不清自己的位置。7.游戏基础功能有移动,购买房子,在已经购买的房子下 搭建新的小房子增加过路费,被收费,判断胜负的基础 功能,此外还加入了幸运事件: 财神 - 免收费一次 衰神 - 双倍被收费一次 破坏神 - 直接破坏一个建筑 无论敌我 土地神 - 强占对面建筑 这四项功能在位置处于左上角和右下角的时候会被触发, 添加了很多游戏乐趣哦~~~ ^_^8.游戏基于python的一个模块pygame实现,给我提供了很 多快乐的时光,谢谢老师的阅览与郭宁同学的协助答辩 :)''' #####################准备工作################## # 初始化各种模块import pygameimport randomimport sys # 定义类class Player(): def __init__(self, image ,name , isPlayer): self.name = name self.money = 10000 self.isGoingToMove = False self.movable = True self.image = image self.position = 0 self.temp_position = False self.dice_value = 0 self.locatedBuilding = 0 self.showText = [] self.isPlayer = isPlayer self.ownedBuildings = [] self.isShowText = False self.soundPlayList = 0 self.caishen = 0 self.shuaishen = 0 self.tudishen = 0 self.pohuaishen = 0 def judgePosition(self,buildings): # 位置判断 返回值是所在位置的建筑 for each in buildings: for every in each.location: if self.position == every: return each # 当使用元组时 当元组中只有一个元素时 发现该元素不可迭代 # 出现错误 换成列表后解决 ''' try: for every in each.location: if self.position == every: print(each.name) except: if self.position == every: print(each.name) ''' def buyaBuilding(self,isPressYes): # 购买方法 if isPressYes and self.locatedBuilding.owner != self.name: self.locatedBuilding.owner = self.name self.locatedBuilding.wasBought = True self.ownedBuildings.append(self.locatedBuilding) self.money -= self.locatedBuilding.price self.showText = [self.name + '购买了' + self.locatedBuilding.name + '!'] self.soundPlayList = 1 return True else: return False def addaHouse(self,isPressYes): # 在建筑物上添加一个房子 try: if isPressYes and self.locatedBuilding.owner == self.name: self.locatedBuilding.builtRoom += 1 self.money -= self.locatedBuilding.payment self.showText = [self.name + '在' + self.locatedBuilding.name + '上!','盖了一座房子!',\ '有%d' % self.locatedBuilding.builtRoom + '个房子了!',\ "它的过路费是%d" % (self.locatedBuilding.payment * \ (self.locatedBuilding.builtRoom + 1)) ] self.soundPlayList = 2 return True else: return False except: pass def move(self,buildings,allplayers): # 移动方法 返回值是所在的建筑位置 self.dice_value = random.randint(1,6) self.position += self.dice_value if self.position >= 16: self.position -= 16 self.locatedBuilding = self.judgePosition(buildings) self.isShowText = True return self.eventInPosition(allplayers) def eventInPosition(self,allplayers): # 判断在建筑位置应该发生的事件 building = self.locatedBuilding if building.name != '空地': if self.locatedBuilding.wasBought == False: # 未购买的时候显示建筑的数据! if self.isPlayer == True: textLine0 = self.name +'扔出了' + '%d'% self.dice_value + '点!' textLine1 = self.name +'来到了' + building.name + '!' textLine2 = '购买价格:%d' % building.price textLine3 = '过路收费:%d' % building.payment textLine4 = '是否购买?' self.showText = [textLine0,textLine1,textLine2,textLine3,textLine4] return True else : self.addaHouse(not self.buyaBuilding(True)) # ----- 动画 ------- # ----- 是否购买 ------ elif building.owner == self.name: # 路过自己的房子开始加盖建筑! if self.pohuaishen == 1: textLine0 = self.name + '破坏神附体!' textLine1 = '摧毁了自己的房子!' building.owner = 'no' building.wasBought = False self.showText = [textLine0,textLine1] self.pohuaishen = 0 else: if self.isPlayer == True: textLine0 = self.name + '扔出了' + '%d'% self.dice_value + '点!' textLine1 = '来到了ta的'+ self.locatedBuilding.name +'!' textLine2 = '可以加盖小房子!' textLine3 = '加盖收费:%d' % building.payment textLine4 = '是否加盖?' self.showText = [textLine0,textLine1,textLine2,textLine3,textLine4] return True # ----- 动画------- else: self.addaHouse(True) else: for each in allplayers: # 被收费! if self.locatedBuilding.owner == each.name and each.name != self.name: if self.caishen == 1: textLine0 = self.name + '财神附体!' textLine1 = '免除过路费%d!' % (building.payment * (building.builtRoom + 1)) self.showText = [textLine0,textLine1] self.caishen = 0 else: if self.tudishen == 1: textLine0 = self.name + '土地神附体!' textLine1 = '强占土地!' textLine2 = building.name + '现在属于'+ self.name self.locatedBuilding.owner = self.name self.showText = [textLine0,textLine1,textLine2] self.tudishen = 0 else: if self.pohuaishen == 1: textLine0 = self.name + '破坏神附体!' textLine1 = '摧毁了对手的房子!' building.owner = 'no' building.wasBought = False self.showText = [textLine0,textLine1] self.pohuaishen = 0 else: textLine0 = self.name + '扔出了' + '%d'% self.dice_value + '点!' textLine1 = self.name+ '来到了'+ each.name+'的:' textLine2 = building.name + ',被收费!' if self.shuaishen == 1: textLine3 = '过路收费:%d*2!' % (building.payment * (building.builtRoom + 1)*2) self.shuaishen = 0 else: textLine3 = '过路收费:%d' % (building.payment * (building.builtRoom + 1)) textLine4 = '哦!'+ self.name +'好倒霉!' self.showText = [textLine0,textLine1,textLine2,textLine3,textLine4] # 收费! self.money -= building.payment * (building.builtRoom + 1) each.money += building.payment * (building.builtRoom + 1) self.soundPlayList = 3 # ----- 动画------- else: # 发现不能处理在空地上的情况 于是使用 try & except 来解决!然后加入了幸运事件功能! # 后来发现 try except 弊端太大 找不到错误的根源 换为if else嵌套。。 whichone = self.dice_value % 4 if whichone == 0: self.caishen = 1 textLine2 = '遇到了财神!' textLine3 = '免一次过路费!' if whichone == 1: self.shuaishen = 1 textLine2 = '遇到了衰神!' textLine3 = '过路费加倍一次!' if whichone == 2: self.tudishen = 1 textLine2 = '遇到了土地神!' textLine3 = '强占一次房子!' if whichone == 3: self.pohuaishen = 1 textLine3 = '摧毁路过的房子!' textLine2 = '遇到了破坏神!' textLine0 = self.name +'扔出了' +'%d'% self.dice_value + '点!' textLine1 = '来到了运气地点!' self.showText = [textLine0,textLine1,textLine2,textLine3] class Building(): # 好像所有功能都在Player类里实现了=_= def __init__(self,name,price,payment,location): self.name = name self.price = price self.payment = payment self.location = location self.wasBought = False # 是否被购买 self.builtRoom = 0 # 小房子建造的数目 self.owner = 'no' # 带透明度的绘图方法 by turtle 2333def blit_alpha(target,source,location,opacity): x = location[0] y = location[1] temp = pygame.Surface((source.get_width(),source.get_height())).convert() temp.blit(target , (-x , -y)) temp.blit(source,(0,0)) temp.set_alpha(opacity) target.blit(temp,location) ########################主函数######################### def main(): pygame.init() clock = pygame.time.Clock() # 初始化屏幕 size = (1270,768) screen = pygame.display.set_mode(size) pygame.display.set_caption("理工大大富翁 - made by 王璞劼") # 读取字体以及有关数据 textColorInMessageBox = (141,146,152) white = (255,255,255) black = (0,0,0) red = (255,0,0) font = pygame.font.Font('resource\\font\\myfont.ttf',30) # 读取资源 backgroud = pygame.image.load("resource\\pic\\GameMap.png") chess = pygame.image.load("resource\\pic\\chess.png") chess_com = pygame.image.load("resource\\pic\\chess1.png") bigdice_image = pygame.image.load("resource\\pic\\dice.png").convert_alpha() dice_1 = pygame.image.load("resource\\pic\\dice_1.png") dice_2 = pygame.image.load("resource\\pic\\dice_2.png") dice_3 = pygame.image.load("resource\\pic\\dice_3.png") dice_4 = pygame.image.load("resource\\pic\\dice_4.png") dice_5 = pygame.image.load("resource\\pic\\dice_5.png") dice_6 = pygame.image.load("resource\\pic\\dice_6.png") dices = [dice_1,dice_2,dice_3,dice_4,dice_5,dice_6] yes = pygame.image.load("resource\\pic\\yes.png") yes2 = pygame.image.load("resource\\pic\\yes2.png") no = pygame.image.load("resource\\pic\\no.png") no2 = pygame.image.load("resource\\pic\\no2.png") GameStart = pygame.image.load("resource\\pic\\GameStart.png") StartGameButton = pygame.image.load("resource\\pic\\StartGameButton.png").convert_alpha() turnover = pygame.image.load("resource\\pic\\turnover.png") turnover2 = pygame.image.load("resource\\pic\\turnover2.png") shuaishen = pygame.image.load("resource\\pic\\shuaishen.png").convert_alpha() tudishen = pygame.image.load("resource\\pic\\tudishen.png").convert_alpha() caishen = pygame.image.load("resource\\pic\\caishen.png").convert_alpha() pohuaishen = pygame.image.load("resource\\pic\\pohuaishen.png").convert_alpha() rollDiceSound = pygame.mixer.Sound("resource\\sound\\rolldicesound.wav") bgm = pygame.mixer.music.load("resource\\sound\\bgm.ogg") throwcoin = pygame.mixer.Sound("resource\\sound\\throwcoin.wav") moneysound = pygame.mixer.Sound("resource\\sound\\moneysound.wav") aiyo = pygame.mixer.Sound("resource\\sound\\aiyo.wav") didong = pygame.mixer.Sound("resource\\sound\\didong.wav") # PlayList 在对象中设置应该播放的声音 playList = [moneysound ,throwcoin ,aiyo] # 各种Surface的rect bigdice_rect = bigdice_image.get_rect() bigdice_rect.left , bigdice_rect.top = 50 , 600 yes_rect = yes.get_rect() yes_rect.left , yes_rect.top = 500,438 no_rect = no.get_rect() no_rect.left , no_rect.top = 630,438 button_rect = StartGameButton.get_rect() button_rect.left , button_rect.top = 1003,30 turnover_rect = turnover.get_rect() turnover_rect.left , turnover_rect.top = 1035,613 # 实例化对象 players = [] computers = [] allplayers = [] player_1 = Player(chess , '玩家' , True ) player_com1 = Player(chess_com , '电脑' , False ) players.append(player_1) computers.append(player_com1) allplayers.append(player_1) allplayers.append(player_com1) presentPlayer = player_com1 # 初始化建筑物数据 gate = Building('大门',1000,200,[1,2]) fountain = Building('喷泉',2000,400,[3,4]) path = Building('小道',800,160,[5]) library = Building('图书馆',2000,400,[6,7]) kongdi1 = Building('空地',0,0,[8]) classroomTen = Building('教十',1200,240,[9,10]) classroomNine = Building('教九',1200,240,[11,12]) resOne = Building('三餐厅',800,160,[13]) resTwo = Building('二餐厅',800,160,[14]) resThree = Building('一餐厅',800,160,[15]) kongdi2 = Building('空地',0,0,[0]) buildings = [gate,fountain,path,library,classroomNine,\ classroomTen,resOne,resThree,resTwo,kongdi1,kongdi2] # 坐标数据 同时处理坐标数据 使之合适 MapXYvalue = [(435.5,231.5),(509.5,231.5),(588.5,231.5),(675.5,231.5),(758.5,231.5),\ (758.5,317.0),(758.5,405.5),(758.5,484.5),(758.5,558.5),(679.5,558.5),\ (601.5,558.5),(518.5,556.5),(435.5,556.5),(435.5,479.5),(435.5,399.0),\ (435.5,315.5) ] MapChessPosition_Player = [] MapChessPosition_Com = [] MapChessPosition_Original = [] MapChessPosition_Payment = [] MapMessageBoxPosition = (474.1 , 276.9) YesNoMessageBoxPosition = [(500,438) , (630,438)] StartGameButtonPosition = (1003,30) TurnOvwrButtonPosition = (1035,613) # 调整位置 for i in range(0,16): MapChessPosition_Original.append((MapXYvalue[i][0]-50,MapXYvalue[i][1]-80)) MapChessPosition_Player.append((MapXYvalue[i][0]-70,MapXYvalue[i][1]-60)) MapChessPosition_Com.append((MapXYvalue[i][0]-30,MapXYvalue[i][1]-100)) MapChessPosition_Payment.append((MapXYvalue[i][0]-30,MapXYvalue[i][1]-15)) # 循环时所用的一些变量 running = True image_alpha = 255 button_alpha = 255 half_alpha = 30 showdice = True showYes2 = False showNo2 = False showYes_No = False pressYes = False whetherYes_NoJudge = False gameStarted = False showButton2 = False # 播放背景音乐 pygame.mixer.music.play(100) #################进入游戏循环!######################## # 循环开始! while running: if not gameStarted: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 明暗触发 鼠标位置判断 if event.type == pygame.MOUSEMOTION: if button_rect.collidepoint(event.pos): button_alpha = 255 else: button_alpha = 120 if event.type == pygame.MOUSEBUTTONDOWN: if button_rect.collidepoint(event.pos): # 按下按钮 didong.play() gameStarted = True screen.blit(GameStart , (0,0)) blit_alpha(screen, StartGameButton, StartGameButtonPosition, button_alpha) if gameStarted: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 明暗触发 鼠标位置判断 if event.type == pygame.MOUSEMOTION: if bigdice_rect.collidepoint(event.pos): image_alpha = 255 else: image_alpha = 190 if event.type == pygame.MOUSEBUTTONDOWN: if bigdice_rect.collidepoint(event.pos): # 按骰子 if presentPlayer != player_1: rollDiceSound.play(1, 2000) pygame.time.delay(2000) showYes_No = player_1.move(buildings,allplayers) whetherYes_NoJudge = showYes_No presentPlayer = player_1 else: presentPlayer.showText = ['还没到你的回合!'] if turnover_rect.collidepoint(event.pos): # 按回合结束 showButton2 = True if presentPlayer != player_com1: showYes_No = player_com1.move(buildings,allplayers) presentPlayer = player_com1 else: presentPlayer.showText = ['还没到你的回合!'] else: showButton2 = False # 不显示Yes_No的时候不能点击它们! if whetherYes_NoJudge == True: if yes_rect.collidepoint(event.pos): # 按是否 showYes2 = True if no_rect.collidepoint(event.pos): # 按是否 showNo2 = True if event.type == pygame.MOUSEBUTTONUP: if turnover_rect.collidepoint(event.pos): # 按回合结束 showButton2 = False if yes_rect.collidepoint(event.pos): # 按是否 showYes2 = False showYes_No = False # 只有在可以判定的时候才能算按下了是 同时将判断条件置为空 if whetherYes_NoJudge == True: pressYes = True whetherYes_NoJudge = False if no_rect.collidepoint(event.pos): # 按是否 showNo2 = False pressYes = False showYes_No = False whetherYes_NoJudge = False # 测试事件选项 if event.type == pygame.KEYDOWN: if event.key == pygame.K_w: showYes_No = player_1.move(buildings,allplayers) whetherYes_NoJudge = showYes_No presentPlayer = player_1 if event.key == pygame.K_q: showYes_No = player_com1.move(buildings,allplayers) presentPlayer = player_com1 '''for each in allplayers: if each.isGoingToMove == True and each.movable == True : showYes_No = each.move(buildings,allplayers) each.movable = False each.isGoingToMove = False''' ''' allisready = True for each in allplayers: if each.movable == True: allisready = False if allisready: for each in allplayers: each.movable = True ''' # 购买房屋!!!!!!!! if presentPlayer.buyaBuilding(pressYes) == True: pressYes = False if presentPlayer.addaHouse(pressYes) == True: pressYes = False ######################################################################### screen.blit( backgroud , (0,0) ) blit_alpha(screen, bigdice_image, (50, 600), image_alpha) textPosition = [MapMessageBoxPosition[0],MapMessageBoxPosition[1]] # 打印信息 for each in presentPlayer.showText: text = font.render(each, True, white, textColorInMessageBox) screen.blit(text,textPosition) textPosition[1] += 30 # 播放行动声音 if presentPlayer.soundPlayList != 0: playList[presentPlayer.soundPlayList - 1].play() presentPlayer.soundPlayList = 0 # 在位置上显示过路费 for i in range(1,8): for each in buildings: for every in each.location: if i == every: if each.owner == presentPlayer.name: text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, red) elif each.owner == 'no': text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, white) elif each.owner != presentPlayer.name and each.owner != 'no': text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, black) screen.blit(text,MapChessPosition_Payment[i]) for i in range(9,16): for each in buildings: for every in each.location: if i == every: if each.owner == presentPlayer.name: text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, red) elif each.owner == 'no': text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, white) elif each.owner != presentPlayer.name and each.owner != 'no': text = font.render('%d' % (each.payment * (each.builtRoom + 1))\ , True, black) screen.blit(text,MapChessPosition_Payment[i]) # 打印金钱数和幸运状态 money_1 = font.render(player_1.name +'金钱:%d' % player_1.money, True, black, white) screen.blit(money_1,(0,0)) if player_1.pohuaishen == True: screen.blit(pohuaishen,(0,30)) else: blit_alpha(screen, pohuaishen, (0, 30), half_alpha) if player_1.caishen == True: screen.blit(caishen,(55,30)) else: blit_alpha(screen, caishen, (55, 30), half_alpha) if player_1.shuaishen == True: screen.blit(shuaishen,(110,30)) else: blit_alpha(screen, shuaishen, (110, 30), half_alpha) if player_1.tudishen == True: screen.blit(tudishen,(165,30)) else: blit_alpha(screen, tudishen, (165, 30), half_alpha) money_2 = font.render(player_com1.name +'金钱:%d' % player_com1.money, True, black, white) screen.blit(money_2,(1000,0)) if player_com1.pohuaishen == True: screen.blit(pohuaishen,(1000,30)) else: blit_alpha(screen, pohuaishen, (1000, 30), half_alpha) if player_com1.caishen == True: screen.blit(caishen,(1055,30)) else: blit_alpha(screen, caishen, (1055, 30), half_alpha) if player_com1.shuaishen == True: screen.blit(shuaishen,(1110,30)) else: blit_alpha(screen, shuaishen, (1110, 30), half_alpha) if player_com1.tudishen == True: screen.blit(tudishen,(1165,30)) else: blit_alpha(screen, tudishen, (1165, 30), half_alpha) # 放置扔出来的骰子 if player_1.dice_value != 0 and showdice: screen.blit(dices[player_1.dice_value - 1],(70,450)) # 放置回合结束按钮 if showButton2: screen.blit(turnover2,TurnOvwrButtonPosition) else: screen.blit(turnover,TurnOvwrButtonPosition) # 放置是否按钮 if showYes_No == True: screen.blit(yes , YesNoMessageBoxPosition[0]) screen.blit(no , YesNoMessageBoxPosition[1]) if showYes2 == True: screen.blit(yes2 , YesNoMessageBoxPosition[0]) if showNo2 == True: screen.blit(no2 , YesNoMessageBoxPosition[1]) # 放置玩家与电脑的位置 如果重合则挪位 for each in players: for every in computers: if each.position == every.position: screen.blit(each.image,MapChessPosition_Player[each.position]) screen.blit(every.image,MapChessPosition_Com[every.position]) each.temp_position = True every.temp_position = True for each in players: if each.temp_position == False: screen.blit(each.image,MapChessPosition_Original[each.position]) each.temp_position = True each.temp_position = not each.temp_position for every in computers: if every.temp_position == False: screen.blit(every.image,MapChessPosition_Original[every.position]) every.temp_position = True every.temp_position = not every.temp_position # 输赢判断 for each in allplayers: if each.money <= 0: font = pygame.font.Font('resource\\font\\myfont.ttf',200) loseText = font.render(each.name +'输了!', True, red) screen.fill(black) screen.blit(loseText,(100,100)) font = pygame.font.Font('resource\\font\\myfont.ttf',30) pygame.time.delay(3000) # 画面运行 pygame.display.flip() clock.tick(60) # 刷新率 # 双击打开运行 if __name__ == "__main__": main()因为目前python非常火,应用非常的广泛,是目前最火的行业之一,竞争很大,工资很高,未来发展也极好。加油加油! ...

June 30, 2019 · 9 min · jiezi

pythonrequests爬取知乎个人信息数据

效果预览地址:http://23.105.208.123/ 技术栈python3requestsredisechart源码地址https://github.com/MasakiOvO/... python需要安装的库requests,BeautifulSoup,redis,django 思路两个程序。 一个程序负责爬取用户关注和粉丝列表, 并把用户名存入set另一个程序负责根据用户名获取详细信息,存入hash维护 两个列表 1.已爬用户 2.未爬用户第一个程序的流程: 当未爬set不为空时:执行如下操作:每次从未爬取列表中取出一个用户名 根据用户名,获取他的关注与粉丝并遍历,如果用户既没在已爬用户,也没在未爬用户 加入未爬用户列表。第二个程序的流程 每次从未爬set中取出一个用户名,调用接口获取详细信息并存入redis hash中接口获取打开某个人的个人主页,按F12 选择XHR 然后点击图1的关注我的人,和我关注的人,在图2就可以看到header和cookie。 获取用户列表Api: https://www.zhihu.com/api/v4/...{username}/{type}?include=data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics&offset=20&limit=20username 是用户名, type 是类型, 有两种可选 [followers,followees], followers是粉丝 followees是关注改变offset的值可以获取分页 获取个人信息Api: https://www.zhihu.com/people/...user_token是用户名这个api中 返回的是html页面,在html页面中有一个scirpt标签里面的内容是json格式的用户信息,这就很方便了,直接获取键值对 对应的属性就ok。 发送请求F12查看接口,把header和cookie放进requests.get()方法中。 剩下的就很简单了,不赘述了。 总结还有很多优化的地方。比如加入中间件,来提升爬虫的稳定性。对数据进行分类,统计城市分布。

June 27, 2019 · 1 min · jiezi

3web爬虫scrapy模块介绍与使用

【百度云搜索,搜各种资料:http://bdy.lqkweb.com】【搜网盘,搜各种资料:http://www.swpan.cn】Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中。其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。 Scrapy 使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下 Scrapy主要包括了以下组件: 引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心)调度器(Scheduler)用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址下载器(Downloader)用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)爬虫(Spiders)爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面项目管道(Pipeline)负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。下载器中间件(Downloader Middlewares)位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。爬虫中间件(Spider Middlewares)介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。调度中间件(Scheduler Middewares)介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。Scrapy运行流程大概如下: 引擎从调度器中取出一个链接(URL)用于接下来的抓取引擎把URL封装成一个请求(Request)传给下载器下载器把资源下载下来,并封装成应答包(Response)爬虫解析Response解析出实体(Item),则交给实体管道进行进一步的处理解析出的是链接(URL),则把URL交给调度器等待抓取创建Scrapy框架项目 Scrapy框架项目是有python安装目录里的Scripts文件夹里scrapy.exe文件创建的,所以python安装目录下的Scripts文件夹要配置到系统环境变量里,才能运行命令生成项目 创建项目 首先运行cmd终端,然后cd 进入要创建项目的目录,如:cd H:py14 进入要创建项目的目录后执行命令 scrapy startproject 项目名称 scrapy startproject pach1项目创建成功 项目说明 目录结构如下: ├── firstCrawler │   ├── __init__.py │   ├── items.py │   ├── middlewares.py │   ├── pipelines.py │   ├── settings.py │   └── spiders │       └── __init__.py ...

June 12, 2019 · 1 min · jiezi

学python是自学好还是去培训机构这个问题应该这样分析

因为目前python非常火,应用非常的广泛,是目前最火的行业之一,竞争很大,工资很高,未来发展也极好。我个人建议:如条件还可以,负担不是那么大,可以选择培训,培训一定会比你自学的好,如果培训都学好,自学肯定更难。目前python的培训费用都是2W+,这还只是培训费而已,加上一些其他的东西,四个月时间要小三万吧!所以建议选择线上培训,成本低,可以反复学。 如果条件不允许,选择自学,自学肯定会难,但是只要你决心够用,自学也可以找到工作,但是从比例来看会很低,其实无论在哪里学习都是一样的,重在内心怎么看到你学python这个事情。 个人经历:我学python不是培训的,最开始也是从大一开始自学的,那个时候对做web方面比较有兴趣,所以我还是比较相信兴趣是最好的老师这句话的。那个时候在网上找了一些视频教程学着也是非常痛苦,自己也看了一些书,但是作用都不是很大。所以我在这里不建议大家初学python去看书,还是建议当你学完了一部分之后,你在看书温习,这样的效果是我实践出来的,仅代表个人建议。直接完全看书学的后果可能是看了之后能看懂,但是自己动手,啥都不会。 教程视频不在于多,越多越是不看也是我个人总结出来的,我还是很少见到自己完全看视频能自学python的,尤其现在框架越来越难,光看视频还是比较难学python的,很多代码上的东西如果没有人告诉你,可能你连空行都不会,代码写的一团糟,最基本的达不到,更不要说找到工作了。 两个抉择: 一.如果你选择培训建议如下: 我们这个行业别的要求不高,就是做项目的能力,到了公司是否可以干活,能干活完成任务怎么样都可以。但是目前培训的市场学费都在两万以上,加上四个月的吃住行,至少也要三万块钱,这笔费用挺多的,最重要的还是时间问题,我学完编程就学了四年,怎么可能用四个月时间学的很好,除非很聪明的人,我个人觉得目前学python想要找工作,至少要学习个半年的时间,身边也有不少在培训的时候发生的一些事情,当然有好的结果,也有很多不好的结果,不做评价,如果想去培训的朋友,建议慎重选择。 二.如果你选择自学建议如下 1.了解如今的市场行情,就是企业需要什么样的人才,这点很重要。 2.有一套系统的学习方案,学习不是瞎学的,是有节奏感的,每天看多少视频,不是说看完了就完了,在很多人的实践中,看完视频一点用没有用。一天用多少时间学python,自己规划好,每天做什么案例都是非常重要的。3.合理的学习路线,规划好每天的学习。 4.有人指点,很多问题是我们自己不可能解决的,除非那个是天才,可能一个小问题,我们一天都想不明白,但是别人的一句话可能就懂了,这个就是经验。

May 29, 2019 · 1 min · jiezi

Python爬虫教程爬取付费电影告别费钱的日子

今天小编再发一篇爬取电影的文章。不是小编懒,是小编真的不知道写什么了,见谅。如果小编Get到新的技能,一定发。 是不是有好多的小伙伴跟好久好久以前的小编一样,看一个电影充个会员,这个没关系,最主要的是,充一个平台的VIP还不行得有好几个才可以。 这么贫穷的小编,当然只能看6分钟的视频了,不过没关系,小编现在有python。 不会小伙伴此刻的心情是:(如同所示) 不过没关系,小编接下来就是授教大家一些Python神技(零基础的也是可以操作的奥)让咱们首先来看看实现效果吧 把你想要看的VIP电影地址复制粘贴到上面用Python做好的数据转换工具,就可以实现在线免费观看电影了。 一般来说各大平台的VIP电影只能观看6分钟→_→ (四不四很伤 ): 按照小编的授教之后呢大家看下实现效果之后: 实现效果之后: 爱奇艺: 实现之后: 不是很吃惊?是不是感到“亮瞎了”哈哈哈 ~ 这就是Python的独特的魅力,并且像你知道的 前沿科技 技术:爬虫工程、自动化运维、数据挖掘、人工智能、游戏开发、web开发、数据分析、自动化测试、大数据技术、区块链技术……等 都是需要python的! 好啦 好啦,用一句经典的话总结:“向代码致敬”! 最后:若是小伙伴还没有安装PyCharm工具的以及没有搭建Python环境的,可以告诉下小编,帮大家哈!

May 29, 2019 · 1 min · jiezi

xpath匹配标签下面所有内容文字

在我们利用xpath匹配页面标签时,经常会遇到标签下面还包含标签,但是我们只想取下面的所有文字例如相匹配图中 div[@class='display-content']下面所有P的文字,此时我们可以利用这个方法 直接上代码 # 取正文def get_details(url): payload = "" headers = { 'Accept': "*/*", 'Accept-Encoding': "gzip, deflate", 'Accept-Language': "zh-CN,zh;q=0.9,en;q=0.8", 'Cache-Control': "no-cache", 'Connection': "keep-alive", 'Cookie': "SUV=1811281936496730; gidinf=x099980109ee0edb269b528280008252b495807e917b; _muid_=1548315571095387; IPLOC=CN4403; reqtype=pc; t=1557797597640; MTV_SRC=10010001", 'Host': "v2.sohu.com", 'Origin': "http://m.sohu.com", 'Pragma': "no-cache", 'Referer': "http://m.sohu.com/ch/8/?_f=m-index_important_hsdh&spm=smwp.home.nav-ch.1.1557825265945dy1ukUW", 'User-Agent': "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Mobile Safari/537.36", 'Postman-Token': "46314343-d211-4b4e-8d84-2b20462a5f54" } response = requests.request("GET", url, data=payload, headers=headers) text = etree.HTML(response.text) tt = text.xpath("//div[@class='display-content']") # print(tt) info = tt[0].xpath("string(.)") return info返回结果如图 ...

May 14, 2019 · 1 min · jiezi

爬虫平台Crawlab-v02发布

Crawlab是一个专注于爬虫的集成了爬虫管理、任务调度、任务监控、数据分析等模块的分布式爬虫管理平台,非常适合对爬虫管理、爬虫工程化有要求的开发者及企业。对Crawlab还不了解的童鞋,请移步之前的文章: 分布式通用爬虫管理平台Crawlab手把手教你如何用Crawlab构建技术文章聚合平台(一)手把手教你如何用Crawlab构建技术文章聚合平台(二)Crawlab的任务调度核心模块是基于Celery的,因此天然支持分布式爬虫、多节点抓取。Crawlab虽然是用python写的,但爬虫不局限于python爬虫,理论上可兼容任何语言以及任何框架。从目前开源的框架来看,大部分爬虫平台是以scrapyd为核心,因此只能支持scrapy框架的爬虫,而Crawlab不仅支持scrapy,还支持其他框架的爬虫。 更新一览v0.2 已完成[x] 基础统计[x] 数据分析(爬虫)[x] 网站信息[x] 定时任务[x] 修复bug待开发[ ] 用户管理[ ] 上传爬虫[ ] 导出数据[ ] 高级数据分析(网站、任务)[ ] 更多爬虫例子[ ] 文件管理截屏基础统计(爬虫) 基础统计(任务) 定时任务 网站信息 __Github__: tikazyq/crawlab 如果感觉Crawlab还不错的话,请加作者微信拉入开发交流群,大家一起交流关于Crawlab的使用和开发。

May 10, 2019 · 1 min · jiezi

http代理ip选择的重点

作为一个首先发展起来的代理ip,http代理ip在网络上的应用是最多的,针对其提供的代理ip服务也是很多的,但是这也为用户选择http代理ip服务增加了难度,如果不是对http代理ip服务非常熟悉和了解的人,是很难轻易找寻到一个可靠的http代理ip服务的。 对于用户来说,选择http代理ip之前,去了解想要选择的代理商是很重要的,而这是完全可以在网络上找寻到答案的。许多http代理ip使用用户在使用以后,都会对其作出评价,这些评价都是客观真实的,可以帮助初次使用的用户来作出选择。 作为一家优质代理ip的服务厂家,我们为用户提供的http代理ip都是稳定,高质量的。在使用代理的客户对其评价也非常高,在搜寻代理商排名的时候,亿牛云也是遥遥领先的,因此选择亿牛云代理,就是选择了靠谱,选择了稳定,选择了高效的完成任务。

April 24, 2019 · 1 min · jiezi

对编程零概念如何接触学习python

Python 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum 于1989年底发明,第一个公开发行版发行于1991年,Python 源代码同样遵循GPL(GNU General Public License)协议。Python 语法简洁而清晰,具有丰富和强大的类库。 对编程零概念,如何接触学习python?我们通常称 Python 为胶水语言,他能够轻松的把其他语言编写的模块联结在一起(特别是C/C++),正式因为 Python 有着简洁优雅,开发效率高的优点,它被广泛应用于网站开发,网络编程,图形处理,科学计算,机器学习,网络爬虫等等。Python学习关注,但是也是因为 Python 的用处太过于广泛,这就导致了很多的小白并不能明确自己的学习方向导致自己学的很杂乱,造成了技能范围广但是并没有什么高度的情况,所以我们要明确自己的学习方向,我们归纳了一下,学习Python可以做以下几个方向的工作:如果你想要学好Python可以加入一个组织,这样大家学习的话就比较方便,还能够共同交流和分享资料,给你推荐一个学习的组织学习有可学习有困难或者想获取Python资料请加Python学习Q群629440 234,互相学习,互相分享学习资料 对编程零概念,如何接触学习python?在不同方向上,有不同的技能需求。选择自己最爱的方向学,才能早日跳坑。我们就给大家说一下后端开发方向的学习路线,按我整理的路线勤奋学习,相信你不日就会拥有 Python 后端开发的能力。 对编程零概念,如何接触学习python?值得庆幸的是,专门介绍软件,工具及网站服务的技术Blog上CarlCheo绘制了一张图表,告诉你该怎么开始伟大的码农航道。 对编程零概念,如何接触学习python?第一阶段:Python入门 数据类型 流程控制 常用模块 函数、迭代器、装饰器 递归、迭代、反射 面向对象编程 更高级的技能就不说了,最起码这几个你必须得烂熟于心。 这一阶段在我看来没什么难度, 不过面向对象编程的思想需要仔细体会。 第二阶段:WEB前端基础 学习一点前端的内容,既然我们要从事 Web方 向的开发,那么 Web 开发肯定是离不开前端页面的,虽然说企业都有专职的前端工程师,但是我们要求后端工程师也需要具备一定的前端知识,这对提升你的综合竞争力有很大的帮助,而且 HTML 相较于 Python 要简单一些,有助于树立你的学习信心,如果一开始就被难到了,那相信你的学习热情马上就会被浇灭的。 Html/CSS 基础 Dom 编程 原生 JS 学习 JQuery、EasyUi、AngulaJS Ajax 异步加载 Highchart 画图 Bootstrap 第三阶段:网络编程 Socket C/S编程、Twisted 异步网络框架 多线程、多进程、携程 gevent 、selectpollepoll FTP 服务器开发 批量命令、文件分布工具 RabbitMQ 消息队列、SqlAlchemy ORM ...

April 24, 2019 · 1 min · jiezi

记一次还可以抢救一下的爬虫私活,求接盘!

前言最近接了一个爬虫的私活,收益颇丰。自认为对爬虫掌握的还算不错,爬过很多国内外网站,数据超过百万,应对过封IP、设验证码、假数据、强制登录等反爬虫手段。于是乎,我毫不犹豫的接下了该活。但是进行了一半,我遇到了困难,写这篇文章希望能够找到感兴趣的朋友一起解决,一起分享劳动成果。如果到期没有解决的话,就当一次经历记录一下也罢。项目需求一个类似百度文库的网站,要求给出url,获得文章,以Word形式保存下来。保持格式不变。我的进展和思路我以前爬数据都是以文本的形式获得数据,然后清洗,保存数据库。但是这次需要保存到word,这不难,难在要求格式不变。我打算根据元素的css属性,设置在word里面的格式。获取文本首先我使用我最熟悉的python+selenium+chrome组合,无头模式启动不用打开浏览器比较方便def open_brower_headless(): chromeOptions = webdriver.ChromeOptions() chromeOptions.add_argument(“headless”) browser = webdriver.Chrome(chrome_options=chromeOptions) return browser文章部分是一个iframe框,通过selenium的switch_to_frame()方法切换到iframe元素,然后就是一系列的定位取值操作,很容易的取到了文章的文本。文章都是以许多<p>标签组合在一起的。通过绝对定位控制格式。(爬虫手法详情https://segmentfault.com/a/11…)我利用selenium的value_of_css_property()方法可以获得元素的属性(font-family、top、font-size),这个方法比较强,不仅可以获得行内样式的css,还可以获得外嵌式的css,所以我不用担心它的样式写在css文件里。这样每一行的格式我就得到了。1. 怎么换行?对比该元素和上一个元素的top属性的值,如果不一样就换行,高度不一样必定不在一行,很合理。2. 文字大小?元素的font-size的大小换算公式 ($/14 +0.5),差不多匹配docx里面的run.font.size的值docx写入wordpython库里面操作word使用的是docx,docx对word 的读写有一套完整的方法。比如:添加文字,设置字体,颜色,大小,段落,表格,添加图片。docx的使用也非常简单,主要分为三级:file >paragraph >run,下面简单介绍一下:file = docx.Document() #新建文件f = file.add_paragraph(“添加段落”) #添加段落run = f.add_run(“追加文字”) #追加文字run.font.color.rgb = RGBColor(0,0,1) #设置字体颜色run.font.size = Pt(36) #设置字体大小run.font.name = “宋体” #设置字体run._element.rPr.rFonts.set(qn(‘w:eastAsia’), ‘宋体’)run.add_break() #换行file.save(“d.docx”) #保存文件至今进度如此我完成了一个简单word的爬取和保存。瓶颈但是我遇到了更复杂的问题,就是表格。F12后发现表格的边框就是一个图片! 至此我不知道怎么进行下去了。开始我以为识别图片后我可以利用doxc 插入表格,根据文字的位置,插入在对应的表格里,但是我发现有的文章还有其他图片。所以我不能遇到图片就将下面的文字按照表格里面的文字处理。其他办法发现这条路似乎走不通后,我试了其他办法,就是pandoc,这是一个文档转化工具,windows下安装后通过输入命令来转化文档。比如将a.html转化为b.docxpandoc -s a.html -o b.docx但是得到得word 格式还没有我上面程序写的好,应该是我不太会用,网上对pandoc评价很高,几乎神器。我尝试将html先转化为pdf,然后再转word.但是失败了,需要安装pdf 引擎,而且需要配中文之类的,总之我没有成功,不知道转化成pdf后再转化word 它能否识别并插入表格。而不是背景图。知情人请告知,感激不尽。我发现文章结构的class名和百度文库里的一样,这是通过百度富文本编辑器编辑的吧?,如果是这样通过这个富文本编辑器反编辑一下是否可行?后面的话距离项目测试版交期还有3天,搞不定这个问题话就黄了,如果有朋友能够解决或者有思路的话可以一起完成,报酬四位数。一起吃鸡,真不舍得放弃!

April 18, 2019 · 1 min · jiezi

代理IP延迟高主要由以下原因导致

客户端网络不佳;要访问的目标网站不稳定/离代理服务器较远,比如跨国;代理IP服务器网络环境不佳,比如不是 BGP 链路,无法同时为电信/联通用户提供稳定的速度;代理IP服务器使用的人数较多;代理IP服务器硬件性能差;亿牛云代理是国内高质量代理IP提供商,基于Linux系统研发的平台,自营线路,电信机房宽带,私密家庭IP。高匿名私密代理IP节点分布全国。专业的运维团队,强大的技术研发,保证了代理服务器的稳定及速度,有这样优秀的代理商提供的代理,肯定会让客户使用的得心应手。www.16yun.cn

April 10, 2019 · 1 min · jiezi

爬虫过程中加上这些策略让你采集效率更高

我们都知道在采集数据过程中,尤其是爬取大量数据的时候,很多网站都有反爬虫措施,封ip是很严重的,,让你在采集的时候很心烦。本文就如何解决这个问题总结出一些应对措施,这些措施可以单独使用,也可以同时使用,效果更好。一 、伪造User-Agent 在请求头中把User-Agent设置成浏览器中的User-Agent,来伪造浏览器访问。比如:headers = {‘User-Agent’:‘Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36’}resp = requests.get(url,headers = headers)在每次重复爬取之间设置一个随机时间间隔比如:time.sleep(random.randint(0,3)) # 暂停03秒的整数秒,时间区间:[0,3]或:time.sleep(random.random()) # 暂停01秒,时间区间:[0,1)而且最主要的是ua要越多越好,不要固定的使用那几个,要经常更换最新真实的ua。二、伪造cookies若从浏览器中可以正常访问一个页面,则可以将浏览器中的cookies复制过来使用,比如:cookies = dict(uuid=‘b18f0e70-8705-470d-bc4b-09a8da617e15’,UM_distinctid=‘15d188be71d50-013c49b12ec14a-3f73035d-100200-15d188be71ffd’)resp = requests.get(url,cookies = cookies)把浏览器的cookies字符串转成字典def cookies2dict(cookies):items = cookies.split(’;’)d = {}for item in items: kv = item.split(’=’,1) k = kv[0] v = kv[1] d[k] = vreturn d注:用浏览器cookies发起请求后,如果请求频率过于频繁仍会被封IP,这时可以在浏览器上进行相应的手工验证(比如点击验证图片等),然后就可以继续正常使用该cookies发起请求。三、使用代理可以换着用多个代理IP来进行访问,防止同一个IP发起过多请求而被封IP,比如: # 要访问的目标页面 targetUrl = “http://httpbin.org/ip” # 要访问的目标HTTPS页面 # targetUrl = “https://httpbin.org/ip” # 代理服务器 proxyHost = “t.16yun.cn” proxyPort = “31111” # 代理隧道验证信息 proxyUser = “username” proxyPass = “password” proxyMeta = “http://%(user)s:%(pass)s@%(host)s:%(port)s” % { “host” : proxyHost, “port” : proxyPort, “user” : proxyUser, “pass” : proxyPass, } # 设置 http和https访问都是用HTTP代理 proxies = { “http” : proxyMeta, “https” : proxyMeta, }(这里是用的亿牛云的动态转发代理进行示例)不管我们采集什么网站的数据,光有代理是不行的,要配合多种反爬策略一起才能更高效的获取大量的数据。 ...

April 4, 2019 · 1 min · jiezi

如何实现一个Python爬虫框架

这篇文章的题目有点大,但这并不是说我自觉对Python爬虫这块有多大见解,我只不过是想将自己的一些经验付诸于笔,对于如何写一个爬虫框架,我想一步一步地结合具体代码来讲述如何从零开始编写一个自己的爬虫框架2018年到如今,我花精力比较多的一个开源项目算是Ruia了,这是一个基于Python3.6+的异步爬虫框架,当时也获得一些推荐,比如Github Trending Python语言榜单第二,目前Ruia还在开发中,Star数目不过700+,如果各位有兴趣,欢迎一起开发,来波star我也不会拒绝哈什么是爬虫框架说这个之前,得先说说什么是框架:是实现业界标准的组件规范:比如众所周知的MVC开发规范提供规范所要求之基础功能的软件产品:比如Django框架就是MVC的开发框架,但它还提供了其他基础功能帮助我们快速开发,比如中间件、认证系统等框架的关注点在于规范二字,好,我们要写的Python爬虫框架规范是什么?很简单,爬虫框架就是对爬虫流程规范的实现,不清楚的朋友可以看上一篇文章谈谈对Python爬虫的理解,下面总结一下爬虫流程:请求&响应解析持久化这三个流程有没有可能以一种优雅的形式串联起来,Ruia目前是这样实现的,请看代码示例:可以看到,Item & Field类结合一起实现了字段的解析提取,Spider类结合Request * Response类实现了对爬虫程序整体的控制,从而可以如同流水线一般编写爬虫,最后返回的item可以根据使用者自身的需求进行持久化,这几行代码,我们就实现了获取目标网页请求、字段解析提取、持久化这三个流程实现了基本流程规范之后,我们继而就可以考虑一些基础功能,让使用者编写爬虫可以更加轻松,比如:中间件(Ruia里面的Middleware)、提供一些hook让用户编写爬虫更方便(比如ruia-motor)这些想明白之后,接下来就可以愉快地编写自己心目中的爬虫框架了如何踏出第一步首先,我对Ruia爬虫框架的定位很清楚,基于asyncio & aiohttp的一个轻量的、异步爬虫框架,怎么实现呢,我觉得以下几点需要遵守:轻量级,专注于抓取、解析和良好的API接口插件化,各个模块耦合程度尽量低,目的是容易编写自定义插件速度,异步无阻塞框架,需要对速度有一定追求什么是爬虫框架如今我们已经很清楚了,现在急需要做的就是将流程规范利用Python语言实现出来,怎么实现,分为哪几个模块,可以看如下图示:同时让我们结合上面一节的Ruia代码来从业务逻辑角度看看这几个模块到底是什么意思:Request:请求Response:响应Item & Field:解析提取Spider:爬虫程序的控制中心,将请求、响应、解析、存储结合起来这四个部分我们可以简单地使用五个类来实现,在开始讲解之前,请先克隆Ruia框架到本地:# 请确保本地Python环境是3.6+git clone https://github.com/howie6879/ruia.git# 安装pipenvpip install pipenv # 安装依赖包pipenv install –dev然后用PyCharm打开Ruia项目:选择刚刚pipenv配置好的python解释器:此时可以完整地看到项目代码:好,环境以及源码准备完毕,接下来将结合代码讲述一个爬虫框架的编写流程Request & ResponseRequest类的目的是对aiohttp加一层封装进行模拟请求,功能如下:封装GET、POST两种请求方式增加回调机制自定义重试次数、休眠时间、超时、重试解决方案、请求是否成功验证等功能将返回的一系列数据封装成Response类返回接下来就简单了,不过就是实现上述需求,首先,需要实现一个函数来抓取目标url,比如命名为fetch:import asyncioimport aiohttpimport async_timeoutfrom typing import Coroutineclass Request: # Default config REQUEST_CONFIG = { ‘RETRIES’: 3, ‘DELAY’: 0, ‘TIMEOUT’: 10, ‘RETRY_FUNC’: Coroutine, ‘VALID’: Coroutine } METHOD = [‘GET’, ‘POST’] def init(self, url, method=‘GET’, request_config=None, request_session=None): self.url = url self.method = method.upper() self.request_config = request_config or self.REQUEST_CONFIG self.request_session = request_session @property def current_request_session(self): if self.request_session is None: self.request_session = aiohttp.ClientSession() self.close_request_session = True return self.request_session async def fetch(self): “““Fetch all the information by using aiohttp””” if self.request_config.get(‘DELAY’, 0) > 0: await asyncio.sleep(self.request_config[‘DELAY’]) timeout = self.request_config.get(‘TIMEOUT’, 10) async with async_timeout.timeout(timeout): resp = await self._make_request() try: resp_data = await resp.text() except UnicodeDecodeError: resp_data = await resp.read() resp_dict = dict( rl=self.url, method=self.method, encoding=resp.get_encoding(), html=resp_data, cookies=resp.cookies, headers=resp.headers, status=resp.status, history=resp.history ) await self.request_session.close() return type(‘Response’, (), resp_dict) async def _make_request(self): if self.method == ‘GET’: request_func = self.current_request_session.get(self.url) else: request_func = self.current_request_session.post(self.url) resp = await request_func return respif name == ‘main’: loop = asyncio.get_event_loop() resp = loop.run_until_complete(Request(‘https://docs.python-ruia.org/').fetch()) print(resp.status)实际运行一下,会输出请求状态200,就这样简单封装一下,我们已经有了自己的请求类Request,接下来只需要再完善一下重试机制以及将返回的属性封装一下就基本完成了:# 重试函数async def _retry(self): if self.retry_times > 0: retry_times = self.request_config.get(‘RETRIES’, 3) - self.retry_times + 1 self.retry_times -= 1 retry_func = self.request_config.get(‘RETRY_FUNC’) if retry_func and iscoroutinefunction(retry_func): request_ins = await retry_func(weakref.proxy(self)) if isinstance(request_ins, Request): return await request_ins.fetch() return await self.fetch()最终代码见ruia/request.py即可,接下来就可以利用Request来实际请求一个目标网页,如下:这段代码请求了目标网页https://docs.python-ruia.org/并返回了Response对象,其中Response提供属性介绍如下:Field & Item实现了对目标网页的请求,接下来就是对目标网页进行字段提取,我觉得ORM的思想很适合用在这里,我们只需要定义一个Item类,类里面每个属性都可以用Field类来定义,然后只需要传入url或者html,执行过后Item类里面 定义的属性会自动被提取出来变成目标字段值可能说起来比较拗口,下面直接演示一下可能你就明白这样写的好,假设你的需求是获取HackerNews网页的title和url,可以这样实现:import asynciofrom ruia import AttrField, TextField, Itemclass HackerNewsItem(Item): target_item = TextField(css_select=‘tr.athing’) title = TextField(css_select=‘a.storylink’) url = AttrField(css_select=‘a.storylink’, attr=‘href’)async def main(): async for item in HackerNewsItem.get_items(url=“https://news.ycombinator.com/"): print(item.title, item.url)if name == ‘main’: items = asyncio.run(main())从输出结果可以看到,title和url属性已经被赋与实际的目标值,这样写起来是不是很简洁清晰也很明了呢?来看看怎么实现,Field类的目的是提供多种方式让开发者提取网页字段,比如:XPathCSS SelectorRE所以我们只需要根据需求,定义父类然后再利用不同的提取方式实现子类即可,代码如下:class BaseField(object): "”" BaseField class """ def init(self, default: str = ‘’, many: bool = False): """ Init BaseField class url: http://lxml.de/index.html :param default: default value :param many: if there are many fields in one page """ self.default = default self.many = many def extract(self, *args, **kwargs): raise NotImplementedError(’extract is not implemented.’)class _LxmlElementField(BaseField): passclass AttrField(_LxmlElementField): """ This field is used to get attribute. """ passclass HtmlField(_LxmlElementField): """ This field is used to get raw html data. """ passclass TextField(_LxmlElementField): """ This field is used to get text. """ passclass RegexField(BaseField): """ This field is used to get raw html code by regular expression. RegexField uses standard library re inner, that is to say it has a better performance than _LxmlElementField. """ pass核心类就是上面的代码,具体实现请看ruia/field.py接下来继续说Item部分,这部分实际上是对ORM那块的实现,用到的知识点是元类,因为我们需要控制类的创建行为:class ItemMeta(type): """ Metaclass for an item """ def new(cls, name, bases, attrs): __fields = dict({(field_name, attrs.pop(field_name)) for field_name, object in list(attrs.items()) if isinstance(object, BaseField)}) attrs[’__fields’] = __fields new_class = type.new(cls, name, bases, attrs) return new_classclass Item(metaclass=ItemMeta): """ Item class for each item """ def init(self): self.ignore_item = False self.results = {}这一层弄明白接下来就很简单了,还记得上一篇文章《谈谈对Python爬虫的理解》里面说的四个类型的目标网页么:单页面单目标单页面多目标多页面单目标多页面多目标本质来说就是要获取网页的单目标以及多目标(多页面可以放在Spider那块实现),Item类只需要定义两个方法就能实现:get_item():单目标get_items():多目标,需要定义好target_item具体实现见:ruia/item.pySpider在Ruia框架中,为什么要有Spider,有以下原因:真实世界爬虫是多个页面的(或深度或广度),利用Spider可以对这些进行 有效的管理制定一套爬虫程序的编写标准,可以让开发者容易理解、交流,能迅速产出高质量爬虫程序自由地定制插件接下来说说代码实现,Ruia框架的API写法我有参考Scrapy,各个函数之间的联结也是使用回调,但是你也可以直接使用await,可以直接看代码示例:from ruia import AttrField, TextField, Item, Spiderclass HackerNewsItem(Item): target_item = TextField(css_select=‘tr.athing’) title = TextField(css_select=‘a.storylink’) url = AttrField(css_select=‘a.storylink’, attr=‘href’)class HackerNewsSpider(Spider): start_urls = [f’https://news.ycombinator.com/news?p={index}’ for index in range(1, 3)] async def parse(self, response): async for item in HackerNewsItem.get_items(html=response.html): yield itemif name == ‘main’: HackerNewsSpider.start()使用起来还是挺简洁的,输出如下:[2019:03:14 10:29:04] INFO Spider Spider started![2019:03:14 10:29:04] INFO Spider Worker started: 4380434912[2019:03:14 10:29:04] INFO Spider Worker started: 4380435048[2019:03:14 10:29:04] INFO Request <GET: https://news.ycombinator.com/news?p=1>[2019:03:14 10:29:04] INFO Request <GET: https://news.ycombinator.com/news?p=2>[2019:03:14 10:29:08] INFO Spider Stopping spider: Ruia[2019:03:14 10:29:08] INFO Spider Total requests: 2[2019:03:14 10:29:08] INFO Spider Time usage: 0:00:03.426335[2019:03:14 10:29:08] INFO Spider Spider finished!Spider的核心部分在于对请求URL的请求控制,目前采用的是生产消费者模式来处理,具体函数如下:详细代码,见ruia/spider.py更多至此,爬虫框架的核心部分已经实现完毕,基础功能同样一个不落地实现了,接下来要做的就是:实现更多优雅地功能实现更多的插件,让生态丰富起来修BUG项目地址点击阅读原文或者在github搜索ruia,如果你有兴趣,请参与进来吧!如果觉得写得不错,点个好看来个star呗 ...

March 15, 2019 · 3 min · jiezi

Python微型异步爬虫框架

AmipyPython微型异步爬虫框架(A micro asynchronous Python website crawler framework)基于Python 3.5 + 的异步async-await 框架,搭建一个模块化的微型异步爬虫。可以根据需求控制异步队列的长度和延迟时间等。配置了可以去重的布隆过滤器,网页内容正文过滤等,完全自主配置使用。GitHub地址:源码适用环境windows 7 +Python 3.5 +安装直接使用pip安装即可:pip install amipy基础命令1.查看当前路径下的可用命令,在DOS命令行下输入:>amipy会出现命令帮助界面。2.创建一个新的项目,在DOS命令行下输入:>amipy cproject myproject会在当前路径下创建一个Amipy爬虫项目myproject。如果想要创建在指定目录下,可以加上附加参数,-d,如:> amipy cproject myproject -d D:\somefolder项目myproject便会在路径D:somefolder下创建。项目的目录结构应该如下:–myproject |-spiders | |-init.py |-init.py |-settings.py其中:settings.py 为整个项目的配置文件,可以为整个项目下的爬虫安装共有的中间件,控制整个项目的请求并发数,设置日志级别、文件路径等。3.进入项目路径,创建一个新的爬虫,在DOS命令行下输入:>amipy cspider myspider此时在项目myproject目录下的spiders文件夹中会创建一个爬虫目录myspider,此时的项目结构为:–myproject |-spiders | |-init.py | |-myspider | | |-init.py | | |-cookies.info | | |-item.py | | |-settings.py | | |-site_record.info | | |-spider.py | | |-url_record.info |-init.py |-settings.py |-log.log其中:位于myspider文件夹下的settings.py为爬虫myspider的配置文件,该配置只对当前爬虫有效。可以对该爬虫的布隆过滤器进行配置,安装中间件等。cookies.info 为爬虫的请求cookie保存文件,该爬虫爬过的所有网站的cookie会保存进该文件。可以通过爬虫配置文件settings.py进行路径加载和保存。site_record.info 为爬虫爬取过的网站的布隆过滤器记录文件,方便下次爬取的时候加载,会把爬取过的网站自动去掉。防止重复爬取。url_record.info 为该爬虫发出的请求url+headers+method+数据的去重后集合,爬虫结束运行时,如果配置保存去重url集合。下次爬取时加载该文件可以自动过滤爬取过的所有url+headers+method+数据。item.py 为ORM的MongoDB数据集合对象,对应的类属性可以映射到数据库集合中的字段,类名为数据表名。spider.py 为当前爬虫的主要文件,自己编写爬取逻辑,提取规则和数据保存脚本等。4.运行项目下的所有爬虫,进入项目路径,在DOS命令行下输入:>amipy runproject则该项目下的所有爬虫会开始运行,如果不想运行某个爬虫,只需要加上参数 -e,如:>amipy runproject -e No1spider No2spider则名为“No1spider”、“No2spider”的爬虫均不会运行。5.运行指定的爬虫,进入项目路径,在DOS命令行下输入:>amipy runspider myspider01 则名为“myspider01”的爬虫便会被启动。可以加上多个爬虫名称,用空格隔开即可。6.列出当前项目下的所有爬虫信息。在DOS命令行下输入:>amipy list便会将当前项目下的所有爬虫信息列出。使用Amipy爬虫编写流程编写自己的爬虫。【假设你已经安装前面"基础命令"创建了一个项目,并且创建了一个爬虫名为myspider】只需要进入myspider文件夹,按照需求修改当前爬虫的配置settings.py 以及数据存储需要用到的表模型item.py编写,编辑文件spider.py,加入爬取规则逻辑等。Url类对象Url类对象是一个规则匹配类,它提供了许多种模式的url规则匹配。比如:from amipy import Url# 表示匹配到正则模式’http://www.170mv.com/song.‘的所有链接Url(re=‘http://www.170mv.com/song.’)# 表示匹配到正则模式’http://www.170mv.com/song.‘的所有链接其回调函数为’getmp3’Url(re=‘http://www.170mv.com/song/.’,callback=‘getmp3’)# 表示匹配到地址为http协议,且路径为‘/novel/chapter1’,参数number=2的所有链接Url(scheme=‘http’,path=’/novel/chapter1’,params=‘number=2’)# 表示匹配到域名为www.baidu.com的所有链接,为该链接请求设置代理为'127.0.0.1:1080’Url(domain=‘www.baidu.com’,proxy=‘127.0.0.1:1080’)# 表示匹配到域名为www.baidu.com的所有链接,直接扔掉这些链接。Url(domain=‘www.baidu.com’,drop=True)Url类应用的还在于黑白名单属性中,如在爬虫类中的属性:whitelist = [ Url(re=‘http://www.170mv.com/song.’), Url(re=‘http..sycdn.kuwo.cn.’),]blacklist = [ Url(re=‘http://www.170mv.com/song.’), Url(re=‘http..sycdn.kuwo.cn.’),] 表示爬虫请求的url黑白名单匹配规则。必要属性打开spider.py ,可以看到有两个默认的必要属性:name 爬虫的唯一标识,项目下不能有该属性重名的爬虫。urls 起始链接种子,爬虫开始的url列表这两个属性是必须的。回调函数整个项目的主要实现在于回调函数的使用,利用异步请求得到响应后马上调用其请求绑定的回调函数来实现爬虫的异步爬取。请求后响应的回调函数(类方法)有:parse 返回状态200,请求正常响应正常,可以编写正常的规则提取、数据保存等。error 状态码非200,出现异常状态码,编写错误处理逻辑等。exception 请求出现异常,异常自定义处理。数据存储Amipy目前只支持MongoDB数据库,默认的数据库设置在爬虫配置文件settings.py中。对于爬取的数据进行保存,默认只使用MongoDB进行数据存储(后续可以自己扩展编写ORM)。只需要打开item.py,修改其中的示例类,原先为:from amipy.BaseClass.orm import Model,Fieldclass DataItemName(Model): …修改其内容为:from amipy.BaseClass.orm import Model,Fieldclass MyTableName(Model): ID = Field(‘索引’) content = Field(‘内容’)则类名 MyTableName为保存在指定数据库中的数据集合名称,ID为列对象,名称为“索引”,以此类推,content也为列对象,名称为“内容”。可以按照自己的需求进行添加删减列。数据的保存只需要在回调函数中对对应的列对象进行赋值,而后调用ORM对象的save函数即可。比如在spider.py的爬虫类中的成功回调函数parse中保存爬取到的数据: … def parse(self,response): self.item.ID = 200 self.item.content = ‘这是内容’ self.item.save() …则 数据集合 MyTableName中会自动保存一行数据:列“索引”为200,列“内容”为“这是内容”的数据行。引用orm数据模型对象只需要调用爬虫类的item属性,如上面示例中的self.item即是。获取其数据库对象可以使用:self.item.db来获得当前爬虫连接的MongoDB数据库对象。可以通过self.item.db.save()self.item.db.delete()self.item.db.update()…等api来实现数据库操作。事件循环loopAmipy爬虫的异步请求基于python3的协程async框架,所以项目全程只有一个事件循环运行,如果需要添加更多的爬虫请求,可以通过回调函数传进事件循环,加入请求队列。具体做法便是通过在爬虫类的回调函数中使用send函数来传递请求Request对象:import amipyfrom amipy import Request,sendclass MySpider(amipy.Spider): … def parse(self,response): … # 加入新的爬虫请求 url = ‘http://www.170mv.com/download/' send(Request(self,url)) …可以在项目配置文件settings.py中设置整个项目最大的协程并发数CONCURRENCY,以及协程请求的延时等。Telnet连接Amipy爬虫内置一个服务线程,可以通过Telnet进行连接来查看操作当前项目的爬虫,在启动爬虫后,可以通过新开一个DOS命令窗口,输入:>telnet 127.0.0.1 2232进行Telnet连接至项目服务线程,可以使用的命令有: show spiders show all running spiders and their conditions. list list a general situation of all spiders. echo echo a running spider and its attributes. pause pause a running spider by a give name. stop stop a running/paused spider by a give name. close close a spider by a give name. restart restart a stopped spider by a give name. resume resume a paused spider by a give name. quit quit the Spider-Client. help show all the available commands usage.举例,假设当前爬虫唯一标识名称为lianjia,则可以通过:$amipy> pause lianjia来暂停爬虫lianjia的爬取进度,在爬虫将当前请求队列清空后会一直暂停,直到收到Telnet端发出的其他命令。恢复爬虫使用:$amipy> resume lianjia查看当前项目下所有爬虫:$amipy> list详细查看则使用:$amipy> show spiders开启关闭Telnet在项目的配置文件settings.py中设置SPIDER_SERVER_ENABLE。例子1. 使用Amipy创建链家网爬虫(LianJiaSpider)爬虫目的:爬取链家网上北京当前最新的租房信息,包含“价格”,“房屋基本信息”、“配套设施”、“房源描述”、“联系经纪人”、“地址和交通”存入MongoDB数据库中创建项目进入到D:LianJia路径,创建Amipy项目LJproject:D:\LianJia> amipy cproject LJproject创建爬虫进入到项目路径D:LianJiaLJproject,创建Amipy爬虫lianjia:D:\LianJia\LJproject> amipy cspider lianjia编写数据库模型打开D:LianJiaLJprojectspidersLianjiaitem.py,编写数据保存模型:#coding:utf-8from amipy.BaseClass.orm import Model,Fieldclass LianJiaRenting(Model): price = Field(‘价格’) infos = Field(‘房屋基本信息’) facility = Field(‘配套设施’) desc = Field(‘房源描述’) agent = Field(‘联系经纪人’) addr = Field(‘地址与交通’)设置数据库连接打开 D:LianJiaLJprojectspidersLianjiasettings.py,找到MongoDB数据库连接设置,进行设置:# MongoDB settings for data saving.DATABASE_SETTINGS = { ‘host’:‘127.0.0.1’, ‘port’:27017, ‘user’:’’, ‘password’:’’, ‘database’:‘LianJiaDB’,}要先确保系统安装好MongoDB数据库并已经开启了服务。编写爬虫脚本打开 D:LianJiaLJprojectspidersLianjiaspider.py,编写爬虫采集脚本:import amipy,refrom amipy import send,Request,Urlfrom bs4 import BeautifulSoup as bs class LianjiaSpider(amipy.Spider): name = ’lianjia’ # 设置爬取初始链接 urls = [‘https://bj.lianjia.com/zufang/’] # 设置爬虫白名单,只允许爬取匹配的链接 whitelist = [ Url(re=‘https://bj.lianjia.com/zufang/.*’), ] # 自定义的属性 host =‘https://bj.lianjia.com’ page = 1 # 请求成功回调函数 def parse(self,response): soup = bs(response.text(),’lxml’) item_list = soup(‘div’,class_=‘content__list–item’) for i in item_list: # 获取详情页链接 并发送至爬虫请求队列 url = self.host+i.a[‘href’] send(Request(self,url,callback=self.details)) # 添加下一页 totalpage = soup(‘div’,class_=‘content__pg’)[0][‘data-totalpage’] if self.page>=int(totalpage): return self.page +=1 send(Request(self,self.host+’/zufang/pg{}/’.format(self.page))) def details(self,response): infos = {} agent = {} facility = [] soup = bs(response.text(),’lxml’) infos_li = soup(‘div’,class_=‘content__article__info’)[0].ul(’li’) facility_li = soup(‘ul’,class_=‘content__article__info2’)0 agent_ul = soup(‘ul’,id=‘agentList’)[0] addr_li = soup(‘div’,id=‘around’)[0].ul.li desc_li = soup(‘div’,id=‘desc’)[0].li desc_li.div.extract() desc = desc_li.p[‘data-desc’] if desc_li.p else ’’ for i in infos_li: text = i.text if ‘:’ in text: infos.update({text.split(’:’)[0]:text.split(’:’)[1]}) for i in facility_li[1:]: if ‘no’ not in i[‘class’][-2]: facility.append(i.text) for div in agent_ul(‘div’,class=‘desc’): name = div.a.text phone = div(‘div’,class_=‘phone’)[0].text agent[name]=phone # 数据模型对应并保存 self.item.desc = desc self.item.addr = re.sub(r’[\r\n ]’,’’,addr_li.text) if addr_li else ’’ self.item.price = soup(‘p’,class_=‘content__aside–title’)[0].text self.item.infos = infos self.item.agent = agent self.item.facility = facility self.item.save()如果在爬虫配置文件settings.py中设置遵守目标网站机器人协议可能会被禁止采集,可以自行关闭设置。另外,开启网页内容相似过滤BLOOMFILTER_HTML_ON可能会使爬取的结果数较少,爬虫只会采集相似度不同的网页内容的链接,如果需要大批量采集,而网页正文较少的,可以关闭这个设置。代码比较粗糙,但可以知道Amipy爬虫基本的实现流程。运行爬虫在项目根路径下,输入:D:\LianJia\LJproject> amipy runspider查看数据库进入MongoDB数据库:可以看到在数据库‘LianJiaDB’下的集合“LianJiaRenting”中已经保存有我们爬取的数据,格式如下:{ “_id” : ObjectId(“5c6541b065b2fd1cf002c565”), “价格” : “7500元/月 (季付价)”, “房屋基本信息” : { “发布” : “20天前”, “入住” : “随时入住”, “租期” : “2~3年”, “看房” : “暂无数据”, “楼层” : “中楼层/6层”, “电梯” : “无”, “车位” : “暂无数据”, “用水” : “民水”, “用电” : “民电”, “燃气” : “有”, “采暖” : “集中供暖” }, “配套设施” : [ “电视”, “冰箱”, “洗衣机”, “空调”, “热水器”, “床”, “暖气”, “宽带”, “衣柜”, “天然气” ], “房源描述” : “【交通出行】 小区门口为八里庄南里公交车站,75,675等多路公交经过。地铁6号线十里堡站D口,距离地铁口400米,交通十分方便,便于出行。<br />\n【周边配套】 此房位置棒棒哒,有建设银行,中国银行,交通银行,邮政储蓄,果多美水果超市,购物,金旭菜市场,娱乐,休闲,便利。旁边首航超市,姥姥家春饼,味多美蛋糕店,生活方便。<br />\n【小区介绍】 该小区中此楼是1981建成,安全舒适,小区内主力楼盘为6层板楼,前后无遮挡,此楼是多见的板楼,楼层高视野好。<br />\n”, “联系经纪人” : { “宋玉恒” : “4000124028转7907” }, “地址与交通” : “距离6号线-十里堡192m”}查看当前爬取进度新开一个DOS端口,输入:> telnet 127.0.0.1 2232进行Telnet连接,可以使用命令操作查看当前爬虫的爬取状态。例如使用echo命令:$amipy> echo lianjia可以查看当前爬虫的状态:—————-Spider-lianjia——————– Name:lianjia Status:RUNNING- Class:LianjiaSpider- Success:25 Fail:0 Exception:0- Priority:0- SeedUrls:[‘https://bj.lianjia.com/zufang/’]- Path:D:\LianJia\LJproject\spiders\Lianjia- Session:<aiohttp.client.ClientSession object at 0x000000000386FE10>- StartAt:Thu Feb 14 20:30:21 2019- PausedAt:None- ResumeAt:None- StopAt:None- RestartAt:None- CloseAt:None————————————————– ...

February 14, 2019 · 3 min · jiezi

如何通过Python玩转小视频

什么是爬虫?就是抓取网页数据的程序爬虫怎么抓取网页数据?网页三大特征:网页都有自己唯一的URL。网页都是HTML来描述页面信息。网页都使用http/https协议来传输HTML数据。爬虫的设计思路:1、获取视频ID 2、拼接完整url3、获取视频播放地址4、下载视频模块使用requests安装“pip install requests”Requests库的七个主要方法找到单个视频播放地址获取网页源代码获取播放地址下载视频实现效果

January 27, 2019 · 1 min · jiezi

大众点评爬虫

大众点评爬虫可用api大众点评爬虫、API,可以进行单独城市、单独地区、单独商铺的爬取、搜索、多类型地区搜索、信息获取、提供MongoDB数据库存储支持,可以进行点评文本解密的爬取、存储。源码:地址可用于大众点评网页版目前可用:获取大众点评当前可以查询查看到店铺的所有已激活城市信息获取大众点评里所有省市直辖市的provinceId以及地区areaId根据给定的中文城市、地区名称来获取其大众点评首页链接通过id获取地区名称通过id获取地区内的所有子地区信息获取某个城市的 热搜关键词获取某个城市的 当前可见有效店铺分类获取某个城市的 当前可见有效的辖区信息,包含子地区获取某个城市的 某个关键词相关的搜索结果和结果数(单线程与多线程)搜索某个城市关于某个关键词的某个分类、子地区、排序方式的相关店铺并支持MongoDB存储和本地文件存储获取某个商铺的评分、星级、地址、电话、点评数、人均消费、点评标签、点评种类等获取某个商铺的加密点评信息,支持条数设定环境使用环境:win 7 64bitspycharmpython3第三方库:bs4 >=0.0.1lxml >=4.2.5pymongo >=3.7.1requests >=2.19.1使用前因为大众点评的反爬措施,需要设置IP代理以及随机切换可用的User-Agent来进行大量数据的爬取。IP代理(Proxy)如何设置?config.py中有详细的各个代理设置注释,建议使用PROXY_POOL进行IP代理,可以使用一次一个的接口来获取代理IP。UA池user-agent可以使用settings.py中的UA池,如果你有更多的可用UA,可以自己加进去或者替换掉。用户cookie如果你需要爬取加密的商铺点评数据(页数>1),则需要添加点评用户的登陆cookie到config.py的COOKIE中。具体内容为一个字符串,如:’lxsdk_cuid=1681d897b62c8;hc.v=ff4f63f6;thirdtoken=c9792’之类的。可以在浏览器调试界面获得。数据库存储(MongoDB)与本地存储如果需要存储搜索的店铺数据,则需要到config.py中设置MongoDB的数据库设置(本地存储可以在城市搜索api中设置保存本地的路径。),其中’database’为默认使用的数据库,‘records’为记录抓取的数据表名,‘searchDB’为搜索结果存放的数据库其他相关的配置可以参见config.py 中的设置注解使用获取大众点评当前可以查询查看到店铺的所有已激活城市信息from dianping import DianPingdp = DianPing()cities = dp.active_cities返回结果 cities 为大众点评全国可以显示搜索到店铺的激活城市列表:[ { “activeCity”: true, “appHotLevel”: 1, “cityAbbrCode”: “BJ”, “cityAreaCode”: “010”, “cityEnName”: “beijing”, “cityId”: 2, “cityLevel”: 1, “cityName”: “北京”, “cityOrderId”: 406, “cityPyName”: “beijing”, “directURL”: “”, “gLat”: 39.904667, “gLng”: 116.408198, “overseasCity”: false, “parentCityId”: 0, “provinceId”: 1, “scenery”: false, “tuanGouFlag”: 1 }, …]获取大众点评里所有省市直辖市的provinceId以及地区areaIdfrom dianping import DianPingdp = DianPing()provinces = dp.provinces返回结果 provinces 为全国的省、直辖市的ID信息:{ “北京”: { “areaId”: 1, “provinceId”: “1” }, “天津”: { “areaId”: 1, “provinceId”: “2” }, “河北”: { “areaId”: 1, “provinceId”: “3” }, “山西”: { “areaId”: 1, “provinceId”: “4” }, …}根据给定的中文城市、地区名称来获取其大众点评首页链接from city import Citybeijing = City(‘北京’)url = beijing.url返回结果 url 为北京市的大众点评首页:http://www.dianping.com/beijing获取某个城市的 当前可见有效的辖区信息,包含子地区from city import Citybeijing = City(‘北京’)beijing.get()locations = beijing.locations返回结果 locations 为当前城市的所有子地区信息:[ { “text”: “海淀区”, “value”: “17”, “children”: [ { “text”: “双榆树”, “value”: “2587”, “children”: [ { “text”: “HQ尚客百货”, “value”: “6975” }, { “text”: “当代商城”, “value”: “2622” }, { “text”: “华星影城”, “value”: “2665” }, { “text”: “双安商场”, “value”: “2720” } ] }, … ] }, …]通过id获取城市的某个地区名称#id 必须为城市中某个地区的idfrom util.city import find_region_by_idfrom city import Citybeijing = City(‘北京’)beijing.get()someplace = find_region_by_id(6975,beijing.locations)返回结果 someplace 为北京地区的对应id的子地区名称:# ID 6975 对应的地区HQ尚客百货通过id获取地区内的所有子地区信息from util.city import find_children_regionsfrom city import Citybeijing = City(‘北京’)beijing.get()sub_regions = find_children_regions(5956,beijing.locations)返回结果 sub_regions 为当前id下的所有子地区id列表:# id 在城市的子地区列表中,但其未有子地区,返回:False# id 在城市的子地区列表中, 如果其有子地区的话则返回子地区id列表:[‘6008’]# id 不在城市的子地区列表中,则返回城市的一级子地区:[‘17’, ‘5951’, ‘328’, ‘15’, ‘5952’, ‘14’, ‘5950’, ‘9158’, ‘16’, ‘20’, ‘9157’]获取某个城市的 热搜关键词from city import Citybeijing = City(‘北京’)beijing.get()hot = beijing.hot返回结果 hot 为当前城市“北京”的热搜词汇列表(包含其所属分类id等信息):[ { “subtag”: “3”, “location”: “7”, “maincategoryids”: “35,60”, “datatype”: “3002”, “id”: “786881”, “suggestkeyword”: “温泉” }, { “subtag”: “18”, “location”: “8”, “maincategoryids”: “10”, “datatype”: “3002”, “id”: “692874”, “suggestkeyword”: “烤鸭” }, …]获取某个城市的 当前可见有效店铺分类from city import Citybeijing = City(‘北京’)beijing.get()category = beijing.category返回结果 category 为该城市所有的店铺分类信息列表:[ { “text”: “酒吧”, “value”: “133”, “children”: [ { “text”: “清吧”, “value”: “33950” }, { “text”: “Live House”, “value”: “33951” }, { “text”: “夜店”, “value”: “2951” } ] }, { “text”: “茶馆”, “value”: “134” }, …]获取某个城市的 某个关键词相关的搜索结果和结果数from city import Citybeijing = City(‘北京’)beijing.get()relative = beijing.get_relative(‘健身’)返回结果 relative 为北京市关键词“健身”相关的搜索词汇以及其对应结果数:{ “良子健身 京粮大厦店”: “1”, “健身游泳瑜伽综合性会所”: “1”, “Hey Heroes!私教健身工作室 泛悦坊店”: “1”, “ULife悦体健身 五棵松店”: “1”, “U-Vista优维斯塔健身工作室 金融街旗舰店”: “1”, “健身房24小时”: “161”, “健身体验卡”: “1”, “锐健身”: “29”, “Hot Fitness 热健身工作室 霍营店”: “1”, “锻造健身ForgingFitness国际私教工作室”: “1”}(单线程与多线程)搜索某个城市关于某个关键词的某个分类、子地区、排序方式的相关店铺并支持MongoDB存储和本地文件存储单线程搜索下载相关店铺下例为搜索下载北京市“海淀区”店铺分类为“运动健身”的“有团购”的与“器材”相关的所有店铺,搜索下载结果“按人气排序”,save表示是否保存进MongoDB数据库,details表示是否抓取店铺的详细信息。具体参数可见search函数注释。from city import Citybeijing = City(‘北京’)beijing.get()results = beijing.search(‘器材’,category=‘运动健身’,location=‘海淀区’,filter=‘有团购’,sort=‘按人气排序’,save=True,details=True)返回结果 results 为搜索到的相关店铺,具体内容,单个店铺的MongoDB数据库显示:{ “_id” : ObjectId(“5c3c88f265b2fd3134266c7b”), “店名” : “优享健身(金源店)”, “星级” : “四星商户”, “注册时间” : “2017-07-25T23:19:00”, “地址” : “ 远大路世纪金源燕莎B1层卜蜂莲花超市内南侧家电区”, “人均” : 3526, “预订” : false, “分店url” : “http://www.dianping.com/brands/b93357498s45g45", “商铺图片” : “http://vfile.meituan.net/joymerchant/-1945301364589883676-23601423-1525363931678.jpg", “商铺标签” : “健身房”, “纬度” : 39.9573, “经度” : 116.28518, “电话” : [ “010-57159188” ], “店铺ID” : 93357498, “会员卡ID” : 0, “地区” : [ “远大路” ], “expand” : 0, “poi” : “HEHHURZVVGIDGF”, “promoId” : 0, “shopDealId” : 27807431, “shopPower” : 40, “hasSceneryOrder” : false, “点评数” : “118”, “点评标签” : [ “环境优雅(43)”, “服务热情(17)”, “设施很赞(15)”, “教练很棒(14)”, “器械齐全(7)”, “体验很棒(7)”, “干净卫生(4)”, “高大上(4)” ], “点评类别” : { “图片” : “55”, “好评” : “85”, “中评” : “7”, “差评” : “26” }, “评分” : { “设施” : “8.3”, “环境” : “8.2”, “服务” : “7.6” }}多线程搜索下载相关店铺多线程搜索与单线程搜索流程一致,只是搜索线程多开了而已,线程数为搜索结果的页数,最多为50个(大众点评目前单页最多个数)。启用多线程的话,由于使用代理IP,有可能同时获取的代理多个线程都是同一个,所以在config.py加入了RANDOM_INTERVAL(随机等待间隔)防止多个线程使用同一个代理被封。获取某个商铺的评分、星级、地址、电话、点评数、人均消费、点评标签、点评种类等下例以获取id为507576的店铺信息为例from shop import Shopstore = Shop(‘507576’)store.get()#店铺名name = store.name#店铺星级,50为五星,40为四星,35为三星半stars = store.stars#地址address = store.address#联系方式phone = store.phone#点评数reviews = store.reviews#人均消费average = store.average#顾客评分scores = store.scores#点评种类及数量comment_kinds = store.comment_kinds#点评标签及数量review_tags = store.review_tags返回结果 :‘满福楼’‘50’‘朝阳门外大街8号蓝岛大厦东区六层(东大桥铁站D2出口)‘‘‘64030992 64053088’‘18821’‘128’{‘口味’: ‘9.1’, ‘环境’: ‘9.1’, ‘服务’: ‘9.1’}{‘图片’: ‘3513’, ‘好评’: ‘17632’, ‘中评’: ‘355’, ‘差评’: ‘95’}[‘回头客(404)’, ‘干净卫生(253)’, ‘上菜快(106)’, ‘停车方便(59)’, ‘夜景赞(5)’, ‘请客(161)’, ‘朋友聚餐(93)’, ‘家庭聚餐(44)’, ‘现做现卖(22)’, ‘下午茶(9)’]获取下载保存某个商铺的加密点评信息,支持条数设定获取点评需要使用cookie,具体使用参见“使用前”,默认保存数据进入数据库,具体的参数详情参见get_reviews函数注释。下例以获取店铺id为 507576 的商铺以第2页为起点的 300条加密点评为例:from comment import Commentsfrom dbhelper import Databasefrom config import MongoDBdianpingDB = Database(MongoDB)target_shop = Comments(‘50576’,db=dianpingDB)target_shop.get()target_shop.get_reviews(tname=‘保存数据表名’,count=300,frompage=2)结果已经被存储在数据库中,MongoDB数据库中的单条点评数据内容具体为:{ “_id” : ObjectId(“5c3c914e65b2fd3384558c69”), “点评ID” : “496225994”, “点评链接” : “http://www.dianping.com/review/496225994", “点评用户” : “好想吃好”, “用户ID” : “781396343”, “用户主页” : “http://www.dianping.com/member/781396343", “用户头像” : “https://p0.meituan.net/userheadpicbackend/83fe454da66682fcbd43aed7e716f7c5104831.jpg", “用户等级” : “lv5”, “VIP用户” : true, “点评商铺” : “满福楼”, “商铺ID” : “507576”, “点评星级” : “50”, “用户评价” : { “口味” : “非常好”, “环境” : “非常好”, “服务” : “非常好” }, “点评时间” : “2019-01-13 21:17”, “点评图片” : [ “http://qcloud.dpfile.com/pc/chB7IwRZcpIwgAZu6ZkIE1Ts_aTNOyiGGbmIGbs4RjCN3JfGN-IioWlr9osF8hImjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/zGhlhFul5cqBQs7e5Vz8vKGz21xv2xOlIEIwy7kf50p-NpRbr0UwQ7niAIDwKWOCjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/Ve_jDe47G9v8Da_Hsy9MpZqCs0Fb67Yq6j2rkpqgN7H0kAawvhDXOXBa2ZnI1FIWjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/StJvWhLl7MjtPi7VbNfYIR2I1IS9esxPO21bqfDKVaPygfipf3l2ctLCNDL5jbj1joJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/7UmBsS10yRloypGc2Pp1pdlmdKP2hDzRhWT5wZLgI-JbnpM9T49yMmnt4yPiPxuwjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/sI_CeStxWNFGJcOTa1bhmxOKkLGBEHBmXGaXkST7jk8t-HQzlOY35ADlO6UZvd_rjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/fXFthqUVtnH64f56FytXNTHCV_h2ItUd8n-LqQllEf8Ho8itsBkcmVncTI8kIYxjjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/7DrPJ4wMkZMQJQMwzrV_htFX28QHwS538qf9O7X1Hx0i8AgtQV76cj-_sKD6JTPFjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/FZy3uddbXxAZkk2-J8EI7GFutnl-xTc7gEdOn8IsUFQrvkHyMac7eaNrOOmvIgmcjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/px379Hd9MRRqOF6opKanBs8QEGc7UK5pjkSHtQoP9BrbMF6JuBDWN8BUF4VB5oV5joJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg”, “http://qcloud.dpfile.com/pc/xwUMFgIHr8Uemd33o3rQMg6ktHU-4BMTzvInDCRMhkhXBw3IHLzmZnDdPoSzfFepjoJrvItByyS4HHaWdXyO_DrXIaWutJls2xCVbatkhjUNNiIYVnHvzugZCuBITtvjski7YaLlHpkrQUr5euoQrg.jpg” ], “评论事件” : { “赞” : “4” }, “点评内容” : “家里的抓到300元代金券,今天到店品尝美味。乘直梯到六楼,进店入眼就是放着小铜锅的餐桌,才十一点多点儿大厅就几乎满员。仨人按大众点评的推荐及个人喜好点了「牛骨高汤」「手切鲜羊肉」「羊上脑」「手切精品鲜黄瓜条」「精品太阳肉」仨「羊肉串儿」「糖卷果」肚子实在没地方了,可精品还没吃,只好「烤火烧」「炸火烧」「肉沫烧饼」「烤腰子」各点一个,三人分着尝口儿。点的肉涮着吃没一点儿膻味儿,还很嫩,麻酱蘸料很好吃!特别是腰子烤的牛极了,外面包的油焦脆,里面的腰子火候正好,美味!各种火烧也很好吃![服务]服务很到位!锅里刚有点儿沫子,服务小妹就帮着撇出去,最后还送了果盘,看我们挺爱吃的,又提示我们果盘还可以续,并送了我们2019年新挂历,谢谢!!"}ToDo如果想要抓取多个商铺的点评数据,可以使用多个账户+多代理+UA池来绕过反爬尝试使用selenium对爬取点评数据进行验证码滑动验证使用手机接码平台注册多个账户进行模拟登陆后获取cookie进行爬取点评数据 ...

January 14, 2019 · 3 min · jiezi

python 生成18年写过的博客词云

文章链接:https://mp.weixin.qq.com/s/NmJjTEADV6zKdT–2DXq9Q回看18年,最有成就的就是有了自己的 博客网站,坚持记录,写文章,累计写了36篇了,从一开始的难以下手,到现在成为一种习惯,虽然每次写都会一字一句斟酌,但是每次看到产出,内心还是开心的,享受这样的过程。 这篇文章就是用python 生成自己写的博客词云,平常写的博客都是markdown 格式的,直接把文件传到后台,前端用js去解析文件显示的,所以我这里处理数据就不需要去爬虫网站,直接读文件处理的。 关于生成词云图的,在另外两篇文章中也有介绍过: [python itchat 爬取微信好友信息,生成词云](https://mp.weixin.qq.com/s/4E… python爬虫学习:爬虫QQ说说并生成词云图 markdown文件处理,遍历文件夹,匹配md 后缀的文件,读文件,这里的root 是文件夹的绝对路径。import ostotal = ““file_list = os.listdir(root)for file in file_list: //处理md文件 if os.path.splitext(file)[1] == “.md”: path = os.path.join(root,file) text = open(path, encoding=‘utf-8’).read() //最终得到的字符串 total = total + “\n” + text得到所有的文本之后,使用结巴分词 pip3 install jieba,处理成单个的词语。import jiebawordlist = jieba.cut(total, cut_all=True)wl = " “.join(wordlist)因为平常写的文章里有很多的代码,这里可以正则只留下中文,然后再处理中文字符。import rerec = re.compile(”[^\u4E00-\u9FA5]")total = rec.sub(””, total)wordlist = jieba.cut(total, cut_all=True)wl = " “.join(wordlist)最后就是生成词云,采用WordCloud的库wc = WordCloud( # 设置背景颜色 background_color=“white”, # 设置最大显示的词云数 max_words=1000, # 这种字体都在电脑字体中,window在C:\Windows\Fonts\下,mac下的是/System/Library/Fonts/PingFang.ttc 字体 font_path=‘C:\Windows\Fonts\STFANGSO.ttf’, height=2000, width=2000, # 设置字体最大值 max_font_size=250, # 设置有多少种随机生成状态,即有多少种配色方案 random_state=30,)myword = wc.generate(wl) # 生成词云# 展示词云图plt.imshow(myword)plt.axis(“off”)wc.to_file(‘blog.png’) # 保存图片plt.ion()plt.pause(5)plt.close() # 图片显示5s,之后关闭最终的结果显示图,除去代码之后,看这些词,不少还是跟android相关的,也是平常经常会提到的词汇。 欢迎关注我的个人博客:https://www.manjiexiang.cn/ 更多精彩欢迎关注微信号:春风十里不如认识你 一起学习,一起进步,欢迎上车,有问题随时联系,一起解决!!! ...

January 13, 2019 · 1 min · jiezi

谈谈对Python爬虫的理解

爬虫也可以称为Python爬虫不知从何时起,Python这门语言和爬虫就像一对恋人,二者如胶似漆 ,形影不离,你中有我、我中有你,一提起爬虫,就会想到Python,一说起Python,就会想到人工智能……和爬虫所以,一般说爬虫的时候,大部分程序员潜意识里都会联想为Python爬虫,为什么会这样,我觉得有两个原因:Python生态极其丰富,诸如Request、Beautiful Soup、Scrapy、PySpider等第三方库实在强大Python语法简洁易上手,分分钟就能写出一个爬虫(有人吐槽Python慢,但是爬虫的瓶颈和语言关系不大)任何一个学习Python的程序员,应该都或多或少地见过甚至研究过爬虫,我当时写Python的目的就非常纯粹——为了写爬虫。所以本文的目的很简单,就是说说我个人对Python爬虫的理解与实践,作为一名程序员,我觉得了解一下爬虫的相关知识对你只有好处,所以读完这篇文章后,如果能对你有帮助,那便再好不过什么是爬虫爬虫是一个程序,这个程序的目的就是为了抓取万维网信息资源,比如你日常使用的谷歌等搜索引擎,搜索结果就全都依赖爬虫来定时获取看上述搜索结果,除了wiki相关介绍外,爬虫有关的搜索结果全都带上了Python,前人说Python爬虫,现在看来果然诚不欺我~爬虫的目标对象也很丰富,不论是文字、图片、视频,任何结构化非结构化的数据爬虫都可以爬取,爬虫经过发展,也衍生出了各种爬虫类型:通用网络爬虫:爬取对象从一些种子 URL 扩充到整个 Web,搜索引擎干的就是这些事垂直网络爬虫:针对特定领域主题进行爬取,比如专门爬取小说目录以及章节的垂直爬虫增量网络爬虫:对已经抓取的网页进行实时更新深层网络爬虫:爬取一些需要用户提交关键词才能获得的 Web 页面不想说这些大方向的概念,让我们以一个获取网页内容为例,从爬虫技术本身出发,来说说网页爬虫,步骤如下:模拟请求网页资源从HTML提取目标元素数据持久化什么是爬虫,这就是爬虫:“““让我们根据上面说的步骤来完成一个简单的爬虫程序”““import requestsfrom bs4 import BeautifulSouptarget_url = ‘http://www.baidu.com/s?wd=爬虫’# 第一步 发起一个GET请求res = requests.get(target_url)# 第二步 提取HTML并解析想获取的数据 比如获取 titlesoup = BeautifulSoup(res.text, “lxml”)# 输出 soup.title.texttitle = soup.title.text# 第三步 持久化 比如保存到本地with open(’title.txt’, ‘w’) as fp: fp.write(title)加上注释不到20行代码,你就完成了一个爬虫,简单吧怎么写爬虫网页世界多姿多彩、亿万网页资源供你选择,面对不同的页面,怎么使自己编写的爬虫程序够稳健、持久,这是一个值得讨论的问题俗话说,磨刀不误砍柴工,在开始编写爬虫之前,很有必要掌握一些基本知识:网页的结构是HTML,爬虫的目标就是解析HTML,获取目标字段并保存客户端展现的网页由浏览器渲染,客户端和服务端的信息交互依靠HTTP协议这两句描述体现了一名爬虫开发人员需要掌握的基本知识,不过一名基本的后端或者前端工程师都会这些哈哈,这也说明了爬虫的入门难度极低,从这两句话,你能思考出哪些爬虫必备的知识点呢?基本的HTML知识,了解HTML才方便目标信息提取基本的JS知识 ,JS可以异步加载HTML了解CSS Selector、XPath以及正则,目的是为了提取数据了解HTTP协议,为后面的反爬虫斗争打下基础了解基本的数据库操作,为了数据持久化有了这些知识储备,接下来就可以选择一门语言,开始编写自己的爬虫程序了,还是按照上一节说的三个步骤,然后以Python为例,说一说要在编程语言方面做那些准备:网页请求:内置有urllib库,第三方库的话,同步请求可以使用requests,异步请求使用aiohttp分析HTML结构并提取目标元素:CSS Selector和XPath是目前主流的提取方式,第三方库可以使用Beautiful Soup或者PyQuery数据持久化:目标数据提取之后,可以将数据保存到数据库中进行持久化,MySQL、MongoDB等,这些都有对应的库支持,当然你也可以保存在硬盘,谁硬盘没点东西对吧(滑稽脸)掌握了上面这些,你大可放开手脚大干一场,万维网就是你的名利场,去吧~我觉得对于一个目标网站的网页,可以分下面四个类型:单页面单目标单页面多目标多页面单目标多页面多目标具体是什么意思呢,可能看起来有点绕,但明白这些,你之后写爬虫,只要在脑子里面过一遍着网页对应什么类型,然后套上对应类型的程序(写多了都应该有一套自己的常用代码库),那写爬虫的速度,自然不会慢单页面单目标通俗来说,就是在这个网页里面,我们的目标就只有一个,假设我们的需求是抓取这部 电影-肖申克的救赎 的名称,首先打开网页右键审查元素,找到电影名称对应的元素位置,如下图所示:在某个单一页面内,看目标是不是只有一个,一眼就能看出标题的CSS Selector规则为:#content > h1 > span:nth-child(1),然后用我自己写的常用库,我用不到十行代码就能写完抓取这个页面电影名称的爬虫:import asynciofrom ruia import Item, TextFieldclass DoubanItem(Item): title = TextField(css_select=’#content > h1 > span:nth-child(1)’)async_func = DoubanItem.get_item(url=“https://movie.douban.com/subject/1292052/")item = asyncio.get_event_loop().run_until_complete(async_func)print(item.title)多页面多目标就是此情况下多个url的衍生情况单页面多目标假设现在的需求是抓取 豆瓣电影250 第一页中的所有电影名称,你需要提取25个电影名称,因为这个目标页的目标数据是多个item的,因此目标需要循环获取,这就是所谓的单页面多目标了:import asynciofrom ruia import Item, TextFieldclass DoubanItem(Item): target_item = TextField(css_select=‘div.item’) title = TextField(css_select=‘span.title’) async def clean_title(self, title): if isinstance(title, str): return title else: return ‘’.join([i.text.strip().replace(’\xa0’, ‘’) for i in title])async_func = DoubanItem.get_items(url=“https://movie.douban.com/top250")items = asyncio.get_event_loop().run_until_complete(async_func)for item in items: print(item)多页面多目标多页面多目标是上述单页面多目标情况的衍生,在这个问题上来看,此时就是获取所有分页的电影名称from ruia import TextField, Item, Request, Spiderclass DoubanItem(Item): "”” 定义爬虫的目标字段 "”” target_item = TextField(css_select=‘div.item’) title = TextField(css_select=‘span.title’) async def clean_title(self, title): if isinstance(title, str): return title else: return ‘’.join([i.text.strip().replace(’\xa0’, ‘’) for i in title])class DoubanSpider(Spider): start_urls = [‘https://movie.douban.com/top250’] concurrency = 10 async def parse(self, res): etree = res.html_etree pages = [’?start=0&filter=’] + [i.get(‘href’) for i in etree.cssselect(’.paginator>a’)] for index, page in enumerate(pages): url = self.start_urls[0] + page yield Request( url, callback=self.parse_item, metadata={‘index’: index}, request_config=self.request_config ) async def parse_item(self, res): items_data = await DoubanItem.get_items(html=res.html) res_list = [] for item in items_data: res_list.append(item.title) return res_listif name == ‘main’: DoubanSpider.start()如果网络没问题的话,会得到如下输出:注意爬虫运行时间,1s不到,这就是异步的魅力用Python写爬虫,就是这么简单优雅,诸位,看着网页就思考下:是什么类型的目标类型用什么库模拟请求怎么解析目标字段怎么存储一个爬虫程序就成型了,顺便一提,爬虫这东西,可以说是防君子不防小人,robots.txt大部分网站都有(它的目的是告诉爬虫什么可以爬取什么不可以爬取,比如:https://www.baidu.com/robots.txt),各位想怎么爬取,自己衡量如何进阶不要以为写好一个爬虫程序就可以出师了,此时还有更多的问题在前面等着你,你要含情脉脉地看着你的爬虫程序,问自己三个问题:爬虫抓取数据后是正当用途么?爬虫会把目标网站干掉么?爬虫会被反爬虫干掉么?前两个关于人性的问题在此不做过多叙述,因此跳过,但你们如果作为爬虫工程师的话,切不可跳过会被反爬虫干掉么?最后关于反爬虫的问题才是你爬虫程序强壮与否的关键因素,什么是反爬虫?当越来越多的爬虫在互联网上横冲直撞后,网页资源维护者为了防止自身数据被抓取,开始进行一系列的措施来使得自身数据不易被别的程序爬取,这些措施就是反爬虫比如检测IP访问频率、资源访问速度、链接是否带有关键参数、验证码检测机器人、ajax混淆、js加密等等对于目前市场上的反爬虫,爬虫工程师常有的反反爬虫方案是下面这样的:不断试探目标底线,试出单IP下最优的访问频率构建自己的IP代理池维护一份自己常用的UA库针对目标网页的Cookie池需要JS渲染的网页使用无头浏览器进行代码渲染再抓取一套破解验证码程序扎实的JS知识来破解混淆函数爬虫工程师的进阶之路其实就是不断反反爬虫,可谓艰辛,但换个角度想也是乐趣所在关于框架爬虫有自己的编写流程和标准,有了标准,自然就有了框架,像Python这种生态强大的语言,框架自然是多不胜数,目前世面上用的比较多的有:ScrapyPySpiderPortia这里不过多介绍,框架只是工具,是一种提升效率的方式,看你选择说明任何事物都有两面性,爬虫自然也不例外,因此我送诸位一张图,关键时刻好好想想 ...

January 10, 2019 · 1 min · jiezi

Python爬虫——Python 岗位分析报告

前两篇我们分别爬取了糗事百科和妹子图网站,学习了 Requests, Beautiful Soup 的基本使用。不过前两篇都是从静态 HTML 页面中来筛选出我们需要的信息。这一篇我们来学习下如何来获取 Ajax 请求返回的结果。欢迎关注公号【智能制造专栏】学习更多原创智能制造及编程知识。Python 爬虫入门(二)——爬取妹子图 Python 爬虫入门(一)——爬取糗百本篇以拉勾网为例来说明一下如何获取 Ajax 请求内容本文目标获取 Ajax 请求,解析 JSON 中所需字段数据保存到 Excel 中数据保存到 MySQL, 方便分析简单分析五个城市 Python 岗位平均薪资水平Python 岗位要求学历分布Python 行业领域分布Python 公司规模分布查看页面结构我们输入查询条件以 Python 为例,其他条件默认不选,点击查询,就能看到所有 Python 的岗位了,然后我们打开控制台,点击网络标签可以看到如下请求:从响应结果来看,这个请求正是我们需要的内容。后面我们直接请求这个地址就好了。从图中可以看出 result 下面就是各个岗位信息。到这里我们知道了从哪里请求数据,从哪里获取结果。但是 result 列表中只有第一页 15 条数据,其他页面数据怎么获取呢?分析请求参数我们点击参数选项卡,如下:发现提交了三个表单数据,很明显看出来 kd 就是我们搜索的关键词,pn 就是当前页码。first 默认就行了,不用管它。剩下的事情就是构造请求,来下载 30 个页面的数据了。构造请求,并解析数据构造请求很简单,我们还是用 requests 库来搞定。首先我们构造出表单数据 data = {‘first’: ’true’, ‘pn’: page, ‘kd’: lang_name} 之后用 requests 来请求url地址,解析得到的 Json 数据就算大功告成了。由于拉勾对爬虫限制比较严格,我们需要把浏览器中 headers 字段全部加上,而且把爬虫间隔调大一点,我后面设置的为 10-20s,然后就能正常获取数据了。import requestsdef get_json(url, page, lang_name): headers = { ‘Host’: ‘www.lagou.com’, ‘Connection’: ‘keep-alive’, ‘Content-Length’: ‘23’, ‘Origin’: ‘https://www.lagou.com’, ‘X-Anit-Forge-Code’: ‘0’, ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0’, ‘Content-Type’: ‘application/x-www-form-urlencoded; charset=UTF-8’, ‘Accept’: ‘application/json, text/javascript, /; q=0.01’, ‘X-Requested-With’: ‘XMLHttpRequest’, ‘X-Anit-Forge-Token’: ‘None’, ‘Referer’: ‘https://www.lagou.com/jobs/list_python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=', ‘Accept-Encoding’: ‘gzip, deflate, br’, ‘Accept-Language’: ’en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7’ } data = {‘first’: ‘false’, ‘pn’: page, ‘kd’: lang_name} json = requests.post(url, data, headers=headers).json() list_con = json[‘content’][‘positionResult’][‘result’] info_list = [] for i in list_con: info = [] info.append(i.get(‘companyShortName’, ‘无’)) info.append(i.get(‘companyFullName’, ‘无’)) info.append(i.get(‘industryField’, ‘无’)) info.append(i.get(‘companySize’, ‘无’)) info.append(i.get(‘salary’, ‘无’)) info.append(i.get(‘city’, ‘无’)) info.append(i.get(’education’, ‘无’)) info_list.append(info) return info_list获取所有数据了解了如何解析数据,剩下的就是连续请求所有页面了,我们构造一个函数来请求所有 30 页的数据。def main(): lang_name = ‘python’ wb = Workbook() conn = get_conn() for i in [‘北京’, ‘上海’, ‘广州’, ‘深圳’, ‘杭州’]: page = 1 ws1 = wb.active ws1.title = lang_name url = ‘https://www.lagou.com/jobs/positionAjax.json?city={}&needAddtionalResult=false'.format(i) while page < 31: info = get_json(url, page, lang_name) page += 1 import time a = random.randint(10, 20) time.sleep(a) for row in info: insert(conn, tuple(row)) ws1.append(row) conn.close() wb.save(’{}职位信息.xlsx’.format(lang_name))if name == ‘main’: main()完整代码import randomimport timeimport requestsfrom openpyxl import Workbookimport pymysql.cursorsdef get_conn(): ‘‘‘建立数据库连接’’’ conn = pymysql.connect(host=‘localhost’, user=‘root’, password=‘root’, db=‘python’, charset=‘utf8mb4’, cursorclass=pymysql.cursors.DictCursor) return conndef insert(conn, info): ‘‘‘数据写入数据库’’’ with conn.cursor() as cursor: sql = “INSERT INTO python (shortname, fullname, industryfield, companySize, salary, city, education) VALUES (%s, %s, %s, %s, %s, %s, %s)” cursor.execute(sql, info) conn.commit()def get_json(url, page, lang_name): ‘‘‘返回当前页面的信息列表’’’ headers = { ‘Host’: ‘www.lagou.com’, ‘Connection’: ‘keep-alive’, ‘Content-Length’: ‘23’, ‘Origin’: ‘https://www.lagou.com’, ‘X-Anit-Forge-Code’: ‘0’, ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0’, ‘Content-Type’: ‘application/x-www-form-urlencoded; charset=UTF-8’, ‘Accept’: ‘application/json, text/javascript, /; q=0.01’, ‘X-Requested-With’: ‘XMLHttpRequest’, ‘X-Anit-Forge-Token’: ‘None’, ‘Referer’: ‘https://www.lagou.com/jobs/list_python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=', ‘Accept-Encoding’: ‘gzip, deflate, br’, ‘Accept-Language’: ’en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7’ } data = {‘first’: ‘false’, ‘pn’: page, ‘kd’: lang_name} json = requests.post(url, data, headers=headers).json() list_con = json[‘content’][‘positionResult’][‘result’] info_list = [] for i in list_con: info = [] info.append(i.get(‘companyShortName’, ‘无’)) # 公司名 info.append(i.get(‘companyFullName’, ‘无’)) info.append(i.get(‘industryField’, ‘无’)) # 行业领域 info.append(i.get(‘companySize’, ‘无’)) # 公司规模 info.append(i.get(‘salary’, ‘无’)) # 薪资 info.append(i.get(‘city’, ‘无’)) info.append(i.get(’education’, ‘无’)) # 学历 info_list.append(info) return info_list # 返回列表def main(): lang_name = ‘python’ wb = Workbook() # 打开 excel 工作簿 conn = get_conn() # 建立数据库连接 不存数据库 注释此行 for i in [‘北京’, ‘上海’, ‘广州’, ‘深圳’, ‘杭州’]: # 五个城市 page = 1 ws1 = wb.active ws1.title = lang_name url = ‘https://www.lagou.com/jobs/positionAjax.json?city={}&needAddtionalResult=false'.format(i) while page < 31: # 每个城市30页信息 info = get_json(url, page, lang_name) page += 1 time.sleep(random.randint(10, 20)) for row in info: insert(conn, tuple(row)) # 插入数据库,若不想存入 注释此行 ws1.append(row) conn.close() # 关闭数据库连接,不存数据库 注释此行 wb.save(’{}职位信息.xlsx’.format(lang_name))if name == ‘main’: main()GitHub 地址:https://github.com/injetlee/Python/tree/master/%E7%88%AC%E8%99%AB%E9%9B%86%E5%90%88如果你想要爬虫获取的岗位信息,请关注公号【智能制造专栏】后台留言发送 “python岗位”。 ...

September 3, 2018 · 3 min · jiezi