python爬国外网站(python如何开发小软件)
各位老铁们好,相信很多人对python爬国外网站都不是特别的了解,因此呢,今天就来为大家分享下关于python爬国外网站以及python如何开发小软件的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
如何用 Python 爬取需要登录的网站
最近我必须执行一项从一个需要登录的网站上爬取一些网页的操作。它没有我想象中那么简单,因此我决定为它写一个辅助教程。
在本教程中,我们将从我们的bitbucket账户中爬取一个项目列表。
教程中的代码可以从我的Github中找到。
我们将会按照以下步骤进行:
提取登录需要的详细信息
执行站点登录
爬取所需要的数据
在本教程中,我使用了以下包(可以在requirements.txt中找到):
Python
1
2
requests
lxml
步骤一:研究该网站
打开登录页面
进入以下页面“bitbucket.org/account/signin”。你会看到如下图所示的页面(执行注销,以防你已经登录)
仔细研究那些我们需要提取的详细信息,以供登录之用
在这一部分,我们会创建一个字典来保存执行登录的详细信息:
1.右击“Username or email”字段,选择“查看元素”。我们将使用“name”属性为“username”的输入框的值。“username”将会是 key值,我们的用户名/电子邮箱就是对应的 value值(在其他的网站上这些 key值可能是“email”,“ user_name”,“ login”,等等)。
2.右击“Password”字段,选择“查看元素”。在脚本中我们需要使用“name”属性为“password”的输入框的值。“password”将是字典的 key值,我们输入的密码将是对应的 value值(在其他网站key值可能是“userpassword”,“loginpassword”,“pwd”,等等)。
3.在源代码页面中,查找一个名为“csrfmiddlewaretoken”的隐藏输入标签。“csrfmiddlewaretoken”将是 key值,而对应的 value值将是这个隐藏的输入值(在其他网站上这个 value值可能是一个名为“csrftoken”,“authenticationtoken”的隐藏输入值)。列如:“Vy00PE3Ra6aISwKBrPn72SFml00IcUV8”。
最后我们将会得到一个类似这样的字典:
Python
1
2
3
4
5
payload={
"username":"<USER NAME>",
"password":"<PASSWORD>",
"csrfmiddlewaretoken":"<CSRF_TOKEN>"
}
请记住,这是这个网站的一个具体案例。虽然这个登录表单很简单,但其他网站可能需要我们检查浏览器的请求日志,并找到登录步骤中应该使用的相关的 key值和 value值。
步骤2:执行登录网站
对于这个脚本,我们只需要导入如下内容:
Python
1
2
import requests
from lxml import html
首先,我们要创建session对象。这个对象会允许我们保存所有的登录会话请求。
Python
1
session_requests= requests.session()
第二,我们要从该网页上提取在登录时所使用的 csrf标记。在这个例子中,我们使用的是 lxml和 xpath来提取,我们也可以使用正则表达式或者其他的一些方法来提取这些数据。
Python
1
2
3
4
5
login_url="n/?next=/"
result= session_requests.get(login_url)
tree= html.fromstring(result.text)
authenticity_token= list(set(tree.xpath("//input[@name='csrfmiddlewaretoken']/@value")))[0]
**更多关于xpath和lxml的信息可以在这里找到。
接下来,我们要执行登录阶段。在这一阶段,我们发送一个 POST请求给登录的 url。我们使用前面步骤中创建的 payload作为 data。也可以为该请求使用一个标题并在该标题中给这个相同的 url添加一个参照键。
Python
1
2
3
4
5
result= session_requests.post(
login_url,
data= payload,
headers= dict(referer=login_url)
)
步骤三:爬取内容
现在,我们已经登录成功了,我们将从bitbucket dashboard页面上执行真正的爬取操作。
Python
1
2
3
4
5
url='/overview'
result= session_requests.get(
url,
headers= dict(referer= url)
)
为了测试以上内容,我们从 bitbucket dashboard页面上爬取了项目列表。我们将再次使用 xpath来查找目标元素,清除新行中的文本和空格并打印出结果。如果一切都运行 OK,输出结果应该是你 bitbucket账户中的 buckets/ project列表。
Python
1
2
3
4
5
tree= html.fromstring(result.content)
bucket_elems= tree.findall(".//span[@class='repo-name']/")
bucket_names= [bucket.text_content.replace("n","").strip() for bucket in bucket_elems]
print bucket_names
你也可以通过检查从每个请求返回的状态代码来验证这些请求结果。它不会总是能让你知道登录阶段是否是成功的,但是可以用来作为一个验证指标。
例如:
Python
1
2
result.ok#会告诉我们最后一次请求是否成功
result.status_code#会返回给我们最后一次请求的状态
怎么样python爬虫进行此网站爬取
是加密的,解密方法在JS里面可以弄出来。
首先要AES解密,可以【Python:import Crypto.Cipher.AES】包,解密mode是CFB,seed是"userId:"+uid+":seed"的SHA256值,解密的key是seed[0:24],iv是seed[len(seed)-16:]。
如果没有登录,uid就是用的"anyone",这时候的seed是"61581AF471B166682A37EFE6DD40FE4700EE337FEEEF65E2C8F203FCA312AAAB",也就是key为"61581AF471B166682A37EFE6",iv为"C8F203FCA312AAAB"。
解密后文件是压缩过的,解压即可得到一个JSON。这部分解压我没仔细看他的算法,好像是gzip,直接用【Python:import gzip】解压有点出错,可能没用对或者不是这个算法,你在研究一下。第二种投机的方法就是,可以通过【Python:import execjs】直接调用他的pako.js文件的JS的inflate()函数来解压这块。JS代码混淆后看起来是非常难懂的,使用这种做法可以不用太看懂加密的算法,效率当然写Python实现这个解密算法低1点咯。
最后的JSON再用【Python:import demjson】解析,text的value就是文档。
如何用最简单的Python爬虫采集整个网站
在之前的文章中Python实现“维基百科六度分隔理论“之基础爬虫,我们实现了在一个网站上随机地从一个链接到另一个链接,但是,如果我们需要系统地把整个网站按目录分类,或者要搜索网站上的每一个页面,我们该怎么办?我们需要采集整个网站,但是那是一种非常耗费内存资源的过程,尤其是处理大型网站时,比较合适的工具就是用一个数据库来存储采集的资源,之前也说过。下面来说一下怎么做。
网站地图sitemap
网站地图,又称站点地图,它就是一个页面,上面放置了网站上需要搜索引擎抓取的所有页面的链接(注:不是所有页面,一般来说是所有文章链接。大多数人在网站上找不到自己所需要的信息时,可能会将网站地图作为一种补救措施。搜索引擎蜘蛛非常喜欢网站地图。
对于SEO,网站地图的好处:
1.为搜索引擎蜘蛛提供可以浏览整个网站的链接简单的体现出网站的整体框架出来给搜索引擎看;
2.为搜索引擎蜘蛛提供一些链接,指向动态页面或者采用其他方法比较难以到达的页面;
3.作为一种潜在的着陆页面,可以为搜索流量进行优化;
4.如果访问者试图访问网站所在域内并不存在的URL,那么这个访问者就会被转到“无法找到文件”的错误页面,而网站地图可以作为该页面的“准”内容。
数据采集
采集网站数据并不难,但是需要爬虫有足够的深度。我们创建一个爬虫,递归地遍历每个网站,只收集那些网站页面上的数据。一般的比较费时间的网站采集方法从顶级页面开始(一般是网站主页),然后搜索页面上的所有链接,形成列表,再去采集到的这些链接页面,继续采集每个页面的链接形成新的列表,重复执行。
很明显,这是一个复杂度增长很快的过程。加入每个页面有10个链接,网站上有5个页面深度,如果采集整个网站,一共得采集的网页数量是105,即100000个页面。
因为网站的内链有很多都是重复的,所以为了避免重复采集,必须链接去重,在Python中,去重最常用的方法就是使用自带的set集合方法。只有“新”链接才会被采集。看一下代码实例:
from urllib.request import urlopenfrom bs4 import BeautifulSoupimport repages= set()def getLinks(pageurl):globalpageshtml= urlopen(""+ pageurl)soup= BeautifulSoup(html)forlink in soup.findAll("a", href=re.compile("^(/wiki/)")):if'href' in link.attrs:iflink.attrs['href'] not in pages:#这是新页面newPage= link.attrs['href']print(newPage)pages.add(newPage)getLinks(newPage)getLinks("")
原理说明:程序执行时,用函数处理一个空URL,其实就是维基百科的主页,然后遍历首页上每个链接,并检查是否已经在全局变量集合pages里面,如果不在,就打印并添加到pages集合,然后递归处理这个链接。
递归警告:Python默认的递归限制是1000次,因为维基百科的链接浩如烟海,所以这个程序达到递归限制后就会停止。如果你不想让它停止,你可以设置一个递归计数器或者其他方法。
采集整个网站数据
为了有效使用爬虫,在用爬虫的时候我们需要在页面上做一些事情。我们来创建一个爬虫来收集页面标题、正文的第一个段落,以及编辑页面的链接(如果有的话)这些信息。
第一步,我们需要先观察网站上的页面,然后制定采集模式,通过F12(一般情况下)审查元素,即可看到页面组成。
观察维基百科页面,包括词条和非词条页面,比如隐私策略之类的页面,可以得出下面的规则:
所有的标题都是在h1→span标签里,而且页面上只有一个h1标签。
所有的正文文字都在div#bodyContent标签里,如果我们想获取第一段文字,可以用div#mw-content-text→p,除了文件页面,这个规则对所有页面都适用。
编辑链接只出现在词条页面上,如果有编辑链接,都位于li#ca-edit标签的li#ca-edit→span→a里面。
调整一下之前的代码,我们可以建立一个爬虫和数据采集的组合程序,代码如下:
import redef getLinks(pageUrl):global pageshtml= urlopen(""+ pageUrl)soup= BeautifulSoup(html)try:print(soup.h1.get_text())print(soup.find(id="mw-content-text").findAll("p")[0])print(soup.find(id="ca-edit").find("span").find("a").attrs['href'])except AttributeError:print("页面缺少属性")for link in soup.findAll("a", href=re.compile("^(/wiki/)")):if'href' in link.attrs:#这是新页面newPage= link.attrs['href']print("------------------\n"+newPage)
这个for循环和原来的采集程序基本上是一样的,因为不能确定每一页上都有所有类型的数据,所以每个打印语句都是按照数据在页面上出现的可能性从高到低排列的。
数据存储到MySQL
前面已经获取了数据,直接打印出来,查看比较麻烦,所以我们就直接存到MySQL里面吧,这里只存链接没有意义,所以我们就存储页面的标题和内容。前面我有两篇文章已经介绍过如何存储数据到MySQL,数据表是pages,这里直接给出代码:
import reimport datetimeimport randomimport pymysqlconn= pymysql.connect(host='127.0.0.1',port= 3306, user='root', passwd='19930319', db='wiki', charset='utf8mb4')cur= conn.cursor()cur.execute("USE wiki")#随机数种子random.seed(datetime.datetime.now())#数据存储def store(title, content):cur.execute("INSERT INTO pages(title, content)VALUES(\"%s\",\"%s\")",(title, content))cur.connection.commit()def getLinks(articleUrl):html= urlopen(""+ articleUrl)title= soup.find("h1").get_text()content=soup.find("div",{"id":"mw-content-text"}).find("p").get_text()store(title, content)returnsoup.find("div",{"id":"bodyContent"}).findAll("a",href=re.compile("^(/wiki/)((?!:).)*$"))#设置第一页links=getLinks("/wiki/Kevin_Bacon")try:while len(links)>0:newArticle= links[random.randint(0, len(links)-1)].attrs['href']print(newArticle)links= getLinks(newArticle)finally:cur.close()conn.close()
小结
今天主要讲一下Python中遍历采集一个网站的链接,方便下面的学习。
希望通过上面的操作能帮助大家。如果你有什么好的意见,建议,或者有不同的看法,我都希望你留言和我们进行交流、讨论。
OK,本文到此结束,希望对大家有所帮助。