奇巧淫技

jsvmp特点jsvmp有一个最大的特点,就是有一长串字符串._$jsvmprt(...),算法代码的具体细节都在这个一节长字符串里,所有在算法的扣取上就很不友好,本案例采取补环境的方式实现。(glb="undefined"==typeofwindow?global:window)._$jsvmprt(.....)逻辑分析定位加密入口添加XHR断点,然后向下滑动,断点短住搜索_signature,在关键位置下断点,然后在刷新页面断点位置r变量,来自于S(n,e)函数计算,该S函数就是入口函数分析加密得值逻辑进入S函数,分析这一段逻辑,其实调用的就是//o是{'url':'xxxx'}window.byted_acrawler.sign(o)进入window.byted_acrawler.sign函数,来到acrawler.js文件,也就是jsvmp的Js文件补环境把acrawler.js文件全部复制下来,代码起始有一句(varglb;glb="undefined"==typeofwindow?global:window),这是检查当前是什么环境的,是node还是浏览器有两种处理办法使用jsdom补充window使用window=global当然还有其他更好的方式,这里采用第二次这样就和浏览器一样了加上一个输出,尝试使用node,浏览器执行,查看两者的区别浏览器正常得值,node报错,说明node缺少一些条件在浏览器添加条件断点,查看referrer是什么//referrer来自于document,继续添加环境document={referrer:''}node继续执行,发现没有sign,说明node还被检查着经过分析,发现这些代码,exports、module,这是node才存在的东西,直接改成undefined当然也有更好的方式直接过滤这些特征//nodetrue浏览器false"undefined"!=typeofexports//nodetrue浏览器false"undefined"!=typeofmodule继续执行,缺少href,就根据浏览器的插装输出补充就好了然后是缺少‘protocol’location={href:'',protocol:'https:'}然后是缺少userAgentnavigator={userAgent:'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/86.0.4240.198Safari/537.36'}再次执行,出现结果因为校验的不严格,所以这个短Cookie也是可以过的,长Cookie需要添加一些Cookie才行长Cookie需要加上其他的Cookie,这个cookie位置需要靠后,不然会被清空如果是自己写的环境框架,就不需要担心cookie的位置为了稳定,请求头部还需要带一个随机Cookie完整结构

编程杂谈

爬虫目标爬虫字段:职位名称、职位URL、职位要求(逗号分隔csv文件)完整代码:https://github.com/bigdataboy2020/job51_spider爬虫结构分层结构模块化结构,减少耦合使用模块:gevent、lxml、typing、requests项目说明操作类(job51.py)主要包含发送请求的方法defget_data():请求获取一页所有的职位名称和职位的URLdefget_job_explain():获取一个职业的要求classJob51(object):#总页数。第一次获取会设置真实页数all_page=9999#正在获取的页数page_num=1#Job_name和url列表job_url_data:List[Tuple[str,str]]=list()#职位详情页列表[name,url,说明]job_explain:Tuple[str,str,List[str]]=Nonesession=requests.session()defget_data(self,page_num:str,city:List[str],search:str)->bool:"""#获取该关键词所有的职位名称与链接:parampage_num:当前页数:paramcity:城市列表:paramsearch:搜索词:return:"""returnTruedefget_job_explain(self,job_name:str,url:str)->bool:"""#获取一个职业的要求:paramjob_name:职位名称:paramurl:职位的详情页:return:"""returnTrue中间处理函数(handle.py)主要包含对请求的数据进行处理的函数及相应错误提示defget_data():获取所有页数的职位名称及职位URLdefget_job_explain():获取单个职位的详细信息msg={1:"获取成功",-1:"获取职位链接获取失败",-2:"获取职位详情失败"}classHandle(object):job=Job51()job_num=0#job总个数job_explain:Tuple[str,str,List[str]]=None#Job_name和url列表job_url_data:List[Tuple[str,str]]=list()def__init__(self,city:List[str],search:str):self.get_data(city,search)defget_data(self,city:List[str],search:str):"""#获取所有页数的职位名称及URL:paramcity:城市列表:paramsearch:搜索词:return:"""#获取职位详情链接whileself.job.page_num<=self.job.all_page:ifnotself.job.get_data(str(self.job.page_num),city,search):return-1self.job.page_num+=1#总Job个数self.job_num=self.job.job_url_data.__len__()self.job_url_data=self.job.job_url_datadefget_job_explain(self,job_name:str,job_url:str):"""#获取单个职位的详细信息:paramjob_name:城市名称:paramjob_url:城市url:return:"""job_url_data=self.job.job_url_dataself.job_len=job_url_data.__len__()ifnotself.job.get_job_explain(job_name,job_url):return-2self.job_explain=self.job.job_explainreturn1工具类模块(utils.py)只有一个写入结果的函数#文件写入deflog(msg:Tuple[str,str,List[str]]):withopen("msg.csv","a",encoding="utf-8")asf:f.write(f"{msg[0]},{msg[1]},{msg[2]}\n")主文件(main.py)主要启动文件,协程在这支持

编程杂谈

爬取难点HTML的canvas标签生成的图片,使用平常获取图片URL下载是行不通的。说明爬虫完整代码https://pan.bigdataboy.cn/#/s/wjHw网站csTimer-魔方竞速训练专用计时器爬取内容模仿公式公式对应的canvas图片工具选取Pythonselenium开始爬取爬取canvas的思路是执行canvas.toDataURL("image/png")方法获取图片的base64编码,再转码为bytes,然后保存在本地构造主类classMain:#图片保存路径IMG_PATH="./img/"#公式保存文件FILE="a.txt"#保存公式的个数COUNT=5000#保存速度SPEED=0.1#None:无限制。支持浮点数def__init__(self):#TODO打开网站defsave(self,i):#TODO保存公式及图片defrun(self):#TODO运行类构造类方法def__init__(self):options=ChromeOptions()options.add_experimental_option('excludeSwitches',['enable-automation'])#隐藏自动化测试#options.add_argument("--headless")#注释掉,就无需打开浏览器窗口#加载网站self.bro=webdriver.Chrome(executable_path="./chromedriver_win32/chromedriver.exe",options=options)self.bro.get(url="https://www.cstimer.net/")#检查网页是否加载完成WebDriverWait(self.bro,60).until(EC.presence_of_element_located((By.XPATH,'//div[@id="leftbar"]/div[@class="mybuttonc6"]/div/span[2]')))#判断图片框是否显示ifnotself.bro.find_element_by_id('toolsDiv').is_displayed():#点击显示图片self.bro.find_element_by_xpath('//div[@id="leftbar"]/div[@class="mybuttonc6"]/div/span[2]').click()保存类方法defsave(self,i):#保存公式formula=self.bro.find_element_by_xpath('//div[@id="scrambleTxt"]/div').textwithopen(self.FILE,mode='a+',encoding="UTF-8")asf:text=f"{formula}----{i}\n"logger.info(text)f.write(text)#保存图片JS='returndocument.getElementById("toolsDiv").childNodes[0].childNodes[0].childNodes[0].toDataURL("image/png");'img_base64=self.bro.execute_script(JS).split(',')[1]#执行js文件得到带图片的base64编码img_bytes=base64.b64decode(img_base64)#转为bytes类型path=f"{self.IMG_PATH}{i}.png"logger.info(path)withopen(path,'wb')asf:#保存图片到本地f.write(img_bytes)运行类方法defrun(self):i=1whileself.COUNT>=i:self.bro.find_element_by_xpath('//div[@class="title"]/nobr[2]/span[2]').click()self.save(i)ifself.SPEED:sleep(self.SPEED)logger.info(f"延迟:{str(self.SPEED)}中....")i+=1logger.info(f"爬取完成")使用if__name__=='__main__':mian=Main()mian.run()

编程杂谈

说明主要使用语言&框架:Python&Scrapy源码地址:https://pan.bigdataboy.cn/#/s/6euy爬取思路第一次搜索:获得所有页数url(简化)'https://search.jd.com/Search?keyword={}'methodGETheaders{'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/84.0.4147.105Safari/537.36'}直接请求商品接口,获取商品id&价格url(简化)'https://search.jd.com/s_new.php?keyword={搜索词}&page={页数}&s={分页数}'methodGETheaders{'referer':'https://search.jd.com/Search'}使用商品id,请求商品页面,获得相关信息urlhttps://item.jd.com/{商品id}.htmlmethodGET请求评论接口,获取评论相关数量url)'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={商品id}methodGETheaders{'referer':'https://search.jd.com/Search'}编写爬虫常规设置创建工程&爬虫文件scrapystartprojectjdAppcdjdAppscrapygenspiderjdspiderjd.com修改setting.py文件#伪装#Crawlresponsiblybyidentifyingyourself(andyourwebsite)ontheuser-agentUSER_AGENT='Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/689.36(KHTML,likeGecko)Chrome/99.0.5204.108Safari/637.75'#Obeyrobots.txtrulesROBOTSTXT_OBEY=False#下载延迟DOWNLOAD_DELAY=1#Overridethedefaultrequestheaders:DEFAULT_REQUEST_HEADERS={'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language':'en','referer':'https://search.jd.com/Search',#京东会检测这个}总体架构classJdspiderSpider(scrapy.Spider):name='jdspider'allowed_domains=['jd.com']#爬取的商品good_name=""#第一次请求获取全部商品全部页数search_url='https://search.jd.com/Search?keyword={}'#第一次搜索接口headers={'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/84.0.4147.105Safari/537.36'}#获取商品接口每次请求返回30个goods_url_api='https://search.jd.com/s_new.php?keyword={}&page={}&s={}'#搜索接口#获取页数请求每一页defstart_requests(self):pass#获取每一个商品id,请求商品详情数据defparse(self,response:Response):pass#获取商品详情数据,请求评论信息defget_infor(self,response:Response):pass#得到评论信息,返回itemdefget_comment(self,response:Response):passif__name__=='__main__':#启动fromscrapyimportcmdlinecmdline.execute("scrapyrunspiderjdspider.py".split())start_requests(self)#获取页数请求每一页defstart_requests(self):self.good_name=input("输入爬取的关键词:")r=requests.get(url=self.search_url.format(self.good_name),headers=self.headers)#获取总页数all_pages=re.search(r'<b>1</b><em>/</em><i>(\d*?)</i>',r.text).group(1)logger.info(msg=f"总页数{all_pages}")for_inrange(int(all_pages)*2):#组合每一页的链接goods_url_api=self.goods_url_api.format(self.good_name,_+1,1+25*(_+1-1))logger.info(msg=f"请求链接:{goods_url_api}")#请求每一页的商品yieldRequest(url=goods_url_api,callback=self.parse)parse(self,response:Response)#获取每一个商品id,请求商品详情数据defparse(self,response:Response):item=JdappItem()drug_list:list[Selector]=response.xpath("//div[@id='J_goodsList']/ul/li")for_indrug_list:#商品价格item['good_price']=_.xpath('//div[@class="p-price"]/strong/i/text()').get()#商品iditem['good_id']=_.xpath("@data-sku").get()url=f'https://item.jd.com/{item["good_id"]}.html'logger.info(msg=f"正在爬取商品详情:{url}")yieldRequest(url=url,meta={'item':copy.deepcopy(item),'url':url},callback=self.get_infor,)get_infor(self,response:Response)#获取商品详情数据,请求评论信息defget_infor(self,response:Response):item=response.meta['item']#商品连接item['good_url']=response.urlinfor=dict()#商品介绍parameter:list[str]=response.xpath('//div[@class="p-parameter"]/ul[2]/li/text()').getall()for_inparameter:i=_.split(":")infor[i[0]]=i[1]#规格与包装size_packing_key:list[str]=response.xpath('//div[@class="Ptable"]/div/dl/dl/dt/text()').getall()size_packing_value:list[str]=response.xpath('//div[@class="Ptable"]/div/dl/dl/dd/text()').getall()for_inzip(size_packing_key,size_packing_value):infor[_[0]]=_[1]logger.info(msg=f"商品参数规格信息{infor}")#商品信息item['good_infor']=infor#获取评论url=f'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={item["good_id"]}'logger.info(msg=f"正在爬取商品评论{url}")yieldRequest(url=url,meta={'item':copy.deepcopy(item)},callback=self.get_comment,dont_filter=True)get_comment(self,response:Response)#得到评论信息,返回itemdefget_comment(self,response:Response):item=response.meta['item']comment=json.loads(response.text)#评论数item['comment_number']=comment.get('CommentsCount')[0].get('CommentCountStr')#好评item['good_comment']=comment.get('CommentsCount')[0].get('GoodCountStr')#中评item['medium_comment']=comment.get('CommentsCount')[0].get('GeneralCountStr')#差评item['bad_comment']=comment.get('CommentsCount')[0].get('PoorCountStr')yielditemtip在爬取商品详情页时,需要经常更换IP,不要容易什么都获取不到,源码里的动态转发需要更改为自己的秘钥和订单注意每个Request请求meta的传递方式

编程杂谈

说明项目完整代码:https://pan.bigdataboy.cn/#/s/ZjSy爬虫难点可以发现所需要提交的参数是被加密的(虽然这段加密结果每次都不一样,可以重复使用,但这不是我们的目的,我们并不仅限于一个歌单)开始分析定位Js加密函数位置搜索,分析加密参数所在的Js文件定位加密函数所在位置分析加密参数定位到了加密参数所在的位置,就需要分析传入的参数通过多次抓包,发现这三个参数都是定值bqN1x(["流泪","强"])->010001bqN1x(["爱心","女孩","惊恐","大笑"])->0CoJUm6Qyw8W8judbqN1x(Wx4B.md)->00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7继续查看传入的第一个参数,找到真正的参数列表{csrf_token:"",cursor:"-1",offset:"0",orderType:"1",pageNo:pageNo,pageSize:pageSize,rid:"A_PL_0_"+rid,threadId:"A_PL_0_"+rid,}分析加密函数进入加密函数内部查看分析发现:需要的参数列表被加密进了变量params,所以有个取巧(不用管变量encSecKey,把他当做一个常量)实现加密过程到了这里差不多就了解了大概的加密过程,所以我就需要选着实现加密过程的方式,这里有两种方式可供查考使用Python重写加密过程(加密简单还能实现,费时费力)使用Python执行Js代码,得到加密结果(比较推荐)这里使用execjs(注意安装的时候是pyexecjs),它会自动调动本机的Js环境执行代码(本机已安装node.js。如果Js加密代码里使用了windows对象,document对象获取参数…就需要选择其他能够调用浏览器驱动的类库)构建加密Js文件先把主要调用的Js代码复制出来使用execjs执行这段Js代码importexecjs#读取Js文件js=open('music.163.js','r',encoding="utf-8").read()#预编译Js文件ext=execjs.compile(js)#执行Js函数result=ext.call('start')print(result)说明所复制的Js代码不够完整,所以就需要继续去找,然后添加到Js文件里。执行加密Js代码importrequestsimportexecjsurl='https://music.163.com/weapi/comment/resource/comments/get?csrf_token='headers={'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/84.0.4147.105Safari/537.36',}#读取Js文件js=open('music.163.js','r',encoding="utf-8").read()#预编译Js文件&执行Js函数result=execjs.compile(js).call('start','3130270730')data={'params':result['encText'],'encSecKey':result['encSecKey']}#发送请求r=requests.post(url=url,headers=headers,data=data)print(r.json())print(r)彩蛋:网易音乐的大部分接口都是这个加密方式,只是提交的参数列表不一样

未分类

爬虫目标博主在假期遇到有家长,拿着老师的布置的作业来打印,结果是如下这样的电子书,还不能下载,所以打算编写爬虫进行下载,发现有书籍的链接全都通过Js加密了,这不能忍,这么能阻止小学生做作业呢。网站:https://mp.zhizhuma.com/book/shelf.htm?id=4872所用模块:#-*-coding:utf-8-*-importrequestsimporttimeimportreimportrandomimportbase64importjsonimporthashlibfromCrypto.CipherimportAESfromosimportmakedirs爬虫结构#获取数据每一页的链接的Jsondefget_encryptedData(ebookId):pass#获取真正的连接,有时效defget_auth_key(data,differenceDate):#下载保存连接defdownload_and_save(datadict,differenceDate):if__name__=='__main__':#书籍的分享链接share_url='https://mp.zhizhuma.com/book/sample2.htm?id=52753&shelfId=4872'ebookId=re.search(r'id=(\d+)',share_url).group(1)#获取书籍的URLencryptedData=get_encryptedData(ebookId)#获取时间戳参数differenceDate=encryptedData.get('timestamp')#创建文件夹makedirs(str(differenceDate))fordatainencryptedData.get('data'):#获取加密的连接pageNo_url=get_auth_key(data=data,differenceDate=differenceDate)print(pageNo_url)#下载书籍download_and_save(pageNo_url,differenceDate=differenceDate)get_encryptedData()通过Js分析,发现这段Js的解密,我们使用Python来实现,逻辑并不复杂。defget_encryptedData(ebookId):url='https://biz.zhizhuma.com/ebookpageservices/queryAllPageByEbookId.do'data={"ebookId":ebookId,"_timestamp":"1586101527","_nonce":"24430072-41ad-48cb-9c7f-880f990c0886","_sign":"975F1339ED050BB789CD51D66E40DD6B",}j=requests.post(url=url,data=data).json().get('encryptedData')#AES解密密钥Js寻找cipher=AES.new("Suj4XDDt3jPsH9Jj".encode(),AES.MODE_ECB)raw_data=cipher.decrypt(base64.decodebytes(bytes(j,encoding='utf8'))).rstrip(b'\x0f').decode("utf-8")[:-1]j_data=json.loads(raw_data)returnj_dataget_auth_key()拼接图片链接后的参数,不带这个参数,获取不到图片auth_key参数的生成,也是模仿Js的来写就好。#获取真正的连接,有时效defget_auth_key(data,differenceDate):#页数pageNo=data.get('pageNo')#解密构造参数imgurl=data.get('imgurl').split('https://cdnyuntisyspro.bookln.cn')[1]uid="0"rand=str(random.random())timestamp=str(int(time.time())-int((int(time.time()*1000)-differenceDate)/1000)+15)sstring=imgurl+"-"+timestamp+"-"+rand+"-"+uid+"-69731cbade6a64b58d60"md5=hashlib.md5()md5.update(sstring.encode())md5hash=md5.hexdigest()authKey='auth_key='+timestamp+"-"+rand+"-"+uid+"-"+md5hashurl="https://cdnyuntisyspro.bookln.cn"+imgurl+"?"+authKeyreturn{"pageNo":pageNo,"url":url}download_and_save()#下载保存defdownload_and_save(datadict,differenceDate):c=requests.get(url=datadict.get('url')).contentwithopen(str(differenceDate)+"/"+str(datadict.get('pageNo'))+".png","wb")asfile:file.write(c)运行可以很容易扩展成多线程。大数据男孩原创,仅用于交流学习之用

未分类

爬虫目标通过抖音的分享链接,获取抖音的原视频(无水印)使用模块:requests、re爬虫结构主要为了最后获取视频时所要的参数classDYSpider():def__init__(self,share_url):#get获取3个参数item_idsmidu_codeself.share_url=share_urlself.item_ids=""self.mid=""self.u_code=""#get获取参数dytk后面大括号需要item_idsself.dytk_url="https://www.iesdouyin.com/share/video/{}/"self.dytk=""#获取信息接口getself.infor_url="https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/"self.headers={"user-agent":"Mozilla/5.0(iPhone;CPUiPhoneOS11_0likeMacOSX)AppleWebKit/604.1.38(KHTML,likeGecko)Version/11.0Mobile/15A372Safari/604.1",}defget_imu(self):passdefget_dytk(self):passdefget_infor(self):passdefrun(self):passget_imu()获取item_idsmidu_code三个参数defget_imu(self):r=requests.get(url=self.share_url)dytk_data=r.urlself.item_ids=re.search(r'video/(.+?)/',dytk_data).group(1)self.mid=re.search(r'mid=(.+?)&',dytk_data).group(1)self.u_code=re.search(r'u_code=(.+?)&',dytk_data).group(1)get_dytk()为了获取dytk参数defget_dytk(self):url=self.dytk_url.format(self.item_ids)r=requests.get(url=url,headers=self.headers,params={"region":"CN","mid":self.mid,"u_code":self.u_code,"titleType":"title","utm_source":"copy_link","utm_campaign":"client_share","utm_medium":"android","app":"aweme",})self.dytk=re.search(r'dytk:"(.+?)"}\);',r.text)get_infor()没有对返回的json进行处理defget_infor(self):r=requests.get(url=self.infor_url,headers=self.headers,params={"item_ids":self.item_ids,"dytk":self.dytk,})print(r.json())运行方法defrun(self):self.get_imu()self.get_dytk()self.get_infor()使用dys=DYSpider("https://v.douyin.com/Wf6Rsa/")dys.run()

未分类

爬虫目标通过微博话题获取发帖的信息与用户基本信息,数据可用于该话题的用户分析。爬取字段:账号id号、昵称、关注数、粉丝数、微博数、个性签名、账号类型、等级、简介、使用设备所用到模块:requests、lxml、re说明:无登录爬取微博用户数据,实现自动获取Cookie和Cookie失效自动更新,还有其他技巧,自己看。爬虫结构classWeiBoSpider():def__init__(self):#起始地址self.url="https://s.weibo.com/weibo?q=%23%E8%94%A1%E5%BE%90%E5%9D%A4%E7%82%B9%E8%AF%84%23&Refer=top"#cookieself.cookie=self.get_cookie()#获取所有数据defget_data(self):pass#通过id获取用户信息defget_user_data(self,user_id):pass#获取&更新Cookiedefget_cookie(self):passif__name__=='__main__':wbs=WeiBoSpider()wbs.get_data()获取所有数据defget_data(self):r=requests.get(url=self.url)html=etree.HTML(r.text)#接信息网页userdatas_list=html.xpath('//div[@id="pl_feedlist_index"]/div/div[@action-type="feed_list_item"]')#获取数据users_list=list()foruserdatainuserdatas_list:#昵称nick_name=userdata.xpath('.//div[@class="info"]/div[2]/a/@nick-name')#个人页user_id=re.search(r'/(\d*?)\?',userdata.xpath('.//div[@class="info"]/div[2]/a[1]/@href')[0]).group(1)#账号类型user_type=userdata.xpath('.//div[@class="info"]/div[2]/a[2]/@title')#使用设备equipment=userdata.xpath('.//p[@class="from"]/a[2]/text()')#组合数据data={"nick_name":nick_name,"user_id":user_id,"user_type":user_type,"equipment":equipment,#调用函数获取用户信息"user_data":self.get_user_data(user_id),}print(data)users_list.append(data)returnusers_list通过ID用户信息获取用户信息时,就对Cookie有着严格的要求,但是我们实现了自动化获取Cookie。defget_user_data(self,user_id="2803301701"):user_url="https://weibo.com/u/{}".format(user_id)headers={"Content-Type":"text/html;charset=utf-8","Host":"weibo.com",}r=requests.get(url=user_url,headers=headers,cookies=self.cookie)#判断cookie的有效性ifr.text=="":r=requests.get(url=user_url,headers=headers,cookies=self.get_cookie())#个人签名try:user_sign=re.search(r"简介:(.*?)<\\/span>",r.text).group(1).replace("\\t","").strip()exceptAttributeError:user_sign=""#关注concern=re.search(r'">(\d*?)<\\/strong><spanclass=\\"S_txt2\\">关注',r.text).group(1)#粉丝fans=re.search(r'">(\d*?)<\\/strong><spanclass=\\"S_txt2\\">粉丝<\\/span>',r.text).group(1)#微博数量weibo_count=re.search(r'">(\d*?)<\\/strong><spanclass=\\"S_txt2\\">微博',r.text).group(1)return{"user_sign":user_sign,"concern":concern,"fans":fans,"weibo_count":weibo_count}Cookie获取&更新在爬取微博用户数据遇到困难的朋友可以参考以下。defget_cookie(self):s=requests.session()#获取第一个Cookies.get("https://passport.weibo.com/visitor/visitor")#获取tid参数tid_=s.post(url="https://passport.weibo.com/visitor/genvisitor",data={"cb":"gen_callback","fp":{}})tid=re.search(r'{"tid":"(.+?)"',tid_.text).group(1)#返回需要的所有Cookier=s.get(url="https://passport.weibo.com/visitor/visitor",params={"a":"incarnate","t":tid,"cb":"cross_domain",})cookies=r.cookiestry:cookies["SRT"]exceptKeyError:print("获取cookie失败,真正重新获取")returnself.get_cookie()else:self.cookie=cookiesprint(self.cookie)returncookies运行结果暂没有翻页功能,看后面补充吧!!!

未分类

爬虫目标爬取房天下指定地区的所在小区、小区链接、小区地址、户型、总价、单价等使用的模块:requests、lxml、re、json爬虫结构以下结构可以很好的进行多线程或者协程的扩展。参数类classTool():#需要爬取的城市city="成都"#爬取页数page=2#城市列表获取所以城市的URL的方法在文末,这里只截取了一部分city_url={'成都':'https://cd.esf.fang.com','郴州':'https://chenzhou.esf.fang.com'}解析网页获取信息#获取房子的信息defget_fang_infor(url):#信息fang_list=list()#获取网页信息r=requests.get(url=url)r.encoding=r.apparent_encoding#这里的错误处理是在爬取第二页之后,URL需要获取一个参数try:href=re.search(r'//location.href="(.*?)";',r.text).group(1)exceptAttributeError:passelse:r=requests.get(url=href)r.encoding=r.apparent_encoding#解析网页html=etree.HTML(r.text)dl_html=html.xpath('//div[@class="shop_listshop_list_4"]/dl')fordlindl_html:#小区名称house=dl.xpath('.//p[@class="add_shop"]/a/@title')ifhouse==list():continue#小区链接house_url=url+dl.xpath('.//p[@class="add_shop"]/a/@href')[0]#小区地址house_add=dl.xpath('.//p[@class="add_shop"]/span/text()')#户型等去除前后符号house_types=[a.strip()foraindl.xpath('.//p[@class="tel_shop"]/text()')]#总价all_price=dl.xpath('.//dd[@class="price_right"]/span[1]/b/text()')[0]+dl.xpath('.//dd[@class="price_right"]/span/text()')[0]#单价price=dl.xpath('.//dd[@class="price_right"]/span[2]/text()')#组合数据infor={#小区名称"house":house[0],#小区地址"house_add":house_add[0],#小区链接"house_url":house_url,#户型"house_type":house_types[0],#大小"house_size":house_types[1][:-2],#楼层"floor":house_types[2],#方向"direction":house_types[3],#修建日期"xj_date":house_types[4],#总价"all_price":all_price,#单价"price":price[0][:-3]}fang_list.append(infor)returnfang_list获取所有链接返回一个所有链接的list()#获取页数连接defget_pages():url=Tool.city_url[Tool.city]pages_list=[url]fornuminrange(2,Tool.page+1):pages_list.append(url+"/house/i3{}/".format(num))returnpages_list主程序入口if__name__=='__main__':pages_list=get_pages()print(pages_list)#打印链接列表forpageinpages_list:print(page)#当前爬取的链接fang_list=get_fang_infor(page)print(fang_list)获取所有城市的URLdefget_city_url():url="https://esf.fang.com/esfcities.aspx"r=requests.get(url=url,timeout=5)r.encoding=r.apparent_encoding#匹配城市&urlcity_url_lists=json.loads(re.search(r"varcityJson=(.*?),];",r.text).group(1)+"]")#重新组合格式city_url_dic=dict()#{,...}foraincity_url_lists:city_url_dic={**city_url_dic,**{a.get("name"):"https:"+a.get("url")}}print(city_url_dic)