赞
踩
通过一个程序,根据Url进行爬取网页,获取有用信息 使用程序模拟浏览器,去向服务器发送请求,获取响应信息
1.User‐Agent 2.代理IP 3.验证码访问 4.数据加密
5.动态加载网页 网站返回的是js数据 并不是网页的真实数据
import urllib.request url = 'http://baidu.com' response = urllib.request.urlopen(url) #response是HTTPResponse的类型 'print(type(response))' #按字节读 content1 = response.read(5) #按行读 content2 = response.readline() print(content2) content3 = response.readlines() print(content3) #状态码 print(response.getcode()) #地址 print(response.geturl()) #获取状态信息 print(response.getheaders())
import urllib.request
#页面
url_page = 'http://www.baidu.com'
urllib.request.urlretrieve(url_page,'baidu.html')
#图片
url_img = 'https://tse3-mm.cn.bing.net/th/id/OIP-C.mNqPTNrIJLPdTDtgeTE7MAHaLH?w=186&h=279&c=7&r=0&o=5&dpr=1.5&pid=1.7'
urllib.request.urlretrieve(url_img,filename='lisa.jpg')
#视频
url_video = '视频url'
urllib.request.urlretrieve(url_video,'cat.mp4')
import urllib.request url = 'https://cn.bing.com/search?q=%E5%91%A8%E6%9D%B0%E4%BC%A6&form=ANNTH1&refig=9e63813a16cf4a9fb53ed3f604bcb4f4' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } #请求对象定制 urlopen不能存字典 #请求对象的定制 ua反爬 request = urllib.request.Request(url=url,headers = headers) response = urllib.request.urlopen(request) content = response.read().decode('UTF-8') print(content)
import urllib.request import urllib.parse #获取网页源码 url = 'https://www.baidu.com/s?wd=' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } #将周杰伦变成unicod name = urllib.parse.quote('周杰伦') #根据值获取 url = url + name request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('utf-8') print(content)
import urllib.request import urllib.parse base_url = 'https://www.baidu.com/s?' data = { 'wd':'周杰伦', 'sex':'男', 'location':'中国台湾' } new_data = urllib.parse.urlencode(data) url = base_url + new_data headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } request = urllib.request.Request(url = url,headers = headers) response = urllib.request.urlopen(request) content = response.read().decode('utf-8') print(content)
import urllib.request url = 'https://fanyi.baidu.com/sug' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } data = { 'kw':'spider' } #post请求的参数 必须要进行编码 data = urllib.parse.urlencode(data).encode('utf-8') request = urllib.request.Request(url=url,data=data,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('utf-8') import json obj = json.loads(content) print(obj)
总结:post和get区别?
1:get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法
2:post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法
ajax是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。
这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
#下载豆瓣电影前10页数据 #1、请求对象定制 #2、获取响应数据 #3、下载数据 import urllib.parse import urllib.request def creat_request(page): base_url = 'https://movie.douban.com/j/chart/top_list?type=13&interval_id=100%3A90&action=&' data = { 'start':(page-1)*20, 'limit':20 } data = urllib.parse.urlencode(data) url = base_url + data headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } request = urllib.request.Request(url=url,headers=headers) return request def get_content(request): response = urllib.request.urlopen(request) content = response.read().decode('utf-8') return content def down_load(page,content): with open('douban'+ str(page) +'.json','w',encoding='utf-8')as fp: fp.write(content) #入口(可选) if __name__ == '__main__': start_page = int(input('请输入起始页码')) end_page = int(input('请输入结束页码')) for page in range(start_page,end_page+1): #每一页都有自己请求对象的定制 request = creat_request(page) content = get_content(request) #下载 down_load(page,content)
import urllib.request import urllib.parse def create_request(page): base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname' data = { 'cname': '宜昌', 'pid':'', 'pageIndex': page, 'pageSize': '10' } data = urllib.parse.urlencode(data).encode('utf-8') headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36', 'Cookie':'route - cell = ksa;ASP.NET_SessionId = 5lvicybh0c1hvcltu04vpz3m;Hm_lvt_1039f1218e57655b6677f30913227148 = 1682253815;Hm_lpvt_1039f1218e57655b6677f30913227148 = 1682253815;SERVERID = 6ee43946432b1a5105f8c6178eb14f6d | 1682260334 | 1682260068' } request = urllib.request.Request(url=base_url,headers=headers,data=data) def get_content(request): response = urllib.request.urlopen(request) content = response.read().decode('utf-8') return content def down_load(page,content): with open('kfc_'+str(page)+'.json','w',encoding='utf-8')as fp: fp.write(content) if __name__ == '__main__': start_page = int(input('请输入起始页码:')) end_page = int(input('请输入结束页码')) for page in range(start_page,end_page+1): request = create_request(page) content = get_content(request) down_load(page,content)
import urllib.request import urllib.error #url = 'https://blog.csdn.net/weixin_46211269/article/details/126121311' url = 'http://www.goudan1111.com' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36', 'Cookie': 'route - cell = ksa;ASP.NET_SessionId = 5lvicybh0c1hvcltu04vpz3m;Hm_lvt_1039f1218e57655b6677f30913227148 = 1682253815;Hm_lpvt_1039f1218e57655b6677f30913227148 = 1682253815;SERVERID = 6ee43946432b1a5105f8c6178eb14f6d | 1682260334 | 1682260068' } try: request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('utf-8') print(content) except urllib.error.HTTPError: print('系统正在升级') except urllib.error.URLError: print('系统正在升级')
#数据采集时,需要绕过登录,然后进入到某个页面 #个人信息页面是utf-8 但还是报编码错误 因为没有进入到个人页面 而是跳转 #到登录页面 登录页面不是utf-8 import urllib.request url = 'https://weibo.com/u/5398458536' headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('gb2312') print(content) #数据保存 with open('weibo.html','w',encoding='gb2312')as fp: fp.write(content)
定制更高级的请求头(随着业务逻辑的复杂 请求对象的定制已经满足不了我们的需求(动态cookie和代理 不能使用请求对象的定制)
import urllib.request url = 'http://www.baidu.com' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } request = urllib.request.Request(url=url,headers=headers) #handler bulid_open open #获取handler对象 handler = urllib.request.HTTPHandler() #获取opener对象 opener = urllib.request.build_opener(handler) #调用open方法 response = opener.open(request) content = response.read().decode('utf-8') print(content)
代码配置代理
import urllib.request url = 'http://www.baidu.com/s?wd=ip' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } request = urllib.request.Request(url=url,headers=headers) proxies={ 'http':'58.20.184.187:9091' } handler = urllib.request.ProxyHandler(proxies=proxies) opener = urllib.request.build_opener(handler) response = opener.open(request) content = response.read().decode('utf-8') with open('daili.html','w',encoding='utf-8')as fp: fp.write(content)
import urllib.request
proxies_pool = [
{ 'http':'118.24.219.151:16817' },
{ 'http':'118.24.219.151:16111'}
]
#从代理池中随机选择一个
import random
proxies = random.choice(proxies_pool)
#后面用handler包装
xpath 使用 Ctrl + Shlft + x
#xpath解析
#1.本地文件 etree.parse
#2.服务器响应的数据 response.read().decode('utf-8) etree.HTML()
1.路径查询
查找所有子孙节点,不考虑层级关系
找直接子节点
2.谓词查询
div[@id]
div[@id=“maincontent”]
3.属性查询
@class
4.模糊查询
div[contains(@id, “he”)]
div[starts‐with(@id, “he”)]
5.内容查询
div/h1/text()
6.逻辑运算
div[@id=“head” and @class=“s_down”]
title | price
#解析本地文件 tree = etree.parse('070解析xpath基本使用.html') #tree.xpath('xpath路径') #查找ul下的li li_list = tree.xpath('//body/ul/li') #查找所有有id的属性的li标签 #text()获取标签中的内容 li_list = tree.xpath('//ul/li[@id]/text()') #找到id为11的li标签 注意引号 li_list = tree.xpath('//ul/li[@id="11"]/text()') #查找到id为11的li标签的class的属性值 li_list = tree.xpath('//ul/li[@id="11"]/@class') #查找id中包含1的li标签 li_list = tree.xpath('//ul/li[contains(@id,"1")]/text()') #查询id的值以1开头的li标签 li_list = tree.xpath('//ul/li[starts-with(@id,"c")]/text()') #查询id为11和class为c1的 li_list = tree.xpath('//ul/li[@id="11" and @class="c1"]/text()') # li_list = tree.xpath('//ul/li[@id="11"]/text() | //ul/li[@id="12"]/text()') #判断列表长度 print(li_list) print(len(li_list))
#获取网站源码 #解析 解析服务器响应的文件 etree.HTML #打印 import urllib.request url = 'https://www.baidu.com/' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } requests = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(requests) content = response.read().decode('utf-8') #解析网页源码 获取要的数据 from lxml import etree #解析服务器响应文件 tree = etree.HTML(content) #获取想要的数据 xpath的返回值是列表类型的数据 #浏览器可直接复制获取xml result = tree.xpath('//input[@id="su"]/@value')[0] print(result)
#需求 下载前10页图片 #https://sc.chinaz.com/tupian/qinglvtupian.html #https://sc.chinaz.com/tupian/qinglvtupian_2.html import urllib.request from lxml import etree def creat_request(page): if(page == 1): url = 'https://sc.chinaz.com/tupian/qinglvtupian.html' else: url = 'https://sc.chinaz.com/tupian/qinglvtupian_'+str(page)+'.html' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } request =urllib.request.Request(headers=headers,url=url) return request def get_content(request): response = urllib.request.urlopen(request) content = response.read().decode('utf-8') return content def down_load(content): # 下载图片 tree = etree.HTML(content) name_list = tree.xpath('//div[@class="container"]//img/@alt') #一般涉及图片的网站都会进行懒加载 img_list = tree.xpath('//div[@class="container"]//img/@data-original') for i in range(len(name_list)): name = name_list[i] img = img_list[i] url = 'https:' + img # urllib.request.urlretrieve('图片地址','文件名字') urllib.request.urlretrieve(url=url,filename='./loveImg/'+name+'.jpg') # .loveImg为目录名 放在...目录下 if __name__ == '__main__': start_page = int(input("请输入起始页码")) end_page = int(input("请输入结束页码")) for page in range(start_page,end_page+1): #请求对象定制 request = creat_request(page) # 获取网页源码 content = get_content(request) # 下载 down_load(content)
缺点:无法解析服务器响应的数据
案例:
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }
语法:
obj = json.load(open('073解析jsonpath.json','r',encoding='utf-8')) #书店所有书的作者 author_list = jsonpath.jsonpath(obj,'$.store.book[*].author') #所有的作者 author_list = jsonpath.jsonpath(obj,'$..author') #store下的所有元素 tag_list = jsonpath.jsonpath(obj,'$.store.*') #store下所有的price price_list = jsonpath.jsonpath(obj,'$.store..price') #第三个书 book = jsonpath.jsonpath(obj,'$..book[2]') #最后一本书 book = jsonpath.jsonpath(obj,'$..book[(@.length-1)]') #前两本书 book_list = jsonpath.jsonpath(obj,'$..book[0,1]') book_list = jsonpath.jsonpath(obj,'$..book[:2]') #过滤出所有包含isbn的书 条件过滤需要在()前加一个? book_list = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]') #那本书超过10块钱 book_list = jsonpath.jsonpath(obj,'$..book[?(@.price>10)')
import urllib.request url = 'https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1687975134652_108&jsoncallback=jsonp109&action=cityAction&n_s=new&event_submit_doGetAllRegion=true' headers = { 'Cookie':'t=a7d009fb8c7d40083be5844676f3955e; cookie2=14f2996b749e6492ee3a6c304cdf58f0; v=0; _tb_token_=f8514e7636eee; cna=Aa7CHMZlFjsCAXWWBoxRWAzg; xlly_s=1; tb_city=110100; tb_cityName="sbG+qQ=="; tfstk=dugJF7fyJKvkEwApr8KD88y1fndDm4hyZYl1-J2lAxHxQYdzxgmov9ex1QykY3kKDvM4q8gKTwFIOvRzKQ-mabzURdvgJFcraZVVGyF6nFGRS0JMIFYMVsaped0hBJmGjNfNSdT5oA3QNHwZ0_nAGKPz2RGvbw_pv76gBb1dJwgxquBaoV099e6gBWjWMIIFYuNq8_x0_; l=fBE4_1-lN4I9l8kXBO5BFurza77TzIRb81PzaNbMiIEGa6tP9FwyqNC1pheDWdtjgT5xsetrip0J_dFyl-UU-dsWHpfuKtyuJev68eM3N7AN.; isg=BLS04fS1bHu-f_i3iogL2Ff9hXImjdh3ZG1PEk4VnD_CuVUDdpuRBtx3OfFhRhDP', 'Referer':'https://dianying.taobao.com/?spm=a1z21.3046609.city.1.32c0112aTVArVg&city=110100' } request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('utf-8') #切割 json不能有多余的括号 content = content.split('(')[1].split(')')[0] with open('074解析jsonpath淘票票.json','w',encoding='utf-8')as fp: fp.write(content) import json import jsonpath obj = json.load(open('074解析jsonpath淘票票.json','r',encoding='utf-8')) city_list = jsonpath.jsonpath(obj,'$..regionName') print(city_list)
主要功能也是解析和提取数据
缺点:效率没有lxml的效率高
优点:接口设计人性化,使用方便
BeautifulSoup基本用法
from bs4 import BeautifulSoup #解析本地文件 来将bs4的基础语法进行讲解 #默认gbk打开时需要指定编码 soup = BeautifulSoup(open('075解析bs4的基本使用.html',encoding='utf-8'),'lxml') #根据标签名查找节点 #找到的是第一个符合条件的数据 print(soup.a) #获取标签的属性和属性值 print(soup.a.attrs) #bs4的一些函数 #(1)find #返回第一个符合条件的数据 print(soup.find('a')) #根据title值来找到对应的标签对象 print(soup.find('a',title="a2")) #根据class的值来找到对应的标签对象 注意class需要添加下划线 print(soup.find('a',class_="a2")) #(2)find_all 返回的是一个列表 并且返回了所有a的标签 print(soup.find_all('a')) #如果想获取多个标签的数据 那么需要find_all的参数中添加列表的数据 print(soup.find_all(['a','span'])) #limit查找前几个数据 print(soup.find_all('li',limit=2)) #(3)select(推荐) 返回一个列表 并且返回多个数据 print(soup.select('a')) #可以通过.代表class 类选择器 #代表id print(soup.select('.a2')) print(soup.select('#li')) #属性选择器--通过属性寻找对应标签 #查找到li标签中有id的标签 print(soup.select('li[id]')) #查找到li标签中id为l2的标签 print(soup.select('li[id="l2"]')) #层级选择器 # 后代选择器 #找到div下的li print(soup.select('div li')) #子代选择器 # 某标签的第一级子标签 print(soup.select('div > ul > li')) #找到a标签和li标签的所有对象 print(soup.select('a,li')) #节点信息 # 获取节点内容 obj = soup.select('#d1')[0] #如果标签对象中 只有内容 那么string和get_text()都可以使用 #如果标签对象中 除了内容还有标签 那么string获取不到数据 print(obj.string) print(obj.get_text()) #节点的属性 obj = soup.select('#p1')[0] #name是标签的名字 print(obj.name) #将属性值左右一个字典返回 print(obj.attrs) #获取节点属性 obj = soup.select('#p1')[0] print(obj.attrs.get('class')) print(obj.get('class')) print(obj['class'])
import urllib.request
url = 'https://www.starbucks.com.cn/menu/'
response = urllib.request.urlopen(url)
content = response.read().decode('utf-8')
from bs4 import BeautifulSoup
soup = BeautifulSoup(content,'lxml')
#xpath路径://ul[@class="grid padded-3 product"]//strong
name_list = soup.select('ul[class="grid padded-3 product"] strong')
for name in name_list:
print(name.get_text())
模拟浏览器功能,自动执行网页中的js代码,实现动态加载
from selenium import webdriver
#创建浏览器操作对象
path = 'chromedriver.exe'
browser = webdriver.Chrome(path)
#访问网站
url = 'https://www.JD.com'
browser.get(url)
#获取网页源码
content = browser.page_source
print(content)
#根据id找到对象 常用
button = browser.find_element_by_id('su')
#根据标签属性的属性值来获取对象
button = browser.find_element_by_name('wd')
#根据xpath语句来获取对象 常用
button = browser.find_element_by_xpath('//input[@id="su"]')
#根据标签的名字获取对象
button = browser.find_element_by_tag_name('input')
#使用css语法获取对象 常用
button = browser.find_element_by_css_selector('#su')
#根据链接文本获取
button = browser.find_element_by_link_text('新闻')
input = browser.find_element_by_id('su')
#获取标签属性
print(input.get_attribute('class'))
#获取标签名字
print((input.tag_name))
#获取元素文本
a=browser.find_element_by_link_text('新闻')
print(a.text)
#获取文本框对象 input = browser.find_element_by_id('kw') #文本框输入周杰伦 input.send_keys('周杰伦') time.sleep(2) #获取百度一下按钮 button = browser.find_element_by_id('su') #点击按钮 button.click() time.sleep(2) #滑倒底部 js_bottom = 'document.documentElement.scrollTop=100000' browser.execute_script(js_bottom) time.sleep(2) #获取下一页按钮 next = browser.find_element_by_xpath('//a[@class="n"]') next.click() time.sleep(2) #回到上一页 browser.back() time.sleep(2) #回到下一页 browser.forward() time.sleep(3) #退出 browser.quit()
from selenium import webdriver
path = 'phantomjs.exe'
browser = webdriver.PhantomJS(path)
url = 'https://www.baidu.com'
browser.get(url)
封装
#封装的handless
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def share_browser():
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable‐gpu')
# path是你自己chrome浏览器的文件路径
path = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
chrome_options.binary_location = path
browser = webdriver.Chrome(chrome_options=chrome_options)
return browser
封装调用
browser = share_browser()
url = 'https://www.baidu.com'
browser.get(url)
文档:
官方文档 Requests: 让 HTTP 服务人类 — Requests 2.18.1 文档
快速上手 快速上手 — Requests 2.18.1 文档
import requests url = 'http://www.baidu.com' response = requests.get(url=url) #一个类型和六个属性 #Response类型 print(type(response)) #设置响应的编码格式 response.encoding = 'utf-8' #以字符串的形式返回网页源码 print(response.text) #返回一个url地址 print(response.url) #返回二进制数据 print(response.content) #返回响应状态码 print(response.status_code) #返回响应头 print(response.headers)
参数使用params传递
参数无需urlencode编码
不需要请求对象的定制
请求资源路劲中?可以不加
import requests
url = 'http://www.baidu.com/s'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
'Cookie': 'BIDUPSID=D043207FA0BA8EDA6DE237D13B7A2085; PSTM=1679819122; BAIDUID=D043207FA0BA8EDA6B95F9AF636CC568:FG=1; BAIDUID_BFESS=D043207FA0BA8EDA6B95F9AF636CC568:FG=1; ZFY=SRkQXXk5q963dsWp6MbBx:A9BVsfItJEu2v0jm:BIARX0:C; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_PS_PSSID=38515_36561_38470_38468_38375_37936_38387_38356_26350; BA_HECTOR=200k85012hag2kag808h24dm1i3nmlg1n; PSINO=6; delPer=0; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BCLID=8184894944099422743; BCLID_BFESS=8184894944099422743; BDSFRCVID=EKtOJexroG07VWbfMcMcMWLvdFweG7bTDYrEOwXPsp3LGJLVFe3JEG0Pts1-dEu-S2OOogKKLgOTHUCF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; BDSFRCVID_BFESS=EKtOJexroG07VWbfMcMcMWLvdFweG7bTDYrEOwXPsp3LGJLVFe3JEG0Pts1-dEu-S2OOogKKLgOTHUCF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tRAOoC_-tDvDqTrP-trf5DCShUFs0xnJB2Q-XPoO3KtbSx3PbxcjXttI3PvqKU5f5mkf3fbgy4op8P3y0bb2DUA1y4vp0tLeWeTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPb9QgbP5hQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHj8WDj5b3O; H_BDCLCKID_SF_BFESS=tRAOoC_-tDvDqTrP-trf5DCShUFs0xnJB2Q-XPoO3KtbSx3PbxcjXttI3PvqKU5f5mkf3fbgy4op8P3y0bb2DUA1y4vp0tLeWeTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPb9QgbP5hQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHj8WDj5b3O; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1680340062,1681644218; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1681644271; ab_sr=1.0.1_ODQ3MWVjOTRjMmNhZjlmMzdlZGExZDUzNjZjNzBjZjVkOTIwOTE0MTVmNzg2NDVmMWM5YTc1MTQxMWMxYTMyODgzNDhjODQyMzZlNjZiYmE1Mjg2YTBhZGE4NGNhNTVlN2Y4Y2ExNzNkYjBkZjM3MGYxMTIwMDk0NDFkNzBiMzdkZjJiODFkZTlmNWJmMWE4ODQ5ZjE5ZDRjMmJlODRhNQ=='
}
data = {
'wd':'北京'
}
#url请求资源路径 params参数 kwargs字典
response = requests.get(url=url,params=data,headers=headers)
response.encoding = 'utf-8'
content = response.text
print(content)
post请求不需要编解码
post请求参数是data
不需要请求对象的定制
import requests
url = 'https://fanyi.baidu.com/sug'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}
data = {
'kw':'eye'
}
response = requests.post(url=url,data=data,headers=headers)
content = response.text
import json
obj = json.loads(content)
print(obj)
import requests url = 'http://www.baidu.com/s?' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36', } data = { 'wd':'ip' } #代理的ip proxy = { 'http':'60.167.20.156:1133' } response = requests.get(url=url,headers=headers,params=data,proxies=proxy) response.encoding = 'utf-8' content = response.text with open('daili.html','w',encoding='utf-8')as fp: fp.write(content)
#通过登录 进入到主页面 #通过登陆接口发现 登录的时候需要的参数很多 # __VIEWSTATE: CP3QIJUj3fNNIMyAbBfpI+sp27YaeFH9BAe8qKi8JPdvSus4hqUknovahzQOhH5mAC+Z2cQZ8XESxKjvBC19ufH9dBIjEV1ezk3LHvHkiAMKF3NLdZmW86c4D7DDjqiiY4y3/lkVY86V7w09qbcEI97FfcE= # __VIEWSTATEGENERATOR: C93BE1AE # from: http://so.gushiwen.cn/user/collect.aspx # email: 17609092650 # pwd: 122456 # code: ey2l # denglu: 登录 #观察到__VIEWSTATE、__VIEWSTATEGENERATOR、code是变量 #难点(1)隐藏域__VIEWSTATE __VIEWSTATEGENERATOR 一般情况下看不到的数据都在页面源码中 # 观察到两个数据在页面源码 所以需要获取页面源码 然后进行解析就可以获取了 # (2)验证码 import requests #登录页面的url地址 url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' } #获取页面源码 response = requests.get(url=url,headers=headers) content = response.text #解析页面源码 然后获取__VIEWSTATE、__VIEWSTATEGENERATOR from bs4 import BeautifulSoup soup = BeautifulSoup(content,'lxml') #获取__VIEWSTATE viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value') #获取__VIEWSTATEGENERATOR viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value') #获取验证码图片 code = soup.select('#imgCode')[0].attrs.get('src') code_url = 'https://so.gushiwen.cn' + code #requests里有一个方法session()通过session的返回值 就能使用请求变成一个对象 session = requests.session() #验证码的url的内容 response_code = session.get(code_url) #注意此时要用二进制 因为我们要使用的是图片下载 content_code = response_code.content #wb模式将二进制数据写入文件 with open('code.jpg','wb')as fp: fp.write(content_code) #获取验证码图片后 下载到本地 然后观察验证码 输入到控制台 给code就可以登录 code_name = input('请输入你的验证码') #点击登录 url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx' data_post = { '__VIEWSTATE': viewstate, '__VIEWSTATEGENERATOR': viewstategenerator, 'from': 'http://so.gushiwen.cn/user/collect.aspx', 'email': '17609092650', 'pwd': 'abc8891999', 'code': code_name, 'denglu': '登录' } response_post = session.post(url=url,headers=headers,data=data_post) content_post = response_post.text with open('gushiwen.html','w',encoding='utf-8') as fp: fp.write(content_post)
1.创建爬虫项目 scrapy startproject 项目的名字 注意:项目的名字不允许使用数字开头 也不能包含中文 2.创建爬虫文件 (1)要在spiders文件夹中创建爬虫文件 cd 项目名字\项目名字\spiders cd scrapy_baidu_091\scrapy_baidu_091\spiders (2)创建爬虫文件 scrapy genspider 爬虫文件的名字 要爬取网页 eg:scrapy genspider baidu http://www.baidu.com 一般情况下不需要添加http协议 因为start——urls的值是根据 allowed_domains修改的 所以添加了http的话 start_urls 就需要我们手动去修改了 3.运行爬虫代码 settings里的ROBOTSTXT_OBEY = True要注释掉 注释掉就不遵守robots协议了 君子协议 运行爬虫: scrapy crawl 爬虫的名字 eg:scrapy crawl baidu tips:去掉无关日志信息LOG_LEVEL='ERROR' setting里
import scrapy class BaiduSpider(scrapy.Spider): #爬虫的名字 用于运行爬虫的时候 使用的值 name = "baidu" #允许访问的域名 allowed_domains = ["http://baidu.com"] #起始的url地址 第一次要访问的域名 #start_urls 是在allowed_domains的前面添加一个http:// # 在allowed_domains后面加/ start_urls = ["https://baidu.com"] #执行了start_urls之后 执行的方法 方法中response就是返回的那个对象 #相当于 response = urllib.requests.urlopen() # response = response.get() def parse(self, response): #代码 print('我是谁') #tips 如果连接进去无数据就是xpath路径问题
项目名字
项目名字
spiders文件夹(存储的是爬虫文件)
init
自定义的爬虫文件 核心功能文件 ********
init
items 定义数据结构的地方 爬取的数据包含哪些
middleware 中间件 代理
pipelines 管道 用来处理下载的数据
settings 配置文件 robots协议 ua定义等
response.text 获取的是响应的字符串
response.body 获取的是二进制数据
response.xpath 可以直接是xpath方法来解析response中的内容
response.extract( ) 提取seletor对象的data属性值
response.extract_first( ) 提取的seletor列表的第一个数据
Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取 数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。 该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该 终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。 一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。
进入到scrapy shell的终端 直接在windows的终端中输入scrapy shell 域名
scrapy shell www.baidu.com
yield语句
自定义程序
import scrapy from ..items import ScrapyDangdang95Item class DangSpider(scrapy.Spider): name = "dang" allowed_domains = ["category.dangdang.com"] start_urls = ["http://category.dangdang.com/cp01.41.70.01.01.00.html"] #多页爬虫 base_url = 'http://category.dangdang.com/pg' page = 1 def parse(self, response): pass # src= //ul[@id="component_59"]/li//img/@src # alt= //ul[@id="component_59"]/li//img/@alt # price=//ul[@id="component_59"]/li//span[@class="search_now_price"]/text() # 所有的seletor对象 都可以再次调用xpath方法 li_list = response.xpath('//ul[@id="component_59"]/li') for li in li_list: src = li.xpath('.//img/@data-original').extract_first() #第一张没有懒加载 和其他图片的标签属性是不一样的 if src: src = src else: src = li.xpath('.//img/@src').extract_first() name = li.xpath('.//img/@alt').extract_first() price = li.xpath('.//span[@class="search_now_price"]/text()').extract_first() book = ScrapyDangdang95Item(src=src,name=name,price=price) #获取一个book就将book交给pipelines 返回单个对象 yield book #每一页爬取的逻辑全是一样的 我们只需要将执行的那个页的请求再次调用parse方法 if self.page < 100: self.page = self.page + 1 url = self.base_url + str(self.page) + '-cp01.41.70.01.01.00.html' #怎么调用parse方法 #就是scrapy的get请求 #url就是请求地址 callback就是你要执行的那个函数 注意不加() yield scrapy.Request(url=url,callback=self.parse)
items数据结构
import scrapy
class ScrapyDangdang95Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
#通俗的说你要下载的数据都有什么
src = scrapy.Field()
name = scrapy.Field()
price = scrapy.Field()
pipelines管道
#如果想使用管道的话 那么就必须在settings开启 class ScrapyDangdang95Pipeline: #在爬虫文件开始之前就执行的方法 def open_spider(self,spider): self.fp = open('book.json','w',encoding='utf-8') #item就是yield后面的book对象 def process_item(self, item, spider): #以下这种模式不推荐 每传递过来一个对象 就打开一次文件 对文件的 操作过于频繁 #(1)write 方法必须要是一个字符串 而不能是其他对象 # with open('book.json','a',encoding='utf-8') as fp: # fp.write(str(item)) self.fp.write(str(item)) return item #在爬虫文件执行之后 执行的方法 def close_spider(self,spider): self.fp.close() import urllib.request #多条管道同时开启 # (1)定义管道类 # (2)在settings中开启管道 # "scrapy_dangdang_95.pipelines.DangDangDownloadPipeline":400 class DangDangDownloadPipeline: def process_item(self, item, spider): url = 'http:'+ item.get('src') filename = './books/'+str(item.get('name'))+'.jpg' urllib.request.urlretrieve(url=url,filename=filename) return item
import scrapy from ..items import ScrapyMovie99Item class MvSpider(scrapy.Spider): name = "mv" allowed_domains = ["www.dygod.net"] start_urls = ["http://www.dygod.net/html/tv/rihantv/index.html"] # 要第一页的名字 和 第二页的图片 def parse(self, response): a_list = response.xpath('//ul//a[@class="ulink"]') for a in a_list: #获取第一页的name 和 要跳转的链接 name = a.xpath('./text()') href = a.xpath('./@href').extract_first() #第二页的地址是 url = 'https://www.dygod.net/' + href #对第二页链接发起访问 yield scrapy.Request(url=url,callback=self.parse_second,meta={'name':name}) def parse_second(self,response): src = response.xpath('//div[@id="Zoom"]/img/@src').extract_first() #接受到请求的那个meta参数的值 name = response.meta['name'] movie = ScrapyMovie99Item(src=src,name=name) yield movie
CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发 送请求
所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常合适的
日志级别:
CRITICAL:严重错误
ERROR: 一般错误
WARNING: 警告
INFO: 一般信息
DEBUG: 调试信息
默认的日志等级是DEBUG 只要出现了DEBUG或者DEBUG以上等级的日志 那么这些日志将会打印
#指定日志级别
LOG_LEVEL = 'WARING'
#日志文件存储在logdemo.log的文件中
LOG_FILE = 'logdemo.log'
class Tset(scrapy.Spider): name = 'testpost' allowed_domains = ['https://fanyi.baidu.com/sug'] #post请求 没有参数就无意义 #start_urls 和 parse 都没用了 def start_requests(self): url = 'https://fanyi.baidu.com/sug' data = { 'kw':'final' } yield scrapy.FormRequest(url=url,formdata=data, callback=self.parse_second) def parse_second(self,response): content = response.text obj = json.loads(content,encoding='utf-8')
(1)到settings.py中,打开一个选项
DOWNLOADER_MIDDLEWARES = {
'postproject.middlewares.Proxy': 543,
}
(2)到middlewares.py中写代码
def process_request(self, request, spider):
request.meta['proxy'] = 'https://113.68.202.10:9999'
return Non
爬虫环境配置与python基础语法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。